`

СПЕЦІАЛЬНІ
ПАРТНЕРИ
ПРОЕКТУ

Чи використовує ваша компанія ChatGPT в роботі?

BEST CIO

Определение наиболее профессиональных ИТ-управленцев, лидеров и экспертов в своих отраслях

Человек года

Кто внес наибольший вклад в развитие украинского ИТ-рынка.

Продукт года

Награды «Продукт года» еженедельника «Компьютерное обозрение» за наиболее выдающиеся ИТ-товары

 

Горячие клавиши

Статья опубликована в №38 (606) от 9 октября

+44
голоса

О возможностях «непрограммистского программирования» ОС семейства Windows принято говорить с некоторой долей пренебрежения, дескать, это вам не UNIX... А уж продолжение фразы зависит от выдержки говорящего – самые горячие головы вообще считают, что пользователям Windows не требуется никакой персональной программируемой адаптации системы под свои нужды.

Главная особенность стереотипов заключается в том, что они сильно не соответствуют действительности. И справедливость этого высказывания особенно заметна в случае предмета нашего обсуждения. Потому что он позволяет пользователю удивительно эффективно, с минимальными затратами и минимальным количеством инструментов создавать новую требуемую функциональность – в той системе, которая, согласно стереотипам, совершенно для этого не пригодна. Впрочем, начнем по порядку, с... отступления. В контексте статьи – совершенно необходимого.

Сказывается ли архитектурная модель операционной системы и оболочки пользовательской среды исполнения (приходится явно различать эти понятия, потому что в UNIX-подобных системах, например, между ними нет тесной интеграции) на инструментальном наборе? Если «да», то какова зависимость характера этого влияния от уровня инструментов? Данный материал писался не для поиска ответов на эти вопросы, более того, их поиск потребует несоизмеримо боóльших затрат труда, времени и объемов, чем журнальная статья. Поэтому придется прибегнуть к приему «от очевидного»: очевидно, что зависимость между архитектурной моделью системы и особенностями инструментов для нее есть, менее очевидно, но, по некоторому рассуждению достаточно логично, что чем ниже уровень инструмента, тем меньше проявляется эта зависимость. Впрочем, судите сами: ассемблер – он и на суперкомпьютере ассемблер, и на 4-битовом микроконтроллере. А вот язык сверхвысокого уровня для быстрого, с минимальными затратами «как бы программирования» – с ним так не получится. Он должен упрятывать за простыми и эффективными абстракциями множество сложных понятий, большинство из которых – архитектурно-зависимы. Например, в UNIX-системах фундаментальным архитектурным понятием является канал (pipe), поэтому оно отражается крайне лаконичной формой записи в языках сверхвысокого уровня. А что является фундаментальным в ориентированных на обработку сигналов о событиях операционных системах, к каким относятся и ОС семейства Windows, и пользовательские оболочки типа KDE и Gnome? Вопрос действительно непростой, но попробуем прибегнуть к аналогии (по мнению автора статьи, вполне допустимой). В UNIX-подобных операционных системах языком сверхвысокого уровня формировался некий поток вычислений, и активаторами отдельных «вычислительных узлов» этого потока как раз и были каналы. Иными словами, «обрабатывающий вычислительный узел» (команда) UNIX что-то делает тогда, когда на его вход каналом доставляются обрабатываемые данные. Пользователь (не обязательно человек) может вызвать эту активацию принудительно, передав данные через канал. В системах, ориентированных на обработку сообщений о событиях, ту же самую роль играют... да, именно они: сигналы от устройств взаимодействия пользователя и машины. И если от клавиатуры и мыши сигналов не поступает, операционной системе делать нечего (само собой, есть неинтерактивные сервисы и прочее, но они-то нас как раз не интересуют – в пользовательских системах они потому и «спрятаны», что работают не на пользователя, а на систему). Иногда – настолько нечего, что компьютер «засыпает», переводится в режим с минимальным энергопотреблением.

Итак, по логике вещей, для пользовательских систем нужно инструментальное средство сверхвысокого уровня, позволяющее с наименьшими затратами труда создавать именно обработчики сообщений о ключевых для таких систем событиях. И это средство есть. Причем настолько удачное и позволяющее столь многое, что буквально через несколько дней возни с ним начинаешь понимать, какие дивиденды приносит грамотный отказ от универсальности в пользу системно-зависимого высокоуровневого абстрагирования.

AutoHotkey

Предмет нашего обсуждения относится к категории феноменальных в мире Windows-freeware-разработок – начальный релиз программы появился 10 ноября 2003 г., и с тех пор, если судить по частоте выхода версий, она развивается со стабильностью часового механизма. Конечно, – все может случиться, но и в непредвиденных ситуациях развитие AutoHotkey не должно прекратиться хотя бы потому, что программа распространяется с открытыми исходными текстами.

Для Оpen Source программы из мира Windows бинарная версия AutoHotkey распространяется традиционно – в виде инсталлятора и упакованного файла. Разница между ними в том, что инсталляция методом распаковки в указанный каталог требует установки ассоциаций (.ahk -файлов с интерпретатором AutoHotkey) вручную – такой метод инсталляции в ряде случаев очень полезен для системных администраторов (и во всех случаях приносит долгожданное, но временное, успокоение параноидально озабоченным проблемами информационной безопасности). Полноценный Windows-инсталлятор делает то же самое, только без пользовательского вмешательства.

После инсталляции программы в ее каталоге появляются следующие ключевые файлы – интерпретатор AutoНotkey.exe (размером неполных 240 KБ), утилита получения информации о главных объектах, которыми вы будете манипулировать с помощью AutoHotkey – об окнах (AU3_Spy.exe) и файл документации. В подкаталогах находятся различные расширения и дополнения программы, но пока они нас интересовать не будут.

Прежде чем мы начнем знакомство с языком описания реакций на события в пользовательской оконной системе, давайте разберемся с высокоуровневой логикой работы интерпретатора AutoHotkey. По сути, она предусматривает исполнение языковых конструкций двух фундаментальных типов – описаний реакций и одноразово исполняемых скриптов. Конструкция первого типа один раз «прочитывается» интерпретатором, после чего он как бы «замирает» в ожидании указанного события и активирует описанные пользователем действия как реакцию на событие. Соответственно, код скриптов первой категории постоянно загружен в память – до момента явного принудительного прекращения работы интерпретатора. Конструкции второго типа выполняются точно так же, как классические скрипты – до завершения кода скрипта, после чего он автоматически выгружается из оперативной памяти. Но AutoHotkey предусматривает возможность описания и третьей конструкции – перманентно загруженного в память кода скрипта. Для объявления такой несколько необычной конструкции достаточно использовать в начале кода директиву #Persistent – пусть она, ввиду необычности и идеального соответствия рассуждениям о влиянии архитектурной модели ОС на инструментальные средства, будет первым вашим шагом в освоении AutoHotkey (на самом деле эта вроде бы простая директива весьма непроста – кроме указания интерпретатору «этот код выгружать из памяти только по явному требованию программиста», она превращает скрипт как исполняемый объект в то, что принято называть синглетоном – т. е. интерпретатор может исполнять только одну копию #Persistent-скрипта).

А теперь, не откладывая в долгий ящик, сразу создадим первый фрагмент AutoHotkey-кода, дающий возможность «почувствовать вкус» скриптинга в архитектурной модели Windows. Итак, мы уже знаем, что код конструкций первого типа (описание реакций на событие) и перманентных конструкций (директива #Persistent) постоянно «сидит» в памяти запущенного интерпретатора. А как быть, если вы изменили исходные тексты этого кода? В скриптовых языках из архитектурного мира ОС UNIX такая проблема обычно не существует, потому что пользователь (или человек, или сторонняя программа) инициирует исполнение кода скрипта, в явном виде передавая его интерпретатору – в таком случае, если изменился исходный текст скрипта, изменяется и код, исполняемый интерпретатором. В AutoHotkey, безусловно, можно пойти тем же путем – если вы изменили исходный текст скрипта первой категории или перманентного, надо вручную остановить работу интерпретатора и перезапустить его, передав на исполнение обновленный исходный текст. Но это же ужасно! Потому что полностью «ломает» всю идею автоматизации за счет скриптинга. Такая вопиющая несправедливость устраняется следующим фрагментом кода (куда более полезным, чем традиционный «Hello, world!»), который мы разберем «по косточкам»:

; Процедура автозагрузки измененного кода скрипта
ScriptAutoReload:
FileGetAttrib, attribs, %A_ScriptFullPath%
IfInString, attribs, A
{
FileSetAttrib,-A, %A_ScriptFullPath%
Reload
}
Return

Первая строка в приведенном фрагменте – комментарий. В большинстве языков, созданных людьми в состоянии ясного сознания и немодифицированной психики, комментарии – самая низкоуровневая конструкция, вообще игнорируемая механизмами интерпретации или трансляции. Поэтому в AutoHotkey, в полном соответствии с приведенными ранее соображениями, для них применяется синтаксис, заимствованный из ассемблера (в большинстве ассемблеров первым символом комментариев действительно является «;», но ради бога, не воспринимайте эти два предложения всерьез!). Итак, комментарий в AutoHotkey начинается символом «;» – сам этот символ и все, следующие после него до конца строки, интерпретатором игнорируются.

Синтаксически вторая строка – это объявление метки с именем ScriptAutoReload, о чем свидетельствует символ «:» после имени. Это весьма традиционная конструкция, в AutoHotkey заменяющая объявление процедуры – при передаче управления метке (с помощью функции GoSub, в имени которой как раз и используется термин Subroutine – подпрограмма, процедура) интерпретатором выполняется последовательность действий, ограниченная меткой и командой возврата Return, после чего поток выполнения возвращается на следующую за GoSub команду. Если теперь взглянуть на последнюю строку приведенного фрагмента кода, можно сказать, что он описывает процедуру, обеспечивающую автоматическую загрузку обновленного кода скрипта (об этом мы пока знаем только из комментария, но сейчас справедливость утверждения проверим).

Третья строка знакомит нас с двумя главными понятиями всех языков – переменными и функциями. В AutoHotkey используется схожий с функциональными языками синтаксис описания вызовов функций – список из имени и параметров, разделенных запятыми. То есть, если в AutoHotkey-скрипте вы встречаете что-то вроде Ffff, B, C, D – это вызов функции Ffff с параметрами B, C и D. Соответственно, в приведенном примере (во второй строке) функция FileGetAttrib вызывается с двумя параметрами – attribs и %A_ScriptFullPath%. Так как это очевидно не похоже на возможные формы литералов (числовых, символьных, строковых, etc, – синтаксис описания литералов в AutoHotkey весьма традиционен), то речь идет о переменных. В AutoHotkey все переменные обладают следующими характеристиками: во-первых, их имена не зависят от регистра использованных символов (т. е. attribs, Attribs и ATTRIBS – имена одной и той же переменной; кроме того, в именах допустимо использование символов # _ @ $ ? [ ]); во-вторых, их тип всегда – строка символов; в-третьих, если они впервые использованы вне функции, они глобальны; в-четвертых, они не нуждаются в объявлении. Эти ограничения вполне обычны для утилитарных скриптовых языков, не претендующих на сверхприменимость. Именно такими переменными и являются attribs и A_ScriptFullPath.

Наблюдаемое в третьей строке заключение имени переменной между парой символов процентов («%») в языке AutoHotkey может стать сюрпризом для тех, кто уже знает один или несколько скриптовых языков. Сама переменная A_ScriptFullPath относится к классу системных «атрибутов скрипта» (Script Properties, все они описаны в документации, в разделе «Переменные и выражения») и содержит, что очевидно, полное путевое имя файла, в котором хранится код скрипта. Запись %имя_переменной% в AutoHotkey, по сути, инициирует механизм подстановки – %имя_переменной% заменяется содержимым-строкой, хранящейся в переменной. Это позволяет, с одной стороны, гарантировать постоянность доступных только по чтению системных переменных (таких, как атрибуты скрипта) при использовании их в качестве параметров вызываемых функций (что и демонстрирует третья строка примера), и, с другой стороны (точнее, при использовании в выражениях), реализовать механизм «псевдомассивов» – переменных, ссылающихся в ходе выполнения программы на разные переменные из некоторого множества. Последнее вынуждает нас сделать маленькое отступление и привести такой несложный пример:

Var_Named_Variable := Coord_%Which_Coord%

Так как в AutoHotkey строка – главный объект, то синтаксически конкатенация строк обозначается самым удобным способом – никак (на самом деле для нее есть и специальный символ – «.»), что означает – содержимое переменной Var_Named_Variable является содержимым другой переменной, имя которой образовано конкатенацией строки Coord_ и содержимым переменной Which_Coord: если последняя содержит строку «X», Var_Named_Variable будет содержать ту же строку, что и переменная Coord_X.

В четвертой строке с помощью весьма специфической функции ifInString, управляющей потоком исполнения программы, проверяется, есть ли в перечне атрибутов файла флаг «А». Для справки: этот атрибут означает Archived (т. е. файл был перезаписан или изменен) и реализован во всех файловых системах Microsoft, начиная с MS DOS 2.0.

Дальше, в принципе, все понятно даже и без документации – в пятой строке скрипт снимает атрибут Archived с файла со своим исходным текстом, в шестой – выполняет команду перезагрузки исходных текстов в интерпретатор и его перезапуск.

Единственное, что осталось добавить к этому примеру – очевидный в каком-то смысле обязательный для повседневного непрограммистского программирования C-подобный синтаксис.

Теперь поговорим о главном механизме AutoHotkey – естественно, об описании реакций на события в системе. Для этого язык предлагает предельно простой синтаксис, позволяющий реализовать самые вычурные описатели событий – однострочный и многострочный:

шаблон_события :: код_реакции_умещается_в_одной_строке
шаблон_события ::
код_реакции
...
Return

Язык шаблонов событий предельно прост – в нем для ключевых «командных» клавиш введены обозначающие символы (например, наиболее популярная в пользовательских командах клавиша Win обозначается символом #), а также различные модификаторы – от сугубо синтаксических (вроде левая-правая кнопка) до глубинных архитектурно-зависимых семантических (например, модификатор «~» означает, что обработанное AutoHotkey сообщение не требуется удалять из системной очереди сообщений и оно, кроме пользовательского скрипта, будет обработано предусмотренным системой образом).

Помимо этого механизма, AutoHotkey реализует и механизм подмен – заданные пользователем строки при клавиатурном вводе на лету подменяются назначенными им заменами (более того, подмены работают не только при клавиатурном вводе, ведь, по сути, они являются описаниями реакций на последовательности событий). Синтаксис подмен также предельно прост:

::строка::заменяющая_строка

В принципе, этих сведений вполне достаточно для того, чтобы разобраться с AutoHotkey самостоятельно. Программа хорошо (но весьма специфически, что, в общем, характерно для freeware и Оpen Source проектов) документирована. Кроме того, сообщество любителей AutoHotkey-скриптинга охотно делится своими наработками – среди них есть много очень полезных готовых утилит, на отсутствие которых в ОС Windows принято сетовать. В частности, с помощью AutoHotkey несложно реализуются скрипт «сворачивания» окон в заголовок (его исходные тексты имеются в «галерее скриптов» – Scripts Showcase, ссылки на который есть в документации), механизмы управления окнами, традиционные для пользовательских интерфейсов ОС семейства UNIX, а также настоящие полноценные функциональные аналоги UNIX-приложений. Например, с помощью AutoHotkey и утилиты Console (console.sourceforge.net) в ОС Windows создается аналог весьма забавной появляющейся по требованию пользователя консоли в Quake-стиле YaKuake – пошаговое описание разработки такого AutoHotkey-скрипта приведено на сайте Instructables и легко находится по ключевым словам «Quake AutoHotkey Console».

Особенности национального скриптописательства

Существует ошибочное мнение, что локализация продукта – это перевод служебных сообщений, меню, руководства пользователя и соблюдение требуемых национальных нормативов (метрические и денежные системы, etc). AutoHotkey же демонстрирует некоторые аспекты проблемы локализации программного обеспечения, незаметные на первый взгляд. В ОС семейства Windows есть общесистемное понятие «раскладка клавиатуры, используемая по умолчанию», а также для каждого исполняющегося приложения – «текущая раскладка клавиатуры». В связи с этим в ваших даже невинных экспериментах с AutoHotkey вполне возможно появление сообщения «The hotkey ... will not be active because it does not exist in the current keyboard layout», потому что выбранной вами комбинации клавиш... просто нет в раскладке клавиатуры. На самом деле это не проблема – вы всегда можете использовать разрешенный синтаксисом AutoHоtkey прием описания одной реакции на множество событий или скан-коды клавиатуры. По большому счету, если вы хотите, чтобы ваш скрипт мог работать на машинах с по-разному локализованными версиями ОС, лучше пользоваться именно сканкодами – это не ограничение, а естественный прием, позволяющий разработчику бесплатно распространяемой программы удерживать свой проект в рамках реальности его сопровождения.

Синтаксис описания одной реакции на множество событий прост:

шаблон_события_01::
шаблон_события_02::
...
шаблон_события_NM::
код_реакции
...
Return

Ready, set, buy! Посібник для початківців - як придбати Copilot для Microsoft 365

+44
голоса

Напечатать Отправить другу

Читайте также

 

Ukraine

 

  •  Home  •  Ринок  •  IТ-директор  •  CloudComputing  •  Hard  •  Soft  •  Мережі  •  Безпека  •  Наука  •  IoT