...

понедельник, 4 октября 2021 г.

Почему я написал плагин Ataman и как он может изменить вашу работу с IDE от JetBrains

Что такое Ataman?

Ataman – это мой плагин для IDE-шек на базе Intellij. Единственное его предназначение – сделать возможным использование leader key биндингов в моём основном рабочем инструменте – Android Studio.

Leader что?

Leader key, или, как его ещё называют, sticky key – это подход к горячим клавишам, популярный среди пользователей олдскульных редакторов Emacs и Vim. Для того чтобы запустить биндинг, нужно нажать клавишу leader и затем по очереди последовательность клавиш, которая и будет командой.

Emacs и Vim? Это же что-то для дедов

Этим текстовым редакторам действительно дофига лет. Они появились на свет более сорока лет назад, задолго до Java, Intellij и тем более Android Studio. Но им есть что предложить разработчику, попивающему смузи пока его макбук пыхтит, собирая сотни LOC в apk-файл.

Обязательный комикс xkcd про Emacs
https://xkcd.com/378/
https://xkcd.com/378/

Чем обычные биндинги не угодили?

В Intellij очень страшные биндинги, которые могут задействовать до трёх клавиш-модификаторов и клавиши F-ряда. Это какое-то издевательство над пальцами разработчиков. Чтобы переименовать символ нужно зажать Shift+F6, вытянув пальцы в раскоряку. Я когда учился играть на гитаре так сильно пальцы не утруждал. Вызов меню рефакторинга на Windows это Ctrl+Alt+Shift+T. Четыре пальца напрягаются и завидуют пальцам пользователей macos, которым досталось мирное ^T. Кстати, почему T? От Refac[t]or? А чёрт его знает, логики здесь не ищите, использовали свободные клавиши. Не удивительно, что запомнить все биндинги считается тяжелой задачей, для которой пишут специальные плагины типа Key Promoter X, который находится в топе на Jetbrains Marketplace c 2,6M скачиваний.

А чем leader key лучше?

Допустим, я выбрал в качестве лидера Ctrl+L. И хочу вызвать меню рефакторинга. Я могу это сделать нажав три клавиши по очереди:

  • Ctrl+L: leader клавиша

  • с: префикс для группы биндингов для работы с кодом, как в слове [c]ode

  • r: рефакторинг, как в слове [r]efactor

Так как в один момент времени нажата лишь одна клавиша, мои пальчики счастливы. Счастлив и мой мозг, для которого теперь вместо какого-то набора модификаторов и какой-то случайной буквы нужно запомнить одну точку входа во все биндинги и красивую мнемонику. Я даже когда прожимаю это, у меня в голове звучит голос, проговаривая то что я собираюсь сделать: “[c]ode [r]efactor”

Префиксы какие-то. Зачем они нужны?

На клавиатуре всё-таки не хватает символов для того чтобы охватить все нужные биндинги. На 36 буквах и цифрах стандартной qwerty особо не разгуляешься. Обычно пространство доступных сочетаний клавиш расширяют при помощи модификаторов, но с leader key мне доступен гораздо более приятный инструмент - префиксы. Так как каждая клавиша нажимается отдельно, я могу объединять биндинги в группы. Про одну из них я рассказал выше – это [c]ode. Туда я закинул всё что связано с кодом. Вот некоторые из моих биндингов, с подписанными мнемониками:

  • <leader> [c]ode re[f]ormat – отформатирует файл

  • <leader> [c]ode [t]ype_info – информация о типе выражения под курсором

  • <leader> [c]ode [i]mplementation – переход к реализации интерфейса/метода

Моя группа биндингов [c]ode выглядит вот так
Моя группа биндингов [c]ode выглядит вот так

Я и так могу воспользоваться Ctrl+Shift+A и найти нужный мне экшн. И мнемоники не нужны

Я тоже пользуюсь поиском по экшнам, он даже у меня забинден на <leader> [s]earch [a]ctions. Но он достаточно медленный и ожидание пока прогрузится поиск по всем экшнам для того чтобы переименовать переменную выбивает меня из сладкого состояния потока, когда решение уже у тебя в голове и его только лишь осталось перенести в исходник. В этот момент хочется чувствовать себя повелителем машин, который чёткими движениями пальцев повелевает им выполнять нудную работу, а не ждать пока они эту самую нудную работу доделают. Поэтому для тех экшнов, которые нужны постоянно без удобных биндингов не обойтись.

Окей, убедил. Как пользоваться Ataman?

После того как скачаешь плагин, привяжи экшн Ataman: Leader Key к удобной для себя клавише. Можно использовать Ctrl+L из примера выше, можно что-нибудь поинтереснее. Мой знакомый приловчился использовать Tab Tab используя second stroke биндинг. Этот экшн является точкой входа в твои биндинги. Изначально там будет только один биндинг q a f, создающий и открывающий твой конфиг в файле ~/.atamanrc.conf.

Конфиг? Я что, должен ещё и сам придумать эти биндинги?

Я люблю Leader Key за мнемоники, которые помогают мне запомнить все эти биндинги. Вы конечно же можете взглянуть на мой конфиг для вдохновения. Но мои биндинги частично построены на моём опыте использования Doom Emacs, откуда я и взял идею leader key. В них есть специфичные для Emacs термины, типа [b]uffer для табов или [y]ank для копирования. Я привык, а кому-то может показаться неудобно. Поэтому я очень советую вам самим придумать себе свой идеальный конфиг.

Странный формат для конфига. Это типа JSON?

Для конфига используется формат HOCON – это очень классная надстройка над JSON, которая сделана специально для конфигов, но не такая бесячая, как YAML. А всё благодаря тому что вместо значащих отступов для вложенности используются фигурные скобки. Документацию к HOCON можно почитать в репозитории проекта. Ещё советую поставить плагин HOCON для Intellij, с автоформатом редактировать конфиг приятнее.

Ладно, а что за схема такая странная?

Я воспользовался гибкостью HOCON чтобы сделать конфиг удобным для чтения и редактирования. Корневым элементом конфига является группа биндингов bindings, которая по сути словарь биндингов к их определениям. Каждый биндинг может либо вызывать экшон либо быть префиксом для группы биндингов. У любого биндинга должен быть ключ description, который будет показываться в попапе, чтобы всегда можно было подсмотреть, что же там делает q d w a. Префиксы также имеют ключ bindings, прямо как в корне файла и дальше всё идёт по рекурсии. Биндинги экшонов же имеют ключ actionId, в котором лежит id нужного мне экшона. Пример конфига генерируется при первом использовании Ataman.

Пример конфига
bindings { # корень всего конфига
  c { # группа биндингиов, начинающаяся с префикса 'c'
    description: Code...
    bindings {
      # биндинги привязываются к экшонам через actionId
      r { actionId: RefactoringMenu, description: Refactor this... }
      f { actionId: ReformatCode, description: Reformat code }
      c { # группы биндингов могут вкладываться друг в друга
        description: Compile/Run...
        bindings { 
          a { actionId: RunAnything, description: Run Anything... }
          r { actionId: ReRun, description: Rerun last build }
        }
        # actionId: ... -- лучше так не делать, тут уже есть binding
      }
    }
  }
}

Где брать actionId?

actionId нужного вам экшена можно легко нагуглить, например здесь или здесь. Кроме того, в плагине IdeaVim, который я также рекомендую попробовать, есть режим трекинга айдишников. Просто включаю его – и каждый экшен сопровождается его айдишником во всплывашке справа внизу IDE. Если хочется такую же фичу в Ataman – я охотно принимаю пулл-реквесты.

IdeaVim? Ataman с ним интегрируется?

Да! Ataman вообще возник в ответ на фрустрацию от того, что IdeaVim не умеет в leader-key вне активного Editor. Если фокус перешел на Logcat или дерево проекта – все мои биндинги превращались в тыкву. Я давно хотел показать прелесть leader key подхода людям, не знакомым с Vim, поэтому идея написать отдельный плагин быстро была воплощена в жизнь. Для того чтобы использовать в качестве лидера традиционные для Vim SPACE или BACK_SLASH, в Ataman есть специальный экшн Transparent Leader, который работает как лидер только если ваш фокус вне текстового поля. В конфиге же IdeaVim следует прописать обычный экшон, который будет работать несмотря на фокус на Editor.

nnoremap <Space> :action LeaderAction<cr>
vnoremap <Space> :action LeaderAction<cr>

Конец

На этом всё, скачивайте плагин, ставьте звёздочки на гитхабе и в Jetbrains Marketplace, пишите отзывы и заводите на ишшьюсы на баги и хотелки.

Adblock test (Why?)

Комментариев нет:

Отправить комментарий