В этом посте не будет вводных слов и примечаний: те, кто знает что собой представляют IDE и Emacs, но ещё не довели свой файл конфигурации до ума, возможно, найдут для себя что-то интересное. Те же, кто использует новомодные текстовые редакторы, скорее всего обойдут данную заметку стороной, хотя... ребят, постойте! Зачем сидеть на новом условно-бесплатном, если старые проверенные временем редакторы могут быть так же хороши? Ну, вы поняли: предположительно вторая категория возможных читателей это sublime'ры. Приступим же.
Основные пакеты
Это о тех пакетах, которые пригодятся всегда, вне зависимости от используемого
языка программирования и личных пристрастий. Среди них имеются как уже
встроенные, так и те, что ещё предстоит поставить. Прошу обратить внимание:
конфигурация строится на основе .emacs.d
от purcell и в ней для удобства
определены некоторые нестандартные функции.
Напомню, что настройка осуществляется в вашем конфигурационном файле, таком как
.emacs
или же (что удобно когда настроек и пакетов множество) в файле
.emacs.d/init.el
, где подгружаются файлы, в каждом из которых описаны
настройки только для его собственного пакета.
У автора структура каталога emacs выглядит следующим образом:
~/.emacs.d/
├── init.el
├── lisp
│ ├── init-css.el
│ ├── init-ruby-mode.el
├── snippets
│ ├── css-mode
└── themes
└── railscasts-theme.el
В init.el
подгружаются файлы из директории lisp
. Каждый файл описывает какой
пакет здесь необходимо загрузить и какие настройки для этого пакета
использовать. Идея была украдена у человека с ником purcell, о чём уже
упоминалось во вводной статье.
В «умолчательной» комплектации emacs содержит пакет ido, который
позволит с лёгкостью перемещаться между открытыми буферами нажатием клавиш C-x b
.
Потребуем его загрузки при старте редактора и сообщим о необходимости
использовать данный функционал сразу.
; init.el
(require 'ido)
(ido-mode t)
(require 'init-yasnippet)
(require-package 'autopair)
(autopair-global-mode)
Также хорош на вкус знаменитый YASnippet, поставляющий коллекцию сниппетов для самых разных языков программирования. Имеются горячие клавиши и возможность добавления сниппетов собственных. Впрочем, если есть необходимость интерактивной вставки (с параметрами), лучше написать свою функцию.
Настройки для YASnippet:
; init-yasnippet.el
(require-package 'yasnippet)
(yas-global-mode 1)
; где лежат сниппеты
(setq yas-snippet-dirs
'("~/.emacs.d/snippets" ))
(provide 'init-yasnippet)
Самописные сниппеты должны располагаться в поддиректории, соответствующей имени включаемого режима. Это может быть prog-mode, ruby-mode, css-mode и прочие.
И ещё одна незаменимая вещь: autopair автоматически закрывает парные скобки и
кавычки. Включение global-mode
активирует такое поведение всюду, даже в
plain text файлах.
Web-mode
Для примера настроим умное автодополнение в JavaScript и Ruby, позаботимся о закрытии HTML-тегов, подсветке всего и вся. Описание дано короткое: в случае возникновения желания разобраться подробнее следует обратиться к описанию того или иного пакета, которое быстро ищется при помощи google. Большинство пакетов также лежит (и ищется) на github.com.
Вариантов настройки может быть несколько: автором предлагаются лишь некоторые из них. Прежде всего, это включение таких пакетов как web-mode (автозакрытие парных HTML-тегов, подсветка js, html, erb), css-mode (встроен изначально, дополнительно к нему можно настроить поддержку sass и less).
;;; Web-mode
(require-package 'web-mode)
; с какими файлами ассоциировать web-mode
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode))
(add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
; настройка отступов
(setq web-mode-markup-indent-offset 2)
(setq web-mode-css-indent-offset 2)
(setq web-mode-code-indent-offset 2)
; сниппеты и автозакрытие парных скобок
(setq web-mode-extra-snippets '(("erb" . (("name" . ("beg" . "end"))))
))
(setq web-mode-extra-auto-pairs '(("erb" . (("open" "close")))
))
; подсвечивать текущий элемент
(setq web-mode-enable-current-element-highlight t)
Данный пакет незаменим в случае, если вам приходится работать с разного рода шаблонизаторами да и просто чистым HTML. А ежели ещё применить чуток фантазии и написать несколько ya-сниппетов... в общем, обязательно попробуйте.
JavaScript
А что насчёт JavaScript?
;;; JS
(require-package 'json-mode)
(require-package 'js2-mode)
(require-package 'ac-js2)
(require-package 'coffee-mode)
(require-package 'tern)
(require-package 'tern-auto-complete)
(add-hook 'js-mode-hook (lambda () (tern-mode t)))
(eval-after-load 'tern
'(progn
(require 'tern-auto-complete)
(tern-ac-setup)))
Как уже было упомянуто выше, для тонкой настройки рекомендуется обратиться к
документации пакета. Здесь же хочется поставить акцент на последнем пакете:
tern. Tern обеспечивает автодополнение методов JavaScript, но для своей работы
требует предварительной установки node.js
с пакетным менеджером
npm
:
# emerge -pav net-libs/nodejs
# npm install -g tern
После проведения этой процедуры можно активировать tern-mode
Весьма удобно, не так ли?
Ruby
Здесь следует сесть и подумать что приходит на ум при слове «ruby». Пожалуй, это такие вещи как сам интерпретатор, подсветка синтаксиса и автодополнение методов подобно тому, как мы реализовали её в JavaScript тоже пригодилась бы, ещё rvm с возможностью переключаться между используемыми гемами, rails, тестирование кода с rspec... много всего. Что ж, давайте по-порядку.
Перво-наперво надо бы активировать сам ruby-mode и связать его с некоторыми
часто используемыми файлами, которые не имеют расширения .rb
.
(require-package 'ruby-mode)
(require-package 'ruby-hash-syntax)
(add-auto-mode 'ruby-mode
"Rakefile\\'" "\\.rake\\'" "\\.rxml\\'"
"\\.rjs\\'" "\\.irbrc\\'" "\\.pryrc\\'" "\\.builder\\'" "\\.ru\\'"
"\\.gemspec\\'" "Gemfile\\'")
Для тех, кто использует rvm, неплохо было бы позаботиться о возможности интеграции оного в emacs, чем мы, собственно, и займёмся.
(require-package 'rvm)
(rvm-use-default)
; для связки rvm+robe
(defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate)
(rvm-activate-corresponding-ruby))
Emacs умеет запускать терминал, что избавляет от необходимости постоянно переключаться между окнами. Но как запустить irb, не открывая юниксовый shell? Для этого существует inf-ruby.
(unless (package-installed-p 'inf-ruby)
(package-install 'inf-ruby))
(autoload 'inf-ruby "inf-ruby" "Run an inferior Ruby process" t)
(add-hook 'ruby-mode-hook 'inf-ruby-minor-mode)
Часто (если не сказать всегда) ruby ассоциируют с его «киллер-фичей»: фреймворком Ruby On Rails. И здесь emacs'еров ждёт много замечательных вещей.
Начнём с подключения пакета rinari, который поможет быстро перемещаться между каталогами проекта, запускать встроенный веб-сервер и собственную консоль рельсов.
(require-package 'rinari)
(after-load 'rinari
(diminish 'rinari-minor-mode "Rin"))
(global-rinari-mode)
(defun update-rails-ctags ()
(interactive)
(let ((default-directory (or (rinari-root) default-directory)))
(shell-command (concat "ctags -a -e -f " rinari-tags-file-name " --tag-relative -R app lib vendor test"))))
Что получим на выходе:
Но этого мало! Мало, потому что желательно иметь возможность запускать тесты. Да, прямо в emacs. И rspec-mode будет здесь хорошим помощником. С ним можно запустить как полный набор тестов, так и протестировать единственный spec-файл.
(require-package 'rspec-mode)
(eval-after-load 'rspec-mode
'(rspec-install-snippets))
О том, как выбрать нужное, речь пойдёт чуть позже.
Небесполезная штука: подсветка блоков. Иногда это может оказать весомую помощь
при работе с большим (очень большим) файлом. С задачей справляется
ruby-blocks, хотя он имеет недостаток: при загрузке стандартным методом
(elpa) пакетик куражится. Поэтому предлагается взять соответствующий файл
у его автора и поместить в lisp/init-ruby-block.el
.
; init.el
(require 'init-ruby-block)
(ruby-block-mode t)
(setq ruby-block-highlight-toggle t)
Наконец, вспомним об автодополнении для чего будем использовать robe.
Robe не будет работать без активированного inf-ruby, иначе говоря без
запущенного процесса ruby также как tern без установленного nodejs
.
Поэтому есть два пути: последовательно включить соответствующие режимы или
попробовать автоматизировать это дело. С последним при использовании rvm (без
установленного в /usr/bin
ruby) у автора возникли временные сложности, коих не
должно наблюдаться в случае, если руби установлен в директорию по-умолчанию.
(require-package 'robe)
; для работы с rvm
(defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate)
(rvm-activate-corresponding-ruby))
(after-load 'ruby-mode
(add-hook 'ruby-mode-hook 'robe-mode))
(after-load 'robe
(add-hook 'robe-mode-hook 'ac-robe-setup))
(add-hook 'robe-mode-hook
(lambda ()
(add-to-list 'ac-sources 'ac-source-robe)
(set-auto-complete-as-completion-at-point-function)))
Далее предлагается лицезреть достаточно большой кусок кода, благодаря которому «автозакрываются» блоки в erb-файлах, а также происходит проверка на ошибки.
(require-package 'mmm-mode)
(defun sanityinc/ensure-mmm-erb-loaded ()
(require 'mmm-erb))
(require 'derived)
(defun sanityinc/set-up-mode-for-erb (mode)
(add-hook (derived-mode-hook-name mode) 'sanityinc/ensure-mmm-erb-loaded)
(mmm-add-mode-ext-class mode "\\.erb\\'" 'erb))
(let ((html-erb-modes '(html-mode html-erb-mode nxml-mode)))
(dolist (mode html-erb-modes)
(sanityinc/set-up-mode-for-erb mode)
(mmm-add-mode-ext-class mode "\\.r?html\\(\\.erb\\)?\\'" 'html-js)
(mmm-add-mode-ext-class mode "\\.r?html\\(\\.erb\\)?\\'" 'html-css)))
(mmm-add-mode-ext-class 'html-erb-mode "\\.jst\\.ejs\\'" 'ejs)
(add-auto-mode 'html-erb-mode "\\.rhtml\\'" "\\.html\\.erb\\'")
(add-to-list 'auto-mode-alist '("\\.jst\\.ejs\\'" . html-erb-mode))
(mmm-add-mode-ext-class 'yaml-mode "\\.yaml\\'" 'erb)
(dolist (mode (list 'js-mode 'js2-mode 'js3-mode))
(mmm-add-mode-ext-class mode "\\.js\\.erb\\'" 'erb))
Навигация по проекту
В заключение хотелось бы порекомендовать projectile.
(require 'init-projectile)
Этот пакет упростит навигацию по файлам и директориям отдельного проекта. Имеется специальная версия для RoR: projectile-rails. Думается, при наличии одного проекта можно обойтись без подобных излишеств. А вот если проектов множество, и в каждом одинаковая структура, и между ними нужно переключаться! Без projectile одна только навигация может быть аду подобна.
Помимо вышеперечисленного рекомендуется также обзавестить поддержкой emmet, поставить sr-speedbar и... написать пару-тройку сниппетов.
И, как обещалось ранее, примеры доступных нам полезных команд.
описание | команда |
---|---|
сравнить содержимое буфера и оригинального файла | diff-buffer-with-file |
проверить грамотность автора | flyspell-buffer |
закомментировать выделенную область | comment-region |
раскоментировать её же | uncomment-region |
включить режим web-mode | web-mode |
включить режим tern-mode | tern-mode |
запустить ruby shell | inf-ruby |
запустить robe | robe-start |
прогнать текущий тест | rspec-verify |
запустить весь набор тестов | rspec-verify-all |
запустить консоль rails | rinari-console |
найти файл в проекте при помощи rinari | rinari-find-file-in-project |
выбрать версию ruby и gemset | rvm-use |
Сегодня это всё. Главная мысль: vim и emacs не уступают многим графическим платным/условно-работоспособным инструментам, а в некоторых ситуациях превосходят их.