Так как в init есть нечто большее, чем просто загрузка файла и, с другой стороны, символическая ссылка .emacs.d
или изменение HOME
изменений в моей среде выполнения, я выбрал вариант, предложенный @glucas. Я использовал код из startup.el
и добавил патч из # 15539, чтобы использовать переменную окружения для переключения между разными директивными каталогами . Если ничего не указано, используется значение по умолчанию.
С spacemacs была одна проблема: async
он не знает об измененном каталоге init и не может найти необходимые файлы. Но это было решено в spacemacs недавно: ошибка при использовании каталога конфигурации, отличного от .emacs.d · Issue # 3390
Итак, вот мой ~/.emacs
код, который должен вести себя как исходный код инициализации, но с настраиваемым каталогом инициализации:
;;; .emacs --- let the user choose the emacs environment to use
;;; Commentary:
;;; This code mimics the behaviour of `startup.el' to let the
;;; usage of the custom init directory behave just like the
;;; one and only "~/.emacs.d".
;;;
;;; By setting the environment variable `EMACS_USER_DIRECTORY'
;;; the user-emacs-directory can be chosen and if there is an
;;; `init.el' the configuration from that directory will be used.
;;; If the environment variable is not set or there is no `init.el'
;;; the default configuration directory `~/.emacs.d/' will be used.
;;;
;;; The variable `server-name' will be set to the name of the directory
;;; chosen as start path. So if the server will be started, it can be
;;; reached with 'emacsclient -s servername'.
;;;
;;; This now works with a current version of spacemacs but does not
;;; work with `async-start' in general, if the code executed with `async'
;;; uses `user-init-dir' or makes other assumptions about the emacs
;;; start-directory.
;;; Code:
(let* ((user-init-dir-default
(file-name-as-directory (concat "~" init-file-user "/.emacs.d")))
(user-init-dir
(file-name-as-directory (or (getenv "EMACS_USER_DIRECTORY")
user-init-dir-default)))
(user-init-file-1
(expand-file-name "init" user-init-dir)))
(setq user-emacs-directory user-init-dir)
(with-eval-after-load "server"
(setq server-name
(let ((server--name (file-name-nondirectory
(directory-file-name user-emacs-directory))))
(if (equal server--name ".emacs.d")
"server"
server--name))))
(setq user-init-file t)
(load user-init-file-1 t t)
(when (eq user-init-file t)
(setq user-emacs-directory user-init-dir-default)
(load (expand-file-name "init" user-init-dir-default) t t)))
(provide '.emacs)
;;; .emacs ends here
Есть также приятное дополнение, которое делает его работающим как демон без лишних усилий: в качестве имени сервера будет задано имя каталога init. Так что теперь вы можете запустить второй демон emacs с ванильным spacemacs
EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs --daemon
и до сих пор использовать emacsclient
emacsclient -s spacemacs -c -e '(message "Hello spacemacs")'
Мой сценарий использования очень прост, и я удивлен, что я единственный: у меня есть всегда работающий демон emacs и я использую его из графического интерфейса и из консоли (например, с ssh). В этом emacs я готовлю всю свою документацию и рабочий журнал, поэтому он должен быть там постоянно. Но затем я хочу попробовать spacemacs или один из других дистрибутивных пакетов и даже настроить его, пока не смогу отказаться от своей текущей конфигурации или использовать некоторые умные идеи. Как и другие, я хотел создать простую базовую конфигурацию для моих коллег - и задокументировать ее с помощью org-mode в моем работающем экземпляре.
Поскольку единственная проблема, о которой я знаю, это async
то, что она не знает об измененном каталоге init, я думаю о лучшем способе добавить некоторую конфигурацию, в async
которой есть переменные, которые должны быть введены по умолчанию, так что нет необходимости исправлять все вызовы так async-start
же, как это сделали космические маки.