Emacs Daemon против долгого старта Emacs

18 авг. 2013

Бытует мнение, что Emacs — это «тормоз» мира редакторов, из-за долгой загрузки файлов инициализации во время запуска. Что буквально вынуждает часть пользователей постоянно держать Emacs открытым. Хотя волшебная таблетка придумана давно: запуск фонового процесса Emacs Daemon и замена вызова Emacs на запуск Emacs Client. Фоновый процесс (демон) берёт на себя инициализацию настроек, тогда как редактор (клиент) просто подключается к нему во время старта, экономя ваше время.

Основы работы с Emacs Daemon

Emacs Daemon стартует по команде

$ emacs --daemon

инициализирует настройки редактора и затем запускает сервер, который отслеживает подключения клиента. В свою очередь, Emacs Client открывает сессию Emacs либо в консоли:

$ emacsclient -t

либо в новом фрейме:

$ emacsclient -c

Однако, если демон не был запущен, то подключения не произойдёт; чтобы исключить подобный казус, задействуем опцию -a:

$ emacsclient -c -a ""

Тогда Emacs Client произведёт запуск демона самостоятельно, если этого не было сделано до него. Выход из Emacs с завершением работы клиента осуществляется по хоткею C-x #.

Emacs Daemon хранит состояние буферов между подключениями клиента, остановить его можно командой M-x kill-emacs или M-x save-buffers-kill-emacs, последняя позволяет сохранить буферы редактора перед завершением. За пределами Emacs можно не только запускать Emacs Client, но и передавать ему на исполнение Elisp-выражения. Например, выполнить остановку демона:

$ emacsclient -e "(kill-emacs)"

Ложка дёгтя заключается в использовании сборки Emacs с Gtk: давний баг приводит к краху Emacs Daemon после закрытия окна редактора. Сборка на основе Lucid Toolkit избавлена от этого бага (гентушники, лениво потягиваясь, ставят USE="Xaw3d -gtk -gtk3").

Запуск и остановка Emacs Daemon

Разумно это возложить на систему инициализации Linux или совместить с запуском X Window System. Второй вариант предполагает внесение команд запуска и остановки Emacs Daemon в файлы ~/.bash_profile и ~/.bash_logout, соответственно.

Ниже в этом параграфе речь пойдёт о Gentoo и пакете emacs-daemon, чьё назначение, очевидно, следует из названия. Каждому пользователю username для подключения к Emacs Daemon необходимо иметь свой экземпляр демона, который запускался бы с привилегиями пользователя. Создайте символьную ссылку в директории /etc/init.d/ (но не копируйте сам скрипт, что лишит вас важных обновлений):

# cd /etc/init.d/
# ln -s emacs emacs.username

и скрипт запуска автоматически определит пользователя по username. Теперь запустим демона

# /etc/init.d/emacs.username start

а также добавим в загрузку

# rc-update add emacs.username default

Настраивается демон с помощью файла /etc/conf.d/emacs. Скрипты, указанные в переменных EMACS_START и EMACS_STOP, запускаются на соответствующих стадиях. Для корректного завершения Emacs Daemon настоятельно рекомендую указать следующий скрипт для остановки:

EMACS_STOP="/usr/libexec/emacs/emacs-stop.sh"

который идёт вместе с пакетом emacs-daemon. Для подробного вывода сообщений при инициализации просто установите переменную

EMACS_DEBUG="y"

Подводные камни Emacs Daemon

При использовании не консольного шрифта к ошибке ведёт стандартная установка шрифта в файле инициализации

(set-face-attribute 'default nil :font FONT)

где FONT — имя шрифта в виде строки, например, "Droid Sans Mono 10". Зато подойдёт другой способ:

(add-to-list 'default-frame-alist '(font . FONT))

Также во время запуска демона исключите вопросы от Emacs, так как возможности дать ответ у вас не будет, и на первом же вопросе загрузка прекратится. Например, если сохранение сессий Emacs возложено на плечи DeskTop, то следует заранее определиться с его поведением на случай конфликта между используемой и сохранённой сессиями. Для безусловного сохранения сессий задайте переменной desktop-save значение t вместо ask-if-new, используемого по умолчанию. За загрузку конфликтующей сессии отвечает переменная desktop-load-locked-desktop: значение t разрешает работу с сессией другого Emacs Daemon, тогда как nil, наоборот, запрещает. Использовать nil имеет смысл тогда, когда в системе есть несколько пользователей, имеющих доступ к одним и тем же сессиям DeskTop. В остальном, смело можно использовать значение t.

Наверх

Наверх