- PVSM.RU - https://www.pvsm.ru -
При работе со многими программами использование разнообразных комбинаций горячих клавиш — залог высокой производительности и удобства для пользователя. Для достаточно сложных программ мы заучиваем десятки специфических комбинаций клавиш для различный действий. Это позволяет сосредоточиться на фактической работе, а не на блуждании мышкой по многоэтажным меню в поисках необходимого пункта.
Поэтому, идеальная память под комбинации горячих клавиш — мышечная. Пока комбинация в мышечной памяти, не нужно во время работы переключать внимание на выполнение соответствующего действия — оно делается на автоматизме.
Это хорошо, однако у данного интерфейса пользовательского ввода есть проблемы.
Давайте рассмотрим их на примере работы в знакомой большинству обитателей хабра среде — интегрированной среде разработки (IDE).
Это сложная программная система, имеющая множество аспектов использования (написание кода, навигация по коду, рефакторинг, компиляция и исполнение, отладка, работа с системой контроля версий, и.т.д).
Для каждого из этих аспектов есть свои наборы горячих клавиш, которые не используются в других аспектах (когда я пишу код, мне не нужно помнить, какой комбинацией клавиш открывается окно просмотра локальных переменных в отладчике).
Первая проблема заключается в том, что если какое-либо действие делается нерегулярно, то соответствующая комбинация клавиш с большой вероятностью забудется к следующему разу её использования. При этом, в тот момент, когда эта комбинация снова станет нужна, она может оказаться использованной не один-два раза, а достаточно активно некоторое время.
Пример: допустим, вы решили провести крупномасштабный рефактроинг вашей программной системы.
Основные действия, которые нужно будет делать — внесение различных полуавтоматизированных изменений в код (переименования символов, извлечения кусков кода в отдельные функции, изменения сигнатур функций, и.т.д). Кроме того, вам гораздо чаще придётся прыгать с места на место по проекту, смотреть на различные диаграммы классов, иерархии вызовов, и.т.д.
Данный набор действий может довольно сильно отличается от того, который используется при обычном написании кода, поэтому, комбинации горячих клавиш для таких действий со временем могут вымываться из головы, поскольку крупные рефакторинги делаются нерегулярно.
Для борьбы с этой проблемой некоторые программисты делают себе разнообразные cheat-sheets со списками команд, которые полезны в редких случаях. Когда такой случай наступает, приходится обращаться к шпаргалке (или гуглить).
Если вам по какой-либо причине пришлось сменить IDE, заученные на уровне мышечной памяти горячие клавиши старой среды разработки могут оказаться серьёзным барьером. Придётся переучиваться, а это не очень приятное и непродуктивное занятие.
Кроме того, старые комбинации в новой системе могут иметь совершенно другие значения, что особо раздражает.
Тут всё может быть совсем плохо. Одни и те же действия в разных системах могут иметь разные комбинации горячих клавиш. В этом случае приходится постоянно держать в голове по набору комбинаций для каждой системы. Кроме того, нужно всё время мысленно контролировать, что за система используется прямо прямо сейчас. Ключевое тут: «держать в голове», — о мышечной памяти можно забыть, что повлечёт за собой падение производительности.
Допустим, вы отлаживаете клиент-серверную систему, где сервер написан на с++ в Visual Studio, а клиент — приложение на java в IDEA или eclipse.
Сервер формирует пакет с данными, отправляет их клиенту, который их каким-то образом обрабатывает. Сначала нам необходимо разобраться, правильно ли серверная часть генерирует пакеты для отправки. Затем, после отправки данных сервером, нужно будет в дебаггере на клиентской стороне смотреть, как полученные данные обрабатываются. Причём, общение сервера с клиентом может не ограничиться пересылом одного пакета. В этом случае вам придётся перескакивать туда-обратно между дебаггерами не один раз. Основные действия, которые будут делаться вами в данном случае — команды пошагового исполнения программы (step over, step into, step out). Концептуально, эти действия одни и те же, однако в каждой из сред разработки за них отвечают свои функциональные клавиши:
VS | eclipse | IDEA | |
step into | F11 | F5 | F7 |
step over | F10 | F6 | F8 |
step out | Shift+F11 | F7 | Shift+F8 |
При этом, например, 'step into' в eclipse делается клавишей F5, которая в VS отвечает за 'resume execution', что может сбить весь процесс отладки по неосторожности.
В таких ситуациях я часто замечал за собой, что начинаю отлаживать практически исключительно мышкой — это гораздо медленнее, но зато я точно знаю, какое действие и в какой среде я сейчас делаю.
Создание системы эмуляции клавиатурного ввода, упрощающей использование программ, имеющих большой набор действий, инициируемых при помощи комбинаций горячих клавиш.
Требования к системе:
Основная идея системы — на компьютере запускается сервер, который отвечает за генерацию клавиатурных команд. Он работает в бэкграунде и отправляет команды активному в тот момент окну. К этому серверу подключается android устройство, которое используется для пользовательского ввода/вывода. Все команды инициируются нажатиями на кнопки, отображаемые на android устройстве. Когда это происходит, сервер отправляет соответствующую комбинацию клавиш активному окну на своей стороне.
Поскольку сопоставление соответствующей комбинации клавиш для данного действия происходит автоматически на сервере, можно будет определить несколько правил такого сопоставления. Это позволяет единообразно работать с разными программами (если наборы действий, производимых в них, схожи).
Для работы данной системе необходимо иметь следующую информацию:
Данные из первого и второго пункта хранятся в простой таблице (текстовый csv файл с табуляциями в качестве разделителей), которая выглядит примерно так:
В нём каждая строка представляют всю информацию об определённой команде. Первые четыре столбца — служебные. В них хранятся данные, которые используются программой для построения интерфейса пользователя:
Все остальные столбцы таблицы — информация о комбинациях горячих клавиш в различных окружениях. Формат представления комбинаций описан в документации библиотеки, которую я использую для эмуляции клавиатуры. Описание формата можно посмотреть на сайте документации библиотеки [1].
Для писания пользовательского интерфейса используется второй текстовый конфигурационный файл. Интерфейс состоит из набора страниц. На страницах расположены кнопки, каждая из которых соответствует какой-либо команде.
Вот пример простейшей конфигурации страницы и то, как она будет выглядеть на клиентском устройстве:
page:main page
debug_start
debug_stepInto
debug_stepOver
debug_stepOut
debug_restart
В конфигурации интерфейса просто прописаны идентификаторы команд — по одному в строчку. Это транслируется в такой интерфейс для пользователя:
Если в конфигурации указать несколько элементов, разделённых точками с запятой, в одной строке, то соответствующие кнопки будут размещены в один ряд. Между кнопками также можно делать пустые промежутки (для этого достаточно просто не указать идентификатора команды в соответствующем месте).
Следующая конфигурация иллюстрирует данные вещи:
page:main page
debug_start;debug_restart;;
;
;debug_stepOver;;
debug_stepInto;;debug_stepOut
;
Интерфейс, в который это транслируется для пользователя:
Бывают случаи, когда какое-то действие не определено для какого-то из окружений, однако не хочется, чтобы место пустовало. Возможно, есть какое-нибудь другое достаточно схожее действие, которое можно поместить в том же месте в этом случае.
Для этого нужно просто написать по порядку идентификаторы через запятую в соответствующем месте. Система автоматически просканирует список и подберёт первый из вариантов, который будет активен в данном окружении:
page:main
debug_start;debug_restart,debug_stopDebugger;;
;
;debug_stepOver;;
debug_stepInto;;debug_stepOut
;
Вид интерфейса в различных окружениях:
Обратите внимание, как кнопка 'restart' в окружении для VS превращается в 'stop debug' в окружении для eclipse, поскольку для eclipse не определена комбинация для 'restart debug'.
Многие команды по факту являются целыми группами команд, которые по смыслу схожи, поэтому хочется их объединить вместе в клиентском UI, однако не хочется, чтобы они занимали слишком много места. Для примера можно привести команды типа 'build something': 'build solution', 'build project', 'compile file'. Для таких групп команд можно определить специальную страницу, которая будет автоматически появляться и исчезать при нажатии кнопки группы. Эта специальная страница отличается от стандартной только заголовком — тело у неё такое же.
page:main page
debug_start;debug_restart;;
;
do_step
;
optionsSelectorPage:do_step;steps
;debug_stepOver;;
debug_stepInto;;debug_stepOut
Пример работы в UI:
Этот подход очень удобен с командами типа '[сделать определённое действие] с [чем-то]', где выбирается ровно один вариант из нескольких для [чего-то].
Все варианты областей действия команды переносятся на дополнительную страницу и автоматически отображаются, когда нужно.
Страницы опций можно также вкладывать одна в другую, образуя более глубокую и разветвлённую структуру.
Для того, чтобы не следить за тем, какое окно сейчас активно (чтобы симулируемый клавиатурный ввод не отправился кому попало), можно попросить программу контролировать это. Для этого системе при запуске передаётся опция 'stickEnvToWindow'.
В этом случае при выборе нового окружения, пользователю будет отображаться такой запрос:
Пользователь должен будет сделать нужное ему окно активным и проинформировать об этом программу, нажав кнопку в нижней части экрана клиентского устройства. После этого, всякий раз, когда пользователь запрашивает исполнение команды, сервер будет проверять, правильное ли окно находится в фокусе. Если это не так, то выполнение команды приостанавливается, а пользователю отображается следующая заглушка:
В этом случае пользователь должен либо вернуть фокус нужному окну и снова запросить выполнение команды, либо отменить команду:
Естественно, данный подход может быть использован не только для горячих клавиш. Любое часто повторяемое действие с клавиатуры может быть автоматизированно при помощи данной программы.
Для себя я регулярно использую подобные вещи:
Часто при наборе русского текста мне приходится переключаться в английскую раскладку ради одного слова, или даже пары символов. Русская раскладка не признаёт существования следующих символов: ' < > [ ] { } $ # @ & ^ ~, некоторые из которых бывают нужны регулярно. Кроме того, в русском тексте могут встречаться повторяющиеся термины на английском, а, если это html, то ещё и тэги.
Симуляцию набора текста в другой раскладке можно реализовать просто добавив команды переключения раскладки клавиатуры перед и после фактического набора вставляемого текста.
Например, чтобы напечатать тэг <html>, нужно использовать следующую комбинацию: '+{COMMA}html+{PERIOD}'. Она правильно сработает, если включена английская раскладка. Если же включена русская раскладка, то нужно добавить в начало и конец комбинации горячую клавишу переключения раскладки. В моём случае, это '%{SHIFT}' (Alt+Shift). Таким образом, если в текстовом редакторе включена русская раскладка клавиатуры, то следующая последовательность символов: '%{SHIFT}+{COMMA}html+{PERIOD}%{SHIFT}' напечатает там <html>.
Пример работы:
Допустим, мне нужно в большом количестве мест в коде обернуть некоторые переменные в макрос или вызов функции. Например, у какой-то из функций нужно изменить тип параметра, поэтому во всех местах, где эта функция вызывается, нужно сконвертировать то, что туда передавалось в новый тип.
Если подобных изменений нужно сделать хотя бы несколько десятков, то идея это автоматизировать становится очень привлекательной.
Шаги, которые нужно сделать в данном случае:
Шаги 2-5 автоматизируются следующей комбинацией: '^{X}my+function+name+9^{V}+0'.
Пример работы:
Кроме того, возможно, в разных местах кода вид этих вызовов может немного различаться (возможно, где-то нужно указывать пространство имён вызываемой функции, передавать дополнительные параметры, и.т.д). Всё эти вариации легко реализовать и иметь под рукой.
Система пока что сырая — это скорее прототип, а не конечная версия. Но, как мне кажется, уже в её нынешнем состоянии, она способна упростить и повысить эффективность работы с горячими клавишами.
Технические детали реализации я в данной статье не затрагивал, чтобы не раздувать её. Если будет интерес — можно будет сделать статью, посвящённую этому.
Код реализации лежит у меня на гитхабе [2]. Там же есть немного более формальной документации о форматах конфигурационных файлов и аргументов командной строки.
Если не хочется качать исходники и компилировать код, есть собранная для windows версия [3] (для запуска нужно будет поставить Microsoft Visual C++ 2015 Redistributable [4]).
Для самостоятельной компиляции исходников нужен C++14 — совместимый компилятор и boost (используются boost::asio и boost::program_options). В документации [5] есть описание того, как собирать проект при помощи gcc и Visual Studio.
Буду рад услышать критику по поводу реализации, а также предложения о том, что можно добавить в систему. Кроме того, сейчас мне не очень нравится формат конфигурационного файла описания UI. Если у кого-нибудь есть идеи, как можно лучше представить подобный интерфейс (предпочтительно в простом текстовом формате), прошу в комментарии.
Что ещё хочется добавить в данной системе:
Все ссылки в одном месте:
Проблемы и неочевидности, о которых стоит знать перед использованием:
Автор: taco_attaco
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/229064
Ссылки в тексте:
[1] сайте документации библиотеки: http://getrobot.net/api/keyboard.html#Compile
[2] гитхабе: https://github.com/vosel/hat
[3] собранная для windows версия: https://github.com/vosel/hat/releases/tag/v0.1.0
[4] Microsoft Visual C++ 2015 Redistributable: https://www.microsoft.com/en-us/download/details.aspx?id=53840
[5] документации: https://github.com/vosel/hat/blob/master/README.md#compilation
[6] Дополнительный репозиторий: https://github.com/vosel/hat-additional
[7] link: https://github.com/vosel/hat-additional/tree/master/other/habrahabr_article_01
[8] boost: http://www.boost.org/
[9] Robot: http://getrobot.net
[10] tau: https://github.com/vosel/tau
[11] статья: https://habrahabr.ru/post/309882/
[12] Клиентское приложение под android: https://play.google.com/store/apps/details?id=com.tau.client
[13] Источник: https://habrahabr.ru/post/318934/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.