Table Of Content1
Д.Бушенко
А.Отт
Программирование Emacs для редактирования и рефакторинга
кода. – Epam, 2011. – 48c.
В пособии показаны основы редактора Emacs, начала програм-
мирования на Emacs Lisp; разобраны несколько примеров скриптов
и наиболее часто употребляемые функции. Особый акцент сделан
на применении Emacs Lisp для разработки программ автома-
тизированного рефакторинга кода.
2
БЛАГОДАРНОСТИ
Авторы выражают благодарность всем, кто помогал им в работе:
компании Epam System за поддержку в создании пособия; Амине
Идиговой и Руслану Щуцкому за дизайн, верстку и печать книги;
Василию Ременюку за организацию встречи любителей
функционального программирования (scala.by), для которой и было
написано это пособие.
К ЧИТАТЕЛЮ
Друг, ты держишь в руках первое издание книги о
программировании Emacs. Мы надеемся, что в будущем сможем
добавить много материала и выпустить новое издание. С твоей
помощью мы можем сделать его лучше! Если ты заметил ошибку,
или хочешь предложить свой скрипт, тему или даже главу –
напиши об этом авторам. Мы будем тебе признательны!
Дмитрий Бушенко ([email protected])
Алекс Отт ([email protected])
3
ОГЛАВЛЕНИЕ
Благодарности .................................................................................... 3
К читателю ......................................................................................... 3
Оглавление ......................................................................................... 4
Введение ............................................................................................ 6
Коротко о GNU Emacs ....................................................................... 8
Получение справки и поиск информации ..................................... 9
Буфера, пакеты, режимы................................................................ 9
Основы Emacs Lisp .......................................................................... 11
Lisp, формы, списки и префиксная нотация................................ 11
Как писать программы на Emacs Lisp ......................................... 12
Типы данных ................................................................................ 13
Символы и переменные ............................................................... 15
Объявление функций ................................................................... 17
Управление ходом программы .................................................... 17
Работа со списками ...................................................................... 21
Примеры elisp-скриптов .................................................................. 24
Импорт Java класса в программе на Clojure ................................ 24
Генерация аксессоров в классе Java ............................................ 27
Генерация и инициализация полей Java-класса в Android-
приложении .................................................................................. 29
Преобразование html-файла в haml-формат ................................ 33
Создание конструктора для неизменяемых объектов ................. 35
Справочник часто употребимых функций ...................................... 39
Перемещение курсора и получение позиции .............................. 39
Группа функций point- ............................................................. 39
goto-char.................................................................................... 39
line-number-at-pos ..................................................................... 39
current-column ........................................................................... 39
Группа функций beginning-of-/end-of- ..................................... 40
Регион/Выделение текста ............................................................ 40
region-active-p ........................................................................... 40
Группа функций region- ........................................................... 40
kill-region .................................................................................. 40
kill-ring-save .............................................................................. 40
Группа функций forward-/backward-........................................ 41
Группа функций search- ........................................................... 41
4
Работа с буфером ......................................................................... 42
buffer-name ............................................................................... 42
buffer-list ................................................................................... 42
with-current-buffer ..................................................................... 42
switch-to-buffer ......................................................................... 43
current-word .............................................................................. 43
insert .......................................................................................... 43
count-lines ................................................................................. 44
find-file ...................................................................................... 44
delete-and-extract-region ............................................................ 44
Прочее .......................................................................................... 44
save-excursion ........................................................................... 45
Группа функций completing-read/ido-completing-read ............. 45
Дополнительная информация .......................................................... 47
Другие полезные пакеты.............................................................. 48
Литература ................................................................................... 48
5
ВВЕДЕНИЕ
Большая часть времени программиста занята написанием и
редактированием программного кода. Существует множество
инструментов, позволяющих быстро разрабатывать программный
продукт, автоматизировать типовые задачи, проводить
рефакторинг. Среди них – известные среды интегрированной
разработки, сложные текстовые редакторы и консольные утилиты.
Каждый из этих инструментов позволяет легко решать свой
собственный класс задач. Здесь мы будем рассматривать только
задачу автоматизированного редактирования и рефакторинга кода.
Сравнивая возможности современных IDE, таких как MS Visual
Studio, Eclipse, Netbeans, Idea, легко заметить, что они обладают
схожей функциональностью. У них есть сниппеты и средства
автоматического рефакторинга, например, переименование класса
или инкапсуляция члена класса в аксессоре. Это очень хорошие
средства, зачастую они покрывают большую часть потребностей
программиста. Но что делать, если появились задачи, для которых
в IDE еще нет решения?
Сложные задачи, для которых пока нет готовых инструментов,
чаще всего возникают на переднем крае Computer Science. Они
появляются вместе с новыми языками программирования и
экспериментальными технологиями. Больше всего нетипичных
задач у любителей немейнстримных языков программирования,
таких как Clojure, Scala, Haskell и т.д.
Что же делать, если вы пользуетесь новейшими языками и
технологиями, а ваш любимый текстовый редактор заставляет
писать массу кода вручную? Разумеется, выбрать такой редактор,
который может автоматизировать повторяющиеся задачи!
В этом пособии мы вкратце рассмотрим возможности текстового
редактора GNU Emacs, позволяющие автоматизировать рутину.
Emacs – программируемый текстовый редактор, именно поэтому
он идеально подходит для решения нетипичных задач. Если в нем
не хватает какой-то возможности, то ее всегда можно добавить
самостоятельно.
Emacs написан, в основном, на языке Emacs Lisp (далее – elisp). Мы
воспользуемся этим языком для того, чтобы реализовать нужные
6
нам функции текстового редактора. Поначалу это, конечно, может
показаться сложным делом. Но усилия, потраченные на изучение
Emacs и elisp, впоследствии окупятся.
7
КОРОТКО О GNU EMACS
Emacs — программа с длиной историей. Еще недавно
существовало несколько популярных ее разновидностей (XEmacs,
SXEmacs, GNU Emacs), но в настоящее время, самой активно
развивающейся является GNU Emacs. Стабильной версией GNU
Emacs является версия 23. Но мы рекомендуем использовать бета-
версии GNU Emacs 24, в которой реализовано много новинок,
включая пакетный менеджер, и многое другое. Пользователи Linux
могут найти сборки для своих дистрибутивов, например, для
Debian & Ubuntu1. Пользователи Windows могут получить
бинарную сборку2.
При запуске, Emacs читает свою конфигурацию из файла
~/.emacs.d/init.el (или из ~/.emacs, если он существует). Эта
конфигурация является программой на Emacs и описывает какие
пакеты должны быть загружены, переменные выставлены и т.п. Но
вначале, вам не обязательно все писать самим — можете начать с
адаптации существующих конфигураций, например, из проекта
Emacs Starter Kit3, который был описан на русском языке4. Просто
следуйте описанным шагам.
Поведение Emacs можно настраивать почти не зная Emacs Lisp —
используя механизм Customize. Имеется несколько команд для
установки значений переменных, шрифтов (faces) и т.п. Самыми
популярными являются команды customize-variable, customize-
group & customize-face. Эти команды можно запустить при помощи
сочетания клавиш M-x <команда>, затем задайте имя переменной
или группы переменных (используйте TAB для дополнения имен).
Подробней о работе с Emacs вы можете в руководстве (есть и
русская версия, но она для версии 20.x), которое идет вместе с ним,
или в следующей статье5.
1 http://emacs.naquadah.org/
2 http://alpha.gnu.org/gnu/emacs/windows/
3 https://github.com/technomancy/emacs-starter-kit
4 http://habrahabr.ru/blogs/emacs/94256/ ,
http://zahardzhan.github.com/2010/emacs-starter-kit-the-program.html
5 http://alexott.net/ru/writings/altlinux-emacs/index.html
8
Получение справки и поиск информации
В поставке GNU Emacs имеется вся информация необходимая для
начала работы с ним и его программирования. Для начинающих
пользователей будет полезен учебник Emacs (вызываемый
сочетанием клавиш C-h t), переведенный на разные языки, в том
числе и на русский. Подробные руководства по Emacs & Emacs
Lisp (а также многим другим пакетам и программам) поставляются
в формате info, и вы можете обратиться к ним через меню или
набрав сочетание C-h i.
Кроме того, вы можете получить подробную информацию о
переменных (текущее значение, описание) с помощью команды
describe-variable (C-h v), функциях (описание, где определена) --
клавиши (C-h f) и текущем режиме (сочетание клавиш C-h m).
Буфера, пакеты, режимы
Практически вся функциональность Emacs (кроме низкоуровневых
модулей) реализована на Emacs Lisp. В состав дистрибутива входит
огромное количество пакетов расширений. Начиная с версии 24, в
состав Emacs входит менеджер пакетов, который используется для
установки "внешних" пакетов, в основном это release-версии. Если
же вы хотите использовать bleeding edge-версии, то можете ставить
пакеты сами (правда их потом неудобно поддерживать), либо
воспользоваться пакетом el-get6, который автоматизирует
установку и поддержание пакетов в актуальном состоянии.
Работа с текстом происходит в буферах Emacs, которые обычно
связаны с файлами на диске. Каждый буфер имеет один основной
(major) режим, который определяет, как текст будет
редактироваться, и может также иметь несколько дополнительных
(minor) режимов. Например, основными режимами являются
режимы для редактирования исходного кода на C/C++, Java,
Clojure, Scala и т.д., а дополнительными режимами являются режим
подсветки ключевых слов (font-lock), проверки орфографии и т.д.
Посмотреть список включенных режимов для текущего буфера
можно при помощи сочетания клавиш C-h m (вам также будут
показаны все keybindings — имеющиеся сочетания клавиш, и
команды к ним привязанные). Обычно основные режимы
включаются автоматически, в зависимости от расширения файла,
6 https://github.com/dimitri/el-get
9
но вы можете включить их явно с помощью M-x <name-mode>
(например, M-x clojure-mode) или изменив маппинг между именем
файла и режимом, например:
(add-to-list 'auto-mode-alist '("\\.ipp$" . c++-mode))
Режимы могут иметь собственные настройки, обычно это
переменные и хуки (набор функций, которые будут вызваны при
включении режима). Переменные могут быть глобальными —
общими для всех буферов, и локальными — специфическими для
конкретных буферов. Обычно в описании переменных (сочетание
C-h v) можно увидеть — локальная эта переменная или глобальная.
Глобальные переменные устанавливаются либо через M-x
customize-variable, либо с помощью setq из Emacs Lisp. А
локальные переменные в основном устанавливаются из хуков.
Хук (hook) — это набор функций без аргументов, которые будут
вызваны при включении режима (открытии файла, или создании
буфера, или явном включении режима). Для каждого режима вы
можете определить множество таких функций, которые будут
вызваны по очереди. Обычно с помощью таких хуков
устанавливаются значения для локальных переменных, локальные
привязки клавиш, дополнительные режимы и т.п. Функции
добавляются в хук с помощью функции add-hook, а удаляются с
помощью remove-hook (удаление хуков – редко встречающаяся
операция). Например:
(defun common-hook ()
(local-set-key "\C-c:" 'uncomment-region)
(local-set-key "\C-c;" 'comment-region)
(local-set-key "\C-c\C-c" 'comment-region)
(font-lock-mode 1))
(add-hook 'emacs-lisp-mode-hook 'common-hook)
(defun elisp-mode-hook ()
;; set local variables
(setq indent-tabs-mode t)
;; enable minor modes
(turn-on-eldoc-mode)
(paredit-mode 1)
;; bind local keys
(local-set-key [(control c) /] 'semantic-ia-complete-symbol))
(add-hook 'emacs-lisp-mode-hook 'elisp-mode-hook)
10