вторник, 6 октября 2015 г.

Мой первый пакет для Emacs: multi-compile

Более актуальная версия
Я часто пишу заметки о Emacs, в формате: скопируйте вот эти строки подкорректируйте под себя, вставьте в конфиг, установите ещё вот этот плагин и т.п. Сегодня решил выйти на "новый уровень" и сделал полноценный пакет для Emacs и что бы нанести пользу максимально большой аудитории - разместил его в melpa. Конечно подготовить его несколько сложнее, чем просто пример конфига для блога, но для меня это своеобразное возвращение долгов за используемые мной open-source решения.


Начну с описания проблемы. Для компиляции проектов обычно используют стандартный модуль compile. Если вкратце то для его настройки нужно для интересующего вас режима переопределить локальную переменную compile-command командой, которую модуль compile выполнит при компиляции. Допустим для "c++-mode" она может быть вот такой:
make --no-print-directory -C <make-dir>

Проблема подхода в том, что одной команды не хватает, часто помимо компиляции требуется ещё запуск тестов, компиляция в release\debug, запуск скомпилированного кода и т.п. Как вариант решения предлагают создавать для каждого режима свой набор функций, по одной на каждый подобный use case, где будет вызываться "compile" с нужными параметрами и потом вешать их на горячие клавиши. Это мягко говоря не удобно, поскольку все простые сочетания давно заняты, а запоминать 5-6 новых пальцедробительных не хочется.

Мне кажется удобным решением было бы при компиляции показывать меню со всеми вариантами действий, что собственно я и реализовал, выглядит это вот так:

Настройка для именно этого меню:
(require 'multi-compile)

(setq multi-compile-alist '(
    (rust-mode . (("rust-debug" . "cargo run")
                  ("rust-release" . "cargo run --release")
                  ("rust-test" . "cargo test")))
    ))
Ну и перед включением конечно нужно установить пакет, (предварительно подключив Melpa репозиторий, если его у вас нет):
M-x package-install multi-compile
В командах компиляции можно использовать шаблоны:
(setq multi-compile-alist '(
    (c++-mode . (("cpp-run" . "make --no-print-directory -C %make-dir")))
    (rust-mode . (("rust-debug" . "cargo run")
                  ("rust-release" . "cargo run --release")
                  ("rust-test" . "cargo test")))
    ))
Полный список реализованных шаблонов вот такой:
  • "%path" - "/tmp/prj/file.rs" - полный путь к открытому файлу.
  • "%dir" - "tmp/prj" - директория, где он лежит.
  • "%file-name" - "file.rs" - имя текущего файла.
  • "%file-sans" - "file" - имя без расширения.
  • "%file-ext" - "rs" - расширение файла.
  • "%make-dir" - "tmp" - просматривается вся иерархия директорий текущего файла и возвращается та, в которой лежит "Makefile".
Шаблоны файлов не обязательно задавать для всего режима, можно использовать регулярные выражения для имени файла:
(setq multi-compile-alist '(
    ("\\.txt\\'" . (("text-filename" . "echo %file-name")))
    (c++-mode . (("cpp-run" . "make --no-print-directory -C %make-dir")))
    (rust-mode . (("rust-debug" . "cargo run")
                  ("rust-release" . "cargo run --release")
                  ("rust-test" . "cargo test")))
    ))
Теперь по отображаемому меню: по умолчанию оно формируется через ido, но можно использовать helm, а для сторонников default конфигурации Emacs есть опция "default":
;;(setq multi-compile-completion-system 'ido)
(setq multi-compile-completion-system 'helm)
;; (setq multi-compile-completion-system 'default)
Ну и собственно вызов меню компиляции осуществляется через "M-x multi-compile-run". Какие-то горячие клавиши я добавлять не стал, каждый добавит свои по вкусу.

Если кому интересно, то исходники лежат на github и вот ссылка на сам пакет multi-compile на Melpa.

2 комментария:

  1. Здравствуйте!
    А Вы сами чем пользуетесь, ido или helm? Мне второй в принципе нравится, но тормозит иногда.

    ОтветитьУдалить
    Ответы
    1. Я - Ido, он как-то удобнее что ли... несколько раз пробовал на helm перейти - не получилось

      Удалить