Как модулировать конфигурацию emacs?
Я решил переписать мои .emacs с нуля, и я хочу настроить что-то модульное, чтобы избежать страшного файла 1c + LoC init.el...
Я думаю, что есть некоторые основные проблемы, которые необходимо решить каждой конфигурации:
- глобальные параметры
- функции редактирования
- навигация (фреймы и буферы)
- сочетания клавиш
- настройки режимов
Пока я все еще общаюсь, чтобы думать о структуре, я ищу несколько указателей на то, как добиться этого.
Я посмотрел на некоторые .emacs на github и т.д., И, похоже, есть разные подходы, и нет предпочтительного способа пойти с этим, что немного запутывает.
Мне было бы интересно прочитать некоторые идеи о том, как структурировать такую настройку, и особенно некоторый связанный код elisp.
edit: Был доволен вещами, и у него не было много времени, чтобы поиграть с этим.
Попробуй предлагаемые методы через несколько дней и посмотри, что лучше всего, тем временем спасибо за все рекомендации!
edit2: Я использовал грамотный файл инициализации с org-mode, и это абсолютно потрясающе!
Я еще не установлен на определенном механизме загрузки, я использовал этот код, чтобы рекурсивно загружать каталог elisp, а затем требовать или что-либо из инструкций по установке.
(if (fboundp 'normal-top-level-add-subdirs-to-load-path)
(let* ((my-lisp-dir "~/.emacs.d/elisp/")
(default-directory my-lisp-dir))
(setq load-path (cons my-lisp-dir load-path))
(normal-top-level-add-subdirs-to-load-path)))
Мне все еще нужно отполировать это, возможно, используя автозагрузку, и некоторый байт-перекомпилировать, если измененные трюки; хотел бы услышать об этом предложения.
Ответы
Ответ 1
Мой файл .emacs загружает ~/.emacs.d/init.el, который определяет следующие функции, написанные сначала для XEmacs, но в настоящее время достаточно хорошо работает для Emacs:
(defconst user-init-dir
(cond ((boundp 'user-emacs-directory)
user-emacs-directory)
((boundp 'user-init-directory)
user-init-directory)
(t "~/.emacs.d/")))
(defun load-user-file (file)
(interactive "f")
"Load a file in current user configuration directory"
(load-file (expand-file-name file user-init-dir)))
Затем остальная часть файла идет и загружает множество отдельных файлов с такими формами:
(load-user-file "personal.el")
Мой текущий набор файлов выглядит следующим образом:
- personal.el
- platform.el
- cygwin.el
- variables.el
- paths.el
- почты news.el
- различ-funcs.el
- bbdb.el
- calendar.el
- гну-funcs.el
- с-и-java.el
- lisp.el
- clojure.el
- go.el
- markdown.el
- SGML-xml.el
- tex.el
- spelling.el
- org.el
- packages.el
- fonts.el
- цвет-theme.el
- frame.el
- server.el
- keys.el
- aquamacs.el
Некоторые из них гораздо более конкретны в намерениях, чем другие, как показывают названия. Чем более мелкозернистые файлы, тем легче отключить кластер форм при переустановке пакета или библиотеки. Это особенно полезно при "переходе" в новую систему, где вы перетаскиваете файлы конфигурации, но еще не имеете всех поддерживающих пакетов.
Ответ 2
Чтобы разделить настройки на разные файлы, вы можете использовать initsplit.el. Кроме того, у wiki есть страница на модульном макете .emacs.
Ответ 3
Что не так с использованием load-file
?
Некоторые дополнительные биты, которые могут оказаться полезными, включают
-
file-exists-p
-
file-expand-wildcards
Используйте C-h f <function>
для получения справки, и вы можете найти Введение в программирование в Emacs Lisp полезным (или загрузить PDF)
Ответ 4
Посмотрите на отличный стартовый комплект emacs, который очень хорошо организован, а также включает пакеты ELPA. Я использовал эту структуру как вдохновение для моей гораздо более простой настройки.
Ответ 5
Если вы хотите разделить свой custom-set-variables
, но хотите
что-то более легкое, чем initsplit.el
, а затем попробуйте следующее:
(defmacro custom-set-variable (var value)
"Call `custom-set-variables' with a warning shown
when customizing using the customize GUI.
XXX: does not support setting the optional NOW and
REQUEST (dependency) fields."
(custom-set-variables
;; `load-file-name' is set by `load-file':
;; http://stackoverflow.com/a/1971376/470844
`(,var ,value nil nil
,(format "!!! CAREFUL: CUSTOM-SET IN %s !!!" load-file-name))))
Теперь разместите свои модули конфигурации в отдельных файлах и загрузите их
с load-file
в вашем ~/.emacs
, как предложили другие. В каждом
конфигурационный модуль, используйте
(custom-set-variable var value)
вместо
(custom-set-variables '(var value))
или
(setq-default var value)
при настройке переменных, управляемых настройкой. Тогда, если вам когда-нибудь понадобится
для настройки переменной с помощью интерфейса настройки, вы увидите
предупреждение о том, какой файл следует сохранить в настройке:
"!!! CAREFUL: CUSTOM-SET IN <path to module file> !!!"
Если вы управляете версиями своих файлов конфигурации, тогда diff сообщит, какие
линии вашего ~/.emacs
, чтобы перейти в пользовательский модуль.
Обсуждение вопросов с наивным использованием нескольких
custom-set-variables
вызывает: http://www.dotemacs.de/custbuffer.html
Изменить: ответ на вопросы Алана
Проблема макроса custom-set-variable
выше решает
Интерфейс настройки в Emacs сохраняет все пользовательские переменные набора в
ваш ~/.emacs
, когда вы редактируете какую-либо настраиваемую переменную набора. если ты
модулируйте свои настраиваемые переменные, распространяя их по
несколько файлов, то вам нужно понять, когда emacs вставляет дубликат
настройки в вашем .emacs и удалить их. custom-set-variable
макрос выше поможет вам сделать это.
Настоящий пример из моих конфигурационных файлов
Я настраиваю переменные, связанные с пробелами в
~/.emacs.d/extensions/whitespace.el
файл, который загружается моим
~/.emacs
. Например, я установил search-whitespace-regexp
переменная такая:
(nc:custom-set-variable search-whitespace-regexp "[ \t\r\n]+")
Теперь происходят две вещи. Во-первых, когда я сталкиваюсь с этой переменной в
интерфейс настройки я получаю предупреждение:
![Generated warning in Emacs' customization dialog]()
Во-вторых, если я изменяю любые переменные, используя интерфейс настройки, мой
~/.emacs
делает очень очевидным, что я затенял некоторые определения.
Например, после изменения search-whitespace-regexp
и
global-whitespace-mode
в интерфейсе настройки, я получаю:
$ svn di --diff-cmd "diff" -x "-U0" ~/v/conf
Index: /home/collins/v/conf/dot.emacs
===================================================================
--- /home/collins/v/conf/dot.emacs (revision 267)
+++ /home/collins/v/conf/dot.emacs (working copy)
@@ -55,0 +56 @@
+ '(agda2-include-dirs (\` ("." (\, (file-truename "~/local/opt/agda-std-lib/src")))) nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/agda.el !!!")
@@ -58,0 +60,3 @@
+ '(global-whitespace-mode t)
+ '(indent-tabs-mode nil nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!")
+ '(indicate-empty-lines t nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!")
@@ -72,0 +77 @@
+ '(search-whitespace-regexp "" nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!")
@@ -74,0 +80 @@
+ '(tab-width 2 nil nil "!!! CAREFUL: CUSTOM-SET IN /home/collins/.emacs.d/extensions/whitespace.el !!!")
Макрос не помогает мне помнить, что я изменил
search-whitespace-regexp
, только, что он уже установлен где-то в другом месте,
но это помогает мне узнать, какие переменные настройки я должен удалить из
my ~/.emacs
(все с предупреждениями), и какие я должен уйти
в моем ~/.emacs
, или перейдите к другим отдельным файлам (все без
предупреждения).
Заключение
Макрос, вероятно, переполнен, но как только он существует, он прост в использовании и делает его
легче не стрелять себе в ногу с затененным пользовательским набором
переменные.
Ответ 6
Вы можете сделать (require 'foo)
, и это будет загружать первые "foo.el" elisp find в вашем пути загрузки или (require 'foo "/home/user/experimental/foo.el")
для чего-то вне вашего пути загрузки. Он сообщит об ошибке, если "foo.el" не содержит выражение (provide 'foo)
. В извращенной ситуации вы можете сделать (require 'foo "bar.el")
, и это будет работать до тех пор, пока "bar.el" имеет предложение (provide 'foo)
.
Ответ 7
Вот библиотека, которая позволяет вам устанавливать новые модули, просто сохраняя их в назначенном каталоге. Его можно загрузить и установить из http://github.com/tripleee/my-site-start/
;;; my-site-start.el --- set up personal .emacs.d/site-start.d/
;;
;; Copyright (C) era eriksson <http://www.iki.fi/~era/> 2008-2009
;; License: GPL v2
;; Version: see `my-site-start-version' below
;;
;;; Commentary:
;;
;; The purpose of my-site-start is to simplify maintenance of user libraries.
;; Instead of indefinitely tweaking your .emacs, just create a site-start.d
;; directory and add symlinks to the libraries you want to load into Emacs.
Эта архитектура накладывает некоторые соглашения, которые вам могут или не нравятся. См. Остальную часть комментария в верхней части файла для полного совка.
Я являюсь автором этого кода и ценю любую обратную связь (хотя не напрямую через этот публичный форум).
Ответ 8
Что я сделал для каждой вещи X, которую я могу использовать, создайте файл configure-X и поместите соответствующий require
в .emacs. Затем эту функцию можно удалить, комментируя одну строку.
Например, чтобы выбрать самый простой (если он наименее назван), у меня есть configure-picture-and-artist-mode.el. Этот файл очень прост:
(global-set-key (kbd "C-M-P")
'picture-mode)
(provide 'configure-picture-and-artist-mode)
И в .emacs:
(require 'configure-picture-and-artist-mode)
После сортировки это не имеет ничего в моем .emacs, за исключением большого списка require
и нескольких изменений в load-path
, данный пакет можно удалить довольно легко, и вся конфигурация для каждого пакет находится в одном месте.
(У меня также есть весь файл .el, который я использую для хранения вещей, которые не имеют никакого очевидного дома (мои глобальные привязки клавиш, вспомогательные функции и т.д.), но в идеале хотят остаться в стороне. emacs.Этот бит не очень модульный и может вводить неявные зависимости от пакетов, которые моя схема должна сделать легко разгружаемой, но на практике это не кажется большой проблемой.)
Ответ 9
Вы можете попробовать init-loader.el
, это загрузчик конфигурационных файлов. init-loader.el
загружает файлы конфигурации из указанного каталога. Это позволяет классифицировать ваши конфигурации и разделять их на несколько файлов.
Для получения дополнительной информации перейдите на вкладку init-loader GitHub Repo
Ответ 10
Спасибо @JoeCasadonte за упоминание страницы EmacsWiki. Поскольку я использую Debian и Ubuntu, этот отрывок из него работал очень хорошо (для добавления в .emacs.d/init.el):
(setq dotfiles-dir (file-name-directory (or load-file-name (buffer-file-name))))
(let ((user-site-start-dir (concat dotfiles-dir "/site-start.d")))
(debian-run-directories user-site-start-dir))
Затем мне просто нужно поместить мои файлы .el внутри ~/.emacs.d/site-start.d(например, ~/.emacs.d/site-start.d/50cedet.el
), и все они автоматически загружаются.