Pull to refresh

Emacs для начинающих: elisp

Reading time 5 min
Views 15K
Введение


Сразу предупреждаю, что я не собираюсь писать ни учебник, ни
вводный курс Lisp и не претендую на какую либо полноту описания. А
собираюсь я дать некоторые полезные по моему мнению сведения, которые
помогут начинающим использовать emacs настраивать его по своему
усмотрению и писать несложные функции, которыми тоже можно будет
пользоваться в процессе использования emacs.

Emacs, как уже неоднократно везде упоминалось, представляет собой
комбинацию текстового редактора и интерпретатора Lisp. Нужно только
уметь этим воспользоваться.

Подготовка рабочего места


Для начала поднастроим наш emacs, чтобы нам было бы комфортно в нем
работать.

Вставим в наш .emacs следующие строки:

(setq auto-mode-alist
      (append
       '(
         ( "\\.el$". lisp-mode))))
(global-font-lock-mode 1)

Первый набор скобок сделает так, что при открытии файла с
расширением .el, в буфере автоматически включается режим работы с
текстами программ Lisp. Последняя строчка включает подсветку
синтаксиса. Раскрашивает операторы языка в разные приятные цвета. Это
реально помогает читать текст программы. Теперь, если мы редактировали
.emacs в emacs, перезапускаем его, чтобы он перечитал файл настроек.

Тут опытные товарищи подсказали, что приведенные операции делать не обязательно, так как нужные режимы включены в современных версиях emacs по умолчанию.


Постараемся все делать из емакса. Итак, нам нужно создать
директорию для наших экспериментальных файлов. И файл.

Предположим, мы находимся в домашнем директории (подразумеваем, что
мы на каком нибудь UNIX-е). Нажимаем:

| Клавиши               | Производимое действие                         |
|-----------------------+-----------------------------------------------|
| C-x C-f RET           | Переходим в режим dired в домашней директории |
| + Имя директории RET  | Создаем новую директорию                      |
| RET                   | Переходим в созданную директорию              |
| C-x C-f myfile.el RET | Открываем файл myfile.el                      |


Самые общие понятия и приемы работы


В лиспе нужно знать два понятия, переменные и функции. Вообще то
переменную можно рассматривать тоже как функцию, возвращающую
значение, присвоенное этой переменной. У переменных и функций есть
имена — последовательность символов. Если в программе заключить имя в
круглые скобки, оно выполнится как функция. Правда, если это имя
переменной, интерпретатор лиспа выдаст ошибку. В лиспе имена принято
записывать, разделяя логические части имени через дефис. Например
my-cool-function

Теперь о том, как вызываются функции. В отличие от, например, Си,
функции вызываются следующим образом:

(name-of-the-function arg1 arg2 arg3 ......)


Т.е. вызов функции заключен в скобки. Первое имя в скобках — имя
функции, остальные имена это аргументы. Так же, как и в Си, в качестве
аргументов могут выступать выражения, возвращающие значения, например
вызовы других функций, например:

(name-of-the-function arg1 (name-of-the-function) arg3 ......)


Это все хорошо, но как с этим работать? В emacs работать с этим
очень легко и просто. Давайте, для начала попробуем сложить 2 и
2. Запишем в нашем файле myfile.el следующее выражение:

(+ 2 2)


Попробуем его расшифровать. Символ "+" это функция,
складывающая два ее аргумента. следующие две двойки — аргументы
функций. Попробуем ее выполнить. Для этого ставим курсор emacs правее
правой скобки нашего выражения (вплотную) и нажимаем C-x e. Если все
сделано правильно, в минибуфере появится цифра "4". Ура, мы
выполнили наше выражение.


Для полноценного программирования принято использовать
переменные. Давайте попробуем это сделать. Для начала нужно присвоить
переменной значение.


(set 'myvar-variable 4)


Что мы здесь имеем?


| Имя            | Комментарий                                                       |
|----------------+-------------------------------------------------------------------|
| set            | Функция, присваивающая первому аргументу значение 2-го            |
| myvar-variable | Имя переменной, которой нужно присвоить значение                  |
| 4              | Присваиваемое значение                                            |
| '              | Значок, который показывает, что имя не должно возвращать значение |


Обратите внимание на заначек (одиночная кавычка), он не дает имени
переменной вернуть значение. Без него интерпретатор лисп будет
жаловаться на ошибку. Есть другой вариант функции присваивания, при
котором не нужно экранировать имя переменной кавычкой, setq. Для этой
функции запись будет выглядеть:


(setq myvar-variable 4)


Теперь, еще один удобный прием работы. Как посмотреть значение
присвоенное переменной? Для этого нужно поставить (можно прямо в
тексте программы) курсор правее имени переменной и нажать C-x e. В
минибуфере будет показано значение переменной. Обратите внимание, что
если вы попробуете это сделать с переменной, у которой стоит
экранирующая кавычка, значение показано не будет, экранированное имя
значение не возвращает.

Присвоение переменной строкового значения. Очень просто. Строка
заключается в кавычки.

(setq myvar-str-variable "My string")

Вывод сообщения в минибуфер.

(message "My message")


Вставка строки в буфер в текущем положении курсора:

(insert "My string")


Выполнение последовательности функций:

(progn
  (setq my-var "Hello")
  (message my-var))

Определение собственных функций


Нет ничего легче, чем определить собственную функцию. Синтаксис
определения такой:

(defun myf-test (a b ...)
  "Строка документации"
  (выражение)
  …
  (выражение))

В этом определении:

| что                   | Комментарий                                    |
|-----------------------+------------------------------------------------|
| defun                 | Ключевое слово для определения функции         |
| myf-test              | Имя функции                                    |
| (a b)                 | Список параметров                              |
| "Строка документации" | Строка документации. Выдается при C-h myf-test |
| (выражение)           | Выражения, выполняемые в теле функции          |


Примечание. Функция возвращает значение, возвращаемое ее последним выражением.

Попробуем для примера определить собственную функцию:

(progn
  (setq my-var "Hello")
  (message my-var))

Проверка:

  (myf-test 1 2)


Прием работы: Чтобы меньше было возни, при отладке функций, удобно пользоваться следующим приемом:


(progn
  (defun myf-test (a b)
    "Add first argument to second. Return result"
    (+ a b))
  (myf-test 1 2)
  )

Если помните, оператор "progn" выполняет список
выражений в его теле. В нашем случае, выполняется сначала определение
функции, затем вызывается на выполнение тестовый пример. Изменив что-то
в определении, можно моментально это проверить.

Но, есть одна заковыка, функции, определяемые таким образом, Вы не
можете вызвать на выполнение командой M-x "имя функции". Для
того, чтобы можно бы было это сделать, в определение функции нужно
вставить оператор "interactive":

(defun myf-test-1 ()
  "Add first argument to second. Return result"
  (interactive)
  (message "Hello"))

Выполнив это определение, и подав команду M-x myf-test-1 RET, Вы
получите в минибуфере слово Hello

Замечание: Для имен своих функций и переменных, желательно выбрать
и использовать свой уникальный префикс, так как в emacs глобальное
пространство имен. Я использую eik-, по имени-отчеству-фамилии. Вам
нужно выдумать что-то свое.

Заключение


Описанных сведений из Lisp, на мой взгляд достаточно, для начала
экспериментов с кастомизацией emacs. В основном кастомизация и
сводится к присваивании значений переменным emacs и написанию
собственных функций.

Литература


  1. В Ubuntu в комплект пакета emacs22 входит
    справочное пособие по Elisp. M-x info, C-s elisp
  2. Google
  3. Программирование на Emacs Lisp
Tags:
Hubs:
+31
Comments 35
Comments Comments 35

Articles