Ejecutando spacemacs junto con emacs regulares: cómo mantener un .emacs.d separado

32

Me gustaría probar spacemacs. Pero todavía no quiero cambiar mi configuración habitual de emacs, por lo que me gustaría que la configuración que está actualmente en mi .emacs.desté en un directorio, y la configuración equivalente para spacemacs esté en otro directorio. No me importa qué nombre tenga el directorio.

¿Es eso posible, sin chroots / LD_PRELOAD / otro truco? ¿Cómo puedo hacerlo?

Croad Langshan
fuente
2
Vea también la respuesta de Dan a una pregunta similar que tenía con respecto a la configuración de un temporizador con opciones cuando se inicia Emacs: emacs.stackexchange.com/questions/3588/... He estado usando una ligera variación de esa respuesta desde entonces.
abogados
1
En la categoría de "otro truco", tal vez, podría crear un enlace simbólico que spacemacsapunte al ejecutable de emacs y usar el valor de (car command-line-args)para decidir qué archivo de inicio ejecutar. Esto supone, por supuesto, que está ejecutando en un sistema unix que no sea OS X. (La forma en que funcionan los paquetes de aplicaciones en OS X hace que este truco sea difícil de llevar a cabo).
Harald Hanche-Olsen
1
Vea otro enfoque aquí: emacs.stackexchange.com/q/4253/780
glucas
2
Acabo de volver a decir, unos 18 meses después, esta es la razón por la que no he aprendido los spacemacs. Tuve algunos problemas molestos con la respuesta aceptada entonces, solo intenté de nuevo, todavía cierto. Después de agregar la capa de organización obtuvo "La definición de la función del símbolo es nula: bucle" en este momento. No sé si esto es parte de la causa, pero ese es exactamente el problema: para un proyecto pulido de "baterías incluidas", parece extraño tener que improvisar algo solo para INICIARLO, luego me pregunto si mi configuración es compatible. Quizás injusto, pero eso me hace perder la confianza. Tal vez en otros 18 meses se solucione ...
Croad Langshan

Respuestas:

20

Una opción es especificar qué configuración desea cargar en un ~/.emacsarchivo. Cuando Emacs se inicie, buscará dicho archivo antes de buscarlo ~/.emacs.d/. Para obtener más detalles, puede leer sobre el archivo Init en el manual de Emacs.

Entonces, por ejemplo, puede crear una ~/.spacemacs.dy mantener su existente ~/.emacs.dtal como está. Luego cree una ~/.emacspara cargar la que tenga ganas de usar:

(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))

Si lo desea, puede encontrar formas de cambiar las configuraciones sin modificar el archivo .emacs. Por ejemplo, haga que sus .emacs busquen alguna variable de entorno que establezca en su shell o en un script que use para iniciar spacemacs:

(setq use-spacemacs (getenv "USE_SPACEMACS"))
glucas
fuente
1
Seguramente, debe haber una forma desde adentro de elisp para saber si estás ejecutando spacemacs o no. Por ejemplo, al marcar (con fboundp) una función o comando que sea exclusivo de spacemacs?
Harald Hanche-Olsen
2
Claro, pero esa no era la pregunta tal como la entendí. Spacemacs es solo una configuración de emacs, y el OP quiere saber cómo mantener más de un directorio de configuración de emacs independiente.
glucas
1
@ HaraldHanche-Olsen también me sorprendió cuando lo descargué, pero cuando lo pensé tenía sentido. Creo que la razón por la que esperamos eso es que, para la mayoría de los sistemas, para hacer un 'producto' pulido como los spacemacs parece ser necesario, es necesario encontrar un lenguaje de sistemas de nivel inferior, pero en emacs hay mucha extensibilidad (gracias, elisp) que eso no es necesario
Croad Langshan
1
Acepté esto, pero en realidad no lo había intentado. Ahora que lo tengo, no funciona tal como está: Error de archivo: no se puede abrir el archivo de carga, /home/me/.emacs.d/core/core-load-paths.el: lo necesitaba (setq user-emacs-directory "~/.spacemacs.d/")para trabajo (en un prognen la rama spacemacs de su condicional). ¿Puedes agregar eso a tu respuesta para que pueda aceptarlo nuevamente?
Croad Langshan
2
@glucas Estoy en win10, por alguna razón HOME se asignó a c: / users / nate. Se eliminó la variable ambiental y todo funcionó bien.
Nathaniel Saxe
12

Como hay mucho más que hacer en init que solo cargar un archivo y, por otro lado, simular .emacs.do cambiar los HOMEcambios en mi entorno de tiempo de ejecución, opté por una variante de lo que @glucas había propuesto. Usé el código de startup.ely agregué el parche # 15539 para usar una variable de entorno para cambiar entre diferentes directorios de inicio. Si no se da ninguno, se usa el predeterminado.

Hubo un problema con spacemacs: asyncno conoce el directorio init cambiado y, por lo tanto, no puede encontrar algunos archivos necesarios. Pero esto se ha resuelto recientemente en spacemacs: error al usar un directorio de configuración que no sea .emacs.d · Problema # 3390

Así que aquí está mi ~/.emacsque debería comportarse como el código de inicio original pero con un directorio de inicio configurable:

;;; .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

También hay una buena adición que lo hace funcionar como un demonio sin esfuerzo adicional: el nombre del servidor se establecerá en el nombre del directorio init. Así que ahora puedes comenzar un segundo demonio emacs con un vainilla spacemacs

EMACS_USER_DIRECTORY=~/.emacsenv.d/spacemacs emacs --daemon

y sigo usando emacsclient

emacsclient -s spacemacs -c -e '(message "Hello spacemacs")'

Mi caso de uso es muy simple y estoy asombrado de ser el único: tengo un demonio emacs siempre en ejecución y lo uso desde la interfaz gráfica de usuario y sobre la consola (con ssh, por ejemplo). En este emacs preparo toda mi documentación y registro de trabajo, por lo que tiene que estar allí todo el tiempo. Pero luego quiero probar spacemacs o uno de los otros paquetes de distribución e incluso configurarlo, hasta que pueda retirar mi configuración actual o usar algunas de las ideas inteligentes. Y como otros, quería crear una configuración básica simple para mis compañeros de trabajo y documentarla con el modo org en mi instancia de ejecución.

Dado que el único problema que conozco es asyncy que no conoce el directorio de inicio cambiado, pienso en la mejor manera de agregar alguna configuración asyncque tenga variables que deberían inyectarse de forma predeterminada, por lo que no es necesario parchear todo invocaciones de async-startlo que habían hecho los spacemacs.

Uwe Koloska
fuente
Esto es realmente encantador y funcionó maravillosamente ... hasta que necesité usarlo async. :-( Ya que han pasado unos meses desde que publicaste, ¿tienes una solución?
Trey
Desafortunadamente no, pero para spacemacs es fijo y para asíncrono general no estoy realmente seguro de si debe haber algún cambio, porque async-startinicia emacs sin nada y si desea usar alguna variable, debe pasarla. Pero claro, sería Sea agradable y conveniente, si async se puede configurar con una lista de variables, que se utilizará en cada invocación de async-start.
Uwe Koloska
1
Con este enfoque, puede haber otras variables que se inicializan desde el directorio predeterminado user-emacs antes de cargar su .emacs. Por ejemplo, necesitaba agregar(setq custom-theme-directory user-emacs-directory) aquí.
glucas
1
No sé dónde se establece esta variable, porque cuando la examino dentro de un testenv mínimo, obtengo: Su valor es "~ / .emacs.d /". El valor original era "~ / .emacsenv.d / init-test /" Por lo tanto, tiene el valor correcto, pero se sobrescribió.
Uwe Koloska el
1
De hecho, terminé usando esta respuesta, mucho después de hacer la pregunta. ¡No he cambiado la respuesta aceptada porque es demasiado larga y porque no he prestado mucha atención a la implementación! Sin embargo, esta respuesta me ha sido muy útil.
Croad Langshan
5

Aquí se explica , y hay un RP en curso para agregarlo a la documentación:

mkdir ~/spacemacs
git clone [email protected]:syl20bnr/spacemacs.git ~/spacemacs/.emacs.d
HOME=~/spacemacs emacs```
StreakyCobra
fuente
66
Sí, a veces cambio de INICIO para probar una configuración alternativa. La desventaja es que HOME se usa para otras cosas que puede preferir no afectar.
glucas
3

Ya ha sido respondido y aceptado, pero si tiene ganas de probar nuevas formas de hacer las cosas de forma reversible (más allá de las configuraciones de emacs), le recomiendo que pase media hora familiarizándose con GNU Stow. Es una especie de ln -sesteroides, y puede haber varios enfoques para usarlo. Puede tener toda la configuración en un subdirectorio (incluidas las configuraciones offlineimap, las configuraciones de emacs, etc.), que sería un enfoque basado en el entorno, o tener un subdirectorio separado para cada aplicación que tenga. Dulce esquizofrenia.

Por ejemplo, lista relacionada con emacs de mi ~ / Stow:

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

Hay una configuración inicial que he logrado utilizar, una configuración 'Me quedo con los valores predeterminados' y una 'Voy a rodar la mía'. Puedo activar y desactivar cada uno de estos y tenerlos siempre disponibles. Cada subdirectorio puede tener un árbol completo en relación con mi ~ / y es bastante útil mezclar y combinar.

Roman Grazhdan
fuente
Ya uso stow como sucede. ¿Pero cómo lo usas para esto? Simplemente está 'explorando dinámicamente' su .emacs.d al simular y vincular el que desea usar, usando stow? ¿Alguna vez corriste ambos al mismo tiempo? Si es así, supongo que ambos emacses piensan que son "dueños" .emacs.d. Me pregunto si eso podría causar algunas rarezas con cosas que guardan el estado allí, como no sé, por ejemplo, recientef, savehist, autoguardado, etc., especialmente cuando las dos copias de emacs se ejecutan con configuraciones radicalmente diferentes.
Croad Langshan
No, solo cambio las configuraciones según sea necesario.
Roman Grazhdan
2

Revisé el parche que usó @Uwe Koloska. No estaba incluido en la rama principal. Estoy de acuerdo, creo que el problema debería resolverse fuera de emacs usando el shell y dejando que emacs no sepa nada al respecto.

Tal vez esa característica sería más lógica desde la perspectiva del usuario, el uso de una bandera sería menos complicado para algunos usuarios.

En mi caso de uso, quiero mantener mi instalación de Emacs y Spacemacs, por lo que mi variación de las dos soluciones anteriores funciona de esta manera.

script de shell

Primero que nada el script para lanzar spacemacs:

#!/bin/sh

export EMACS_USER_DIR=~/spacemacs/emacs.d

exec emacs "$@"

Este script se llama spacemacsy se instala en la /usr/local/bincarpeta.

archivo .emacs

Luego necesito un .emacsarchivo en mi carpeta de inicio que trate adecuadamente la variable de entorno 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))

No tengo experiencia con elisp en absoluto, así que se me ocurrió esto, las personas más experimentadas probablemente podrían encontrar algo mejor. Pero bueno, funciona.

Ojos dulces

Entonces, ¿por qué no agregar un icono?

icono

[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;
Marcos
fuente
3
Su script de shell debería usar exec emacs "$@".
Uwe Koloska
Sí, gracias por el consejo, solo arreglado.
Marcs