Я сделал себе полгода назад скрипт под AHK (https://autohotkey.com/), какой давно хотел. Назвал «Микле́дет». Выложил на гитхаб (пока черновой вариант, но рабочий), может, кому понравится:
(https://raw.githubusercontent.com/formicant/Miqledeth/master/Icons/Miqledeth.svg?sanitize=true)
Работает в последних стабильных версиях AHK 1.1.x под Windows XP, 7 и 10 (на десятке приходится использовать _UIA-версию эксешника AHK).
Идея такая: чтобы модифицировать раскладки, пользователь редактирует не сам скрипт, а файлы описания раскладок, которые лежат в папке Layouts, а скрипт при запуске их парсит и делает всю работу.
Здесь я опишу, как устроены мои раскладки, в качестве примера.
Сейчас у меня в системе установлены две совершенно стандартные раскладки — English (US) и Russian.
В папке Layouts скрипта можно найти файлы layout-Latin.miq и layout-Cyrillic.miq, в которых описываются дополнительные фичи для этих раскладок. (Чтобы было понятнее, о чём дальше пойдёт речь, лучше открыть их в текстовом редакторе и посмотреть.)
Синтаксис файлов напоминает s-выражения, с тем отличием, что скобки — фигурные, перевод строки — значимый символ, и s-выражениям, занимающим целиком одну строку, не требуются скобки.
Пробелы и табуляции нефонематичны — главное, чтобы между токенами был хотя бы один.
Комментарии начинаются с символа % и распространяются до конца строки.
Токены могут состоять из любых символов уникода, кроме зарезервированных синтаксисом («_», «%», «"», «{», «}»), которые эскейпируются символом «_». Также, сочетание «_s» даёт пробел, а «_t», «_r», «_n» — то же, что «\t», «\r» «\n» в сях.
Кроме того, токен можно заключить в кавычки ("), тогда он может содержать вообще любые символы, кроме перевода строки. Кавычки внутри кавычек удваиваются.
Можно также использовать шестнадцатиричные код-пойнты уникода, заключённые в подчёркивания. Например: _8F_, _1F4A9_.
Парсер пока не слишком умный и может выдавать невнятные сообщения об ошибках парсинга. Ещё хуже, когда синтаксис в порядке, но семантика нарушена — тогда скрипт будет неприлично ругаться и/или ломаться :(
В начале идёт блок Layout, в котором указывается название раскладки (Name), соответствующий язык системной раскладки (Language), и значок (IconIndex — см. ниже). То есть, Latin у меня висит на английской системной раскладке, а Cyrillic — на русской.
Раскладки layout-Greek.miq и layout-Hebrew.miq в блоке Layout не содержат Language — они у меня не привязаны к системным раскладкам.
Если блока Layout в файле нет, то содержимое файла распространяется на все раскладки.
Блок Modes определяет, какие клавиши-модификаторы (или их сочетания) использует раскладка, а блок Keys описывает, какие символы соответствуют клавишам, нажатым с этими модификаторами.
Например, в раскладке Latin блок Modes имеет вид:
{ Modes
-
- shift
+ Var
+ Var shift
}То есть, первый режим — без модификаторов,
второй — с шифтом,
третий — с Var'ом,
четвёртый — с Var'ом и шифтом.
(Var — это кастомная клавиша-модификатор, сидящая на правом альте.
Всего кастомных модификаторов у меня три — Var, Dia и Lay, они определены в файле common-Modifiers.miq)
Дальше идёт блок Keys вида
{ Keys
Q q Q ø Ø
...
}Начальный токен — это клавиша, дальше идут символы для режимов по порядку.
То есть, клавиша Q даёт:
в первом режиме (без модификаторов) — q,
во втором (с шифтом) — Q,
в третьем (с Var'ом) — ø,
в четвёртом (c Var + shift) — Ø.
Как видно, первые два режима не вносят ничего нового — в них всё как в системной раскладке. Символы «+» и «-» в блоке Modes используются ради оптимизации: если режим помечен минусом, скрипт не обрабатывает его — ввод идёт напрямую с системной раскладки. В идеале, конечно, было бы правильно вообще не указывать символы для этих режимов, однако они нужны скрипту для правильной обработки замен, а доставать их из самих системных раскладок скрипт пока не умеет, так что приходится делать так. Впрочем, для раскладок, отличных от qwerty это даже улучшает наглядность.
Зарезервированный токен «_» обозначает отсутствие значения. Например, в кириллической раскладке он используется в цифровых клавишах, чтобы не заменять их общее для всех раскладок поведение, определённое в common-Symbols.miq.
Клавиши-модификаторы обычно используются в сочетании с другими клавишами, но скрипт позволяет назначать им действия, когда они нажаты сами по себе.
Например, в файле common-Symbols.miq:
{ Modes
-
- shift
+ Var
+ Var shift
}
{ Keys
...
_ _ _ , ?
...
}Здесь определяется, что Var, нажатый сам по себе, будет давать запятую, а Var + shift — вопросительный знак.
Ещё один блок, который может быть в файлах — Substitutions. В нём определяются замены.
Все замены группируются по группам. Например, в латинской раскладке есть:
{ Substitutions
{ Ligature
AA Ꜳ
Aa Ꜳ
aa ꜳ
AE Æ
Ae Æ
ae æ
...
}
...
{ Superscript
A ᴬ
a ᵃ
ɐ ᵄ
ɑ ᵅ
Æ ᴭ
ᴂ ᵆ
ᴥ ᵜ
B ᴮ
b ᵇ
...
}
...
}— это группы замен c названиями Ligature и Superscript.
В файле common-Diacritics.miq определяется, какие сочетания клавиш инициируют какую группу замен:
{ Modes
+ Dia
...
}
{ Keys
_ {sub Ligature}
...
PgUp {sub Superscript}
...
}То есть, Superscript инициируется сочетанием Dia + PgUp, а Ligature — клавишей Dia, нажатой самой по себе.
Например, чтобы написать символ «æ», надо нажать последовательно: A, E, Dia. Чтобы написать «ᵃ», надо нажать: A, Dia + PgUp.
С диакритиками я сделал такую хитрую вещь:
common-Diacritics.miq
{ Modes
+ Dia
...
}
{ Keys
...
' {sub Acute} {sub AcuteBelow}
...
` {sub Grave} {sub GraveBelow}
...
}
{ Substitutions
Acute {_ ́ } ...
Grave {_ ̀ } ...
...
}layout-Latin.miq
{ Substitutions
...
{ Acute
A Á
a á
...
}
{ Grave
A À
a à
...
}
...
}То есть, сочетание Dia + ' даёт навесной акут. Но также оно инициирует группу замен Acute, на которую я поставил все символы уникода с комбинированным акутом. Таким образом, Акут становится не навесным, а комбинированным, если такой комбинированный символ есть в уникоде. И так со всеми имеющимися в раскладке диакритиками.
Если же нужны именно навесные акуты, то эти замены можно на время отключить:
{ Keys
...
ScrollLock {toggle combining}
}При включённом скролл-локе на значке раскладки появляется апостроф, символизирующий, что диакритика будет вводиться навесная, а не комбинируемая.
В файле common-Layouts.miq задаются клавиши переключения между раскладкми:
{ Modes
+ Lay
+ Lay shift
+ Lay ctrl
}
{ Keys
_ {switchLayout next} {retypePhrase next} {retypeChar next}
L {switchLayout Latin} {retypePhrase Latin} {retypeChar Latin}
...
}Здесь определено, что клавиша Lay (находящаяся на капс-локе) включает следующую системную раскладку, то есть, в моём случае переключается между латиницей и кириллицей.
Раскладки также можно включать напрямую. Например, Lay + L включает латиницу, Lay + G — гречицу и т. д.
Shift + Lay (+ раскладка) преобразует последнюю набранную фразу в соответствующую раскладку, как это делает Punto Switcher в ручном режиме.
Ctrl + Lay (+ раскладка) преобразует таким же образом один последний символ.
Текущая раскладка отображается на значке AHK (так как она не всегда соответствует системной). При добавлении новой раскладки желательно добавить новый значок. Векторные рисунки значков находятся в файле Icons\Icons.svg, их можно дорисовывать справа, а в файле раскладок — указывать порядковый номер значка (IconIndex).
Скрипт берёт значки из dll-ки, которую после редактирования svg-шки надо перебилдить. Для этого используется PowerShell-скрипт Icons\BuildIcons.ps1. Перед первым использованием его надо открыть и вписать туда пути к необходимым инструментам, которые предварительно надо поставить (там всё написано).
При старте (или рестарте) скрипт берёт все файлы .miq из папки Layouts (имена файлов не имеют значения) и парсит их, преобразуя во внутреннее представление. С таким количеством файлов, как у меня, на это тратится несколько секунд — оптимизацией я пока не занимался. У меня запуск скрипта стоит в автозапуске, и пара лишних секунд при загрузке системы не критична. Сама же работа скрипта не создаёт лагов (по крайней мере у меня).