вторник, 5 ноября 2013 г.

popup-switcher - переключение буферов и навигация по функциям, используя TUI-меню

Эргономика промышленных решений

С некоторого времени для разработки на Java я использую IntelliJ IDEA. Какова там навигация по файлам или по методам! Нажимаешь C-S-n (или C-n для классов) и появляется окошко поиска со списком. Вводишь буквы из названия файла и список сокращается - самый удобный способ навигации по файлам проекта. Аналогично C-F12 для навигации по методам открытого класса - интерактивно изменяющееся меню на основе вводимых символов из имени метода. Ничего эргономичнее до этого не видел.

Изящество и красота текстовых интерфейсов

В emacs это все есть, безусловно, но выглядит это... в emacs вообще все выглядит абсолютно самобытно. Именно самобытно. Думаю, вряд ли кто-то скажет, что emacs предоставляет GUI - интерфейс, возможно лишь местами. В большинстве случаев, emacs не предоставляет и CLI - да, он часто интегрируется и CLI-инструментами: CLI-утилита является back-end-ом, а emacs предоставляет свою обертку, он имеет внутренние оболочки shell-ы и repl-ы, может сам быть запущен из внешних, но этот интерфейс, хоть и играет важную роль, все же является скорее вспомогательным. Выходит TUI? Во-многом, да. Но он зачастую деформируется механизмом окон. Если взять, например, mc, far, ndd, старые, времен DOS, среды разработки, антивирусы, архиваторы, предоставляющие TUI-интерфейс, то там любое диалоговое окно - часть общего текстового рабочего пространства. В emacs же окна жестко механически разделяют текстовые области. Данный подход стал идиоматическим. Скажем, org-mode и magit - примеры эффективного разделения возможностей TUI в рамках основного буфера и добавления вспомогательных окон и буферов. Такие буферы имеют свои специальные режимы с удобными таблицами ключей. Может оно и хорошо, и у такого подхода безусловно есть свои плюсы, но всегда ли это нужно? На каждый чих создается новое окно и в нем свой буфер. Лично мне куда приятнее чаще видеть старый-добрый TUI-интерфейс там, где создание отдельного окна избыточно.

TUI в emacs

Библиотеки popup-el (выпадающие меню) и direx-el (деревья) - примеры расширений, предоставляющих некоторую функциональность TUI. К сожалению, предоставляется лишь некоторая часть возможных виджетов, но тем не менее, имеющиеся весьма удобны.

Так, например, первая из них позволила мне реализовать в TUI некоторые из идей, используемых в IntelliJ IDEA: popup-switcher. Вызов интерактивной функции

  • psw-switch-buffer - приведет к появлению списка открытых буферов. Ввод символов имени буфера будет сокращать список. Именно в качестве (еще одного) механизма переключения буферов и задумывался изначально popup-switcher, однако на самом деле, он может быть использован для переключения чего угодно (отсюда и название).
  • psw-switch-projectile-files - работает со всеми файлами проекта (файлы проекта рассматриваются в контексте расширения projectile).
  • psw-switch-function - работает с функциями/методами в текущем файле.
Пример навигации по буферам.
Пример навигации по функциям в файле с исходным кодом на Clojure.

Установка

Установка расширения довольно проста. Добавьте MELPA в вашу переменную package-archives (если у вас он еще не был добавлен):
 (require 'package)
 (add-to-list 'package-archives
              '("melpa" . "http://melpa.milkbox.net/packages/"))
 (package-initialize)
Далее popup-switcher устанавливается командой:
 M-x package-install [RET] popup-switcher [RET]
Кроме того, в файле инициализации .emacs необходимо указать:
 (require 'popup-switcher)

Настройка

После установки psw-in-window-center в значение t всплывающее меню будет появляться в середине окна. По умолчанию появляется в посередине меду левым краем окна и значением fill-column.
 (setq psw-in-window-center t)
Вы можете установить интерактивные функции переключения буферов и навигации по методам для определенных клавиатурных сочетаний на ваш вкус, например:
 (global-set-key [f2] 'psw-switch-buffer)
 (global-set-key (kbd "C-S-n") 'psw-switch-projectile-files)
Для активации возможности навигации по функциям/методам необходимо установить последнюю версию CEDET и подключить библиотеку eassist. Это не является обязательным, и вы можете использовать popup-switcher без CEDET (и, очевидно, без данной функциональности). Пример настройки:
 ;; Activate semantic
 (semantic-mode 1)
 
 ;; Load contrib library
 (add-to-list 'load-path "~/.emacs.d/cedet/contrib/")
 (require 'eassist)
 
 (eval-after-load "eassist"
   '(global-set-key [f3] 'psw-switch-function))

Добавление переключений

Добавлять новые применения механизма переключения очень просто, так функция psw-switch-buffer выглядит следующим образом:
 (defun psw-switch-buffer ()
    (interactive)
    (psw-switcher
     :items-list (psw-get-buffer-list)
     :item-name-getter 'buffer-name
     :switcher 'switch-to-buffer))
где
  • items-list - список, в котором осуществляется выбор (psw-get-buffer-list - просто использует встроеную функцию buffer-list с некоторыми дополнительными фильтрами).
  • item-name-getter - функция получения текстового обозначения каждого элемента списка в меню выбора.
  • switcher - функция, описывающая что делать с выбранным элементом.

Заключение

Для emacs существуют хоть и не всеобъемлющие, но весьма удобные библиотеки работы с TUI. Например, popup-el уже использующаяся в проектах auto-complete и emacs-jedi, а теперь и в popup-switcher.

Библиотека direx-el используется, например, в проекте emacs-jedi-direx. direx-el потенциально может выступать в качестве основы для более простого и современного аналога ECB. Конечно, в данном случае создание нового окна будет необходимо, но мне кажется, что это как раз тот случай, когда это оправдано.

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