Запуск spacemacs вместе с обычными emacs: как сохранить отдельный .emacs.d

32

Я хотел бы попробовать Spacemacs. Но я пока не хочу переключаться с моей обычной конфигурации emacs, поэтому я бы хотел, чтобы конфигурация, которая в данный момент находится в моем, .emacs.dбыла в одном каталоге, а эквивалентная конфигурация для spacemacs - в другом каталоге. Я не против, какое имя у любого каталога.

Возможно ли это, если не считать chroots / LD_PRELOAD / другие подобные хитрости? Как я могу это сделать?

Croad Langshan
источник
2
См. Также ответ Дэна на похожий вопрос, который у меня был относительно установки таймера с параметрами при запуске Emacs: emacs.stackexchange.com/questions/3588/… С тех пор я использовал небольшой вариант этого ответа.
юрист
1
Возможно, в категории «другие хитрости» вы можете создать символическую ссылку, spacemacsуказывающую на исполняемый файл emacs, и использовать значение, (car command-line-args)чтобы решить, какой файл инициализации запускать. Конечно, это предполагает, что вы работаете в Unix-системе, отличной от OS X. (То, как комплекты приложений работают в OS X, затрудняет выполнение этого трюка.)
Харальд Ханче-Олсен
1
Смотрите другой подход здесь: emacs.stackexchange.com/q/4253/780
glucas
2
Я только что вернулся, чтобы сказать, около 18 месяцев спустя, это все еще причина, по которой я не изучал космические карты. У меня было несколько проблем с принятым ответом тогда, просто попробовал еще раз, все еще верно. После добавления org layer получено «Определение функции Symbol void: loop» только сейчас. Я не ЗНАЮ, что это является частью причины, но в этом-то и проблема: для полированного проекта «с батарейками» кажется странным, что нужно что-то сложить вместе, чтобы просто НАЧАТЬ это, а потом задаться вопросом, поддерживается ли моя конфигурация? Возможно несправедливо, но это заставляет меня терять доверие. Может быть, через 18 месяцев это будет исправлено ...
Croad Langshan

Ответы:

20

Один из вариантов - указать, какую конфигурацию вы хотите загрузить в ~/.emacsфайл. Когда Emacs запускается, он ищет такой файл, прежде чем заглядывать внутрь ~/.emacs.d/. Более подробную информацию вы можете прочитать о файле инициализации в руководстве по Emacs.

Так, например, вы можете создать ~/.spacemacs.dи сохранить существующее ~/.emacs.dкак есть. Затем создайте ~/.emacsзагрузку, которую вы хотите использовать:

(setq use-spacemacs t)   ; or nil 

(when use-spacemacs
  (setq user-emacs-directory "~/.spacemacs.d/"))   ; defaults to ~/.emacs.d/

(load (expand-file-name "init.el" user-emacs-directory))

Если вы хотите, вы можете придумать способы переключения конфигураций без изменения файла .emacs. Например, пусть ваш .emacs проверит некоторую переменную среды, которую вы установили в своей оболочке или в скрипте, который вы используете для запуска spacemacs:

(setq use-spacemacs (getenv "USE_SPACEMACS"))
glucas
источник
1
Конечно, из elisp должен быть способ узнать, запускаете ли вы spacemacs или нет? Например, проверяя (с fboundp) функцию или команду, уникальную для spacemacs?
Харальд Ханче-Олсен
2
Конечно, но это был не тот вопрос, насколько я понял. Spacemacs - это просто конфигурация emacs, и ОП хочет знать, как поддерживать более одного независимого каталога конфигурации emacs.
glucas
1
@ HaraldHanche-Olsen, что тоже удивило меня, когда я скачал его, но когда я подумал об этом, это имело смысл. Я думаю, что причина, по которой мы ожидаем, заключается в том, что для большинства систем, для создания отточенного «продукта», такого как spacemacs, необходимо выделить какой-то системный язык более низкого уровня - но в emacs есть такая большая расширяемость (спасибо elisp) что это не обязательно.
Croad Langshan
1
Я принял это, но на самом деле не пробовал. Теперь, когда у меня есть, это не совсем работает как есть: Ошибка файла: не удается открыть загрузочный файл, /home/me/.emacs.d/core/core-load-paths.el - мне нужно было, чтобы (setq user-emacs-directory "~/.spacemacs.d/")это работа (в prognвашей ветке spacemacs условно). Можете ли вы добавить это к своему ответу, чтобы я мог принять его снова?
Croad Langshan
2
@glucas Я нахожусь на win10, по некоторым причинам HOME был назначен в c: / users / nate. Убрал переменную среды и все работало нормально.
Натаниэль Сакс
12

Так как в 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же, как это сделали космические маки.

Уве Колоска
источник
Это действительно прекрасно и прекрасно работает ... пока мне не понадобилось пользоваться async. :-( Так как прошло несколько месяцев с момента публикации, у вас есть обходной путь?
Trey
К сожалению, нет - но для spacemacs это исправлено, и для общей асинхронности я не совсем уверен, должны ли быть какие-либо изменения, потому что async-startзапускает emacs без чего-либо, и если вы хотите использовать какую-то переменную, вы должны передать ее. Но, конечно, это будет будет удобно и удобно, если асинхронность может быть настроена со списком переменных, которые будут использоваться при каждом вызове async-start.
Уве Колоска
1
При таком подходе могут быть другие переменные, которые инициализируются из каталога user-emacs-default по умолчанию перед загрузкой вашего .emacs. Например мне нужно было добавить (setq custom-theme-directory user-emacs-directory)сюда.
glucas
1
Я не знаю, где установлена ​​эта переменная, потому что когда я проверяю ее внутри минимального testenv, я получаю: Ее значение равно «~ / .emacs.d /». Первоначальное значение было «~ / .emacsenv.d / init-test /», поэтому оно имеет правильное значение, но оно было перезаписано.
Уве Колоска
1
Я на самом деле закончил тем, что использовал этот ответ, задолго до того, как задал вопрос. Я не изменил принятый ответ, потому что он такой длинный, и потому что я на самом деле не уделял много внимания реализации! Этот ответ был очень полезен для меня, хотя.
Croad Langshan
5

Это объясняется здесь , и существует постоянный PR, чтобы добавить его в документацию:

mkdir ~/spacemacs
git clone git@github.com:syl20bnr/spacemacs.git ~/spacemacs/.emacs.d
HOME=~/spacemacs emacs```
StreakyCobra
источник
6
Да, я иногда меняю HOME, чтобы попробовать альтернативный конфиг. Недостатком является то, что HOME используется для других вещей, которые вы можете предпочесть не затрагивать.
glucas
3

Он уже получен и принят, но если вам захочется попробовать новые способы сделать вещи обратимыми (помимо конфигураций в emacs), я бы порекомендовал вам потратить полчаса на ознакомление с GNU Stow. Это своего рода ln -sстероиды, и может быть несколько подходов к его использованию. Вы можете иметь всю установку в одном подкаталоге (включая конфиги offlineimap, конфиги emacs и т. Д.) - это будет подход, основанный на среде - или иметь отдельный подкаталог для каждого вашего приложения. Сладкая шизофрения.

Например, список, связанный с emacs, из моего ~ / Stow:

-> % ls ~/Stow | grep emacs
emacs 
emacs_from_scratch
spacemacs
hoodoo@T450s 2:46 [~]

Есть одна начальная конфигурация, которую мне удалось использовать, одна конфигурация «Я придерживаюсь настроек по умолчанию» и одна «Я собираюсь свернуть свою собственную». Я могу просто включить и выключить каждый из них и всегда иметь их в наличии. Каждый подкаталог может иметь целое дерево относительно моего ~ /, и его довольно удобно смешивать и сочетать.

Роман Граждан
источник
Я использую Stow уже, как это происходит. Но как вы используете это для этого? Вы просто «динамически определяете» свой .emacs.d, используя символическую ссылку на вход / выход, который вы хотите использовать, используя stow? Вы когда-нибудь работали одновременно? Если так, то я думаю, что оба emacses думают, что они "свои" .emacs.d. Интересно, может ли это вызвать какие-то странности с вещами, которые сохраняют там состояние, например, я не знаю, скажем Recentf, Savehist, Autosave и т. Д., Особенно, когда две копии Emacs работают с радикально разными конфигурациями?
Croad Langshan
Нет, я просто переключаю конфигурации по мере необходимости.
Роман
2

Я проверил патч, который использовал @Uwe Koloska. Он не был включен в основную ветку. Я несколько согласен, я думаю, что проблема должна быть решена вне emacs, используя оболочку, а emacs ничего не знает об этом.

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

В моем случае я хочу сохранить установку Emacs и Spacemacs, чтобы мой вариант двух вышеупомянутых решений работал следующим образом.

сценарий оболочки

Прежде всего скрипт для запуска spacemacs:

#!/bin/sh

export EMACS_USER_DIR=~/spacemacs/emacs.d

exec emacs "$@"

Этот скрипт вызывается spacemacsи устанавливается в /usr/local/binпапку.

файл .emacs

Затем мне нужен .emacsфайл в моей домашней папке, который будет правильно обрабатывать переменную окружения EMACS_USER_DIR.

(defvar user-custom-dir (getenv "EMACS_USER_DIR"))

(when (/= (length user-custom-dir) 0)
  (setq user-emacs-directory (file-name-as-directory user-custom-dir)))

(load (expand-file-name "init.el" user-emacs-directory))

Я совсем не разбираюсь в elisp, поэтому я придумал это, более опытные люди могли бы придумать что-то лучшее Но эй, это работает.

Eye-конфета

Тогда почему бы не добавить значок:

значок

[Desktop Entry]
Name=Spacemacs
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=spacemacs %F
Icon=/home/marcs/.icons/spacemacs.svg
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupWMClass=Emacs
Keywords=Text;Editor;
Marcs
источник
3
Ваш shell-скрипт должен использовать exec emacs "$@".
Уве Колоска
Да, спасибо за совет, только что исправили.
Marcs