Инструменты и утилиты

AutoHotkey v2: практичные скрипты для разработчика

AutoHotkey v2: практичные скрипты для разработчика

AutoHotkey — это, пожалуй, самый недооценённый инструмент в арсенале Windows-разработчика. Пара строк кода — и у вас есть текстовые сниппеты, которые разворачиваются на лету, горячие клавиши для управления окнами, шаблоны кода по нажатию двух символов и быстрый запуск любых инструментов. Долгое время скрипты писались на AutoHotkey v1 — языке с причудливым синтаксисом, который копился годами. В декабре 2022 года официальной стала версия v2, и это полноценный редизайн языка. В этой статье разберём, что реально изменилось при переходе с v1 на v2, и соберём 4–5 готовых к работе скриптов, которые можно сразу бросить в свой autostart.ahk.

Что изменилось в v2 относительно v1

AutoHotkey v2 — это не косметика, а переписанный с нуля язык. Старые скрипты v1 в большинстве своём в v2 не работают без правок. Если коротко, разработчики навели порядок в трёх областях: синтаксис команд, выражения и объекты.

Команды стали функциями

В v1 был дуализм: «командный» синтаксис (MsgBox, Привет) и «функциональный». Это путало: запятые, проценты для подстановки переменных, разные правила экранирования. В v2 командного синтаксиса больше нет — всё это обычные вызовы функций со скобками и кавычками для строк.

; v1
MsgBox, Привет, %name%

; v2
MsgBox("Привет, " name)

Выражения и строки

В v2 нет «голых» переменных в подстановке через проценты. Строки всегда в кавычках, переменные — без них, конкатенация — через точку или просто пробел. Сравнение и присваивание чётко разделены: := для присваивания, = и == для сравнения. Появился чистый тернарный оператор, оператор «ленивого» присваивания ??= и слияние через ??. Объявление переменных стало строже: обращение к необъявленной переменной — это ошибка времени выполнения, что ловит опечатки на корню.

Полноценные объекты

Главное достижение v2 — нормальная объектная модель. Появились настоящие классы (class), массивы (Array, индексация с 1) и ассоциативные массивы (Map) как отдельные типы. В v1 «объект» был и массивом, и словарём одновременно, что порождало неоднозначности. Теперь [1, 2, 3] — это Array, а Map("ключ", "значение") — это Map. Циклы по ним делаются через for:

tools := Map(
    "code", "C:\Users\me\AppData\Local\Programs\Microsoft VS Code\Code.exe",
    "term", "wt.exe"
)
for name, path in tools
    MsgBox(name " => " path)

Ещё пара важных мелочей: горячие клавиши и хоткстринги теперь могут иметь тело в фигурных скобках (как функция), а #Requires AutoHotkey v2.0 в начале файла гарантирует, что скрипт не запустится случайно под v1.

Скрипт 1. Текстовые сниппеты (hotstrings)

Hotstrings — это автозамена: вы печатаете короткую аббревиатуру, и AutoHotkey подменяет её на полный текст. Незаменимо для email, шаблонных фраз, текущей даты и часто набираемых конструкций. Синтаксис в v2 тот же, что и в v1: двоеточия, аббревиатура, двоеточие, замена.

#Requires AutoHotkey v2.0

::eml::me@example.com
::adr::ул. Примерная, 12, Киев

; Многострочный сниппет — флаг "c" для разбора и continuation section
::sig::
(
С уважением,
Иван Разработчик
GitHub: github.com/example
)

; Текущая дата в формате ГГГГ-ММ-ДД через выполнение кода (флаг X)
:X:dt::SendText(FormatTime(, "yyyy-MM-dd"))
:X:now::SendText(FormatTime(, "yyyy-MM-dd HH:mm"))

Флаг X означает «execute»: вместо подстановки текста выполняется функция. FormatTime без первого аргумента берёт текущее время. SendText отправляет строку как есть, не интерпретируя спецсимволы вроде { или ! — для вставки готового текста это всегда правильный выбор.

Скрипт 2. Горячие клавиши для управления окнами

Постоянно таскать окна между половинами экрана мышкой — потеря времени. Назначим Win+стрелки на привязку активного окна, а Win+C — на центрирование. Символ # в v2 по-прежнему означает клавишу Win.

#Requires AutoHotkey v2.0

; Левая половина экрана
#Left:: SnapWindow(0)
; Правая половина
#Right:: SnapWindow(1)

SnapWindow(rightHalf) {
    if !(hwnd := WinExist("A"))   ; "A" — активное окно
        return
    MonitorGetWorkArea(MonitorGetPrimary(), &l, &t, &r, &b)
    w := (r - l) // 2
    x := rightHalf ? l + w : l
    WinMove(x, t, w, b - t, hwnd)
}

; Win+C — центрировать окно в его текущем размере
#c:: {
    if !(hwnd := WinExist("A"))
        return
    WinGetPos(&x, &y, &w, &h, hwnd)
    MonitorGetWorkArea(MonitorGetPrimary(), &l, &t, &r, &b)
    WinMove((r - l - w) // 2 + l, (b - t - h) // 2 + t, , , hwnd)
}

Обратите внимание на &l, &t — в v2 это передача по ссылке (ByRef через амперсанд). Функции вроде WinGetPos и MonitorGetWorkArea записывают результат в переданные переменные. Целочисленное деление в v2 — оператор //.

Скрипт 3. Вставка шаблонов кода

Многострочные шаблоны (boilerplate) удобно вешать на хоткстринги с continuation section. Покажем заготовку для HTML-документа и блока try/catch. Поскольку внутри кода есть фигурные скобки и спецсимволы, используем SendText, чтобы AHK ничего не интерпретировал.

#Requires AutoHotkey v2.0

; Печатаем "htm5" -> базовый HTML5-каркас
:*:htm5::
{
    tpl := "
    (
<!DOCTYPE html>
<html lang=`"ru`">
<head>
  <meta charset=`"UTF-8`">
  <title></title>
</head>
<body>

</body>
</html>
    )"
    SendText(tpl)
}

; "tryc" -> блок try/catch
:*:tryc::
{
    SendText("try {`n    `n} catch Error as e {`n    MsgBox(e.Message)`n}")
}

Флаг * (звёздочка) срабатывает без завершающего символа — не нужно жать пробел или Enter после аббревиатуры. Внутри строк v2 кавычку экранируют обратным апострофом `", а `n — это перевод строки. В continuation section (текст между скобок) кавычки внутри можно не экранировать, но переносы строк сохраняются буквально.

Скрипт 4. Авто-переключение раскладки и умный буфер обмена

Две частые боли: набрал фразу не в той раскладке и хочешь её «перебить», и хочешь вставить скопированный текст без форматирования. Решим обе.

#Requires AutoHotkey v2.0

; Ctrl+Shift+V — вставить как простой текст (без форматирования)
^+v:: {
    saved := ClipboardAll()        ; сохраняем всё содержимое буфера
    A_Clipboard := A_Clipboard      ; присвоение строки сбрасывает форматирование
    Send("^v")
    Sleep(80)
    A_Clipboard := saved            ; возвращаем исходный буфер
}

; Pause — переключить раскладку выделенного текста через эмуляцию Win+Space
; и заодно показать текущий буфер
^!c:: {
    prev := A_Clipboard
    A_Clipboard := ""
    Send("^c")
    if ClipWait(1)                  ; ждём до 1 сек, пока буфер заполнится
        ToolTip("В буфере: " SubStr(A_Clipboard, 1, 100))
    SetTimer(() => ToolTip(), -2000)   ; убрать подсказку через 2 сек
}

Ключевые моменты v2: буфер обмена теперь называется A_Clipboard (а не Clipboard, как в v1), бинарную копию делает функция ClipboardAll(). Приём «присвоить переменную самой себе» (A_Clipboard := A_Clipboard) отбрасывает RTF/HTML-форматирование, оставляя голый текст. ClipWait надёжнее, чем фиксированный Sleep: он ждёт реального появления данных. А () => ToolTip() — это стрелочная функция v2, удобная для одноразовых колбэков в SetTimer.

Скрипт 5. Быстрый запуск инструментов

Соберём «панель запуска» на одной клавише-модификаторе. Назначим CapsLock как префикс (он всё равно почти бесполезен) и повесим на него запуск редактора, терминала и браузера. Если окно уже открыто — активируем его, иначе запускаем.

#Requires AutoHotkey v2.0

; CapsLock сам по себе ничего не печатает, но работает как модификатор
SetCapsLockState("AlwaysOff")

; CapsLock + E -> VS Code
CapsLock & e:: Run("code")

; CapsLock + T -> Windows Terminal (или активировать, если открыт)
CapsLock & t:: ActivateOrRun("ahk_exe WindowsTerminal.exe", "wt.exe")

; CapsLock + G -> открыть GitHub в браузере по умолчанию
CapsLock & g:: Run("https://github.com")

ActivateOrRun(winCriteria, target) {
    if WinExist(winCriteria)
        WinActivate(winCriteria)
    else
        Run(target)
}

Синтаксис CapsLock & e — это «составная горячая клавиша»: первая клавиша становится модификатором для второй. Run в v2 умеет запускать как исполняемые файлы, так и URL и документы — система сама подберёт обработчик. WinExist с критерием ahk_exe ... проверяет, запущен ли процесс по имени exe, а WinActivate выводит его окно на передний план.

Итого

AutoHotkey v2 — это зрелый, последовательный язык, на котором приятно писать утилиты для собственного рабочего процесса. Если вы только начинаете, нет смысла учить v1: ставьте сразу v2.

  • Синтаксис v1→v2: команды стали функциями со скобками, строки всегда в кавычках, переменные без процентов, обращение к необъявленным переменным теперь ошибка.
  • Объекты: появились раздельные типы Array и Map, настоящие классы и стрелочные функции.
  • Hotstrings разворачивают аббревиатуры в текст, даты и подписи — флаг X для выполнения кода, * для срабатывания без завершающего символа.
  • Управление окнами через WinMove и MonitorGetWorkArea с передачей по ссылке (&var).
  • Шаблоны кода удобно хранить в continuation section и вставлять через SendText, чтобы не интерпретировались спецсимволы.
  • Буфер обмена: A_Clipboard и ClipboardAll(), приём со сбросом форматирования, надёжное ожидание через ClipWait.
  • Запуск инструментов одной клавишей-префиксом (CapsLock & key) с логикой «активировать или запустить».

Начните с небольшого файла autostart.ahk, добавьте в него пару сниппетов из статьи и положите ярлык в папку автозагрузки. Дальше скрипт будет расти вместе с вашими привычками — это и есть главная ценность AutoHotkey.