与常规emacs一起运行spacemacs:如何保持单独的.emacs.d


32

我想尝试spacemacs。但是我现在还不想从常规的emacs配置切换到其他位置,所以我希望当前位于我的配置.emacs.d位于一个目录中,而让spacemacs的等效配置位于另一个目录中。我不在乎两个目录的名称。

缺少chroots / LD_PRELOAD /其他欺骗手段,这是否可能?我该怎么做?


2
另请参见Dan对我有关在Emacs启动时设置带有选项的计时器的类似问题的回答: emacs.stackexchange.com/questions/3588/…从那时起, 我一直在使用该回答的细微变化。
法律列表

1
也许在“其他欺骗”类别中,您可以创建一个spacemacs指向emacs可执行文件的符号链接,并使用的值(car command-line-args)确定要运行哪个初始化文件。当然,这是假设您正在OS X以外的unix系统上运行。(应用捆绑在OS X上的工作方式使该技巧难以实施。)
Harald Hanche-Olsen

1
在此处查看另一种方法:emacs.stackexchange.com/q/4253/780
glucas

2
我只是回过头说,大约18个月后,这仍然是我尚未学习spacemacs的原因。然后,我在接受的答案上遇到了一些小问题,只是再次尝试,仍然如此。添加组织层后,“ Symbol的函数定义为void:loop”才刚刚出现。我不知道这是原因的一部分,但这恰恰是问题所在:对于一个精美的“含电池”项目,只是为了启动它而不得不拼凑一些东西,然后想知道是否支持我的配置,这似乎很奇怪。也许不公平,但这使我失去信任。也许再过18个月就会解决...
Croad Langshan

Answers:


20

一种选择是指定要在~/.emacs文件中加载的配置。当Emacs启动时,它将在查找之前查找此类文件~/.emacs.d/。有关更多详细信息,请阅读Emacs手册中有关Init文件的信息。

因此,例如,您可以创建一个~/.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"))

1
当然,必须从elisp内部找到一种方法来判断您是否正在运行spacemacs?例如,通过(使用fboundp)检查spacemacs特有的功能或命令?
Harald Hanche-Olsen

2
当然,但这不是我所理解的问题。Spacemacs只是一个emacs配置,OP希望知道如何维护多个独立的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提出的变体。我使用了#15539的代码startup.el并添加了补丁,以使用环境变量在不同的init目录之间进行切换。如果没有给出,则使用默认值。

spacemacs有一个问题:async不知道已更改的init目录,因此找不到某些必要的文件。但这已在spacemacs中得到解决:使用.emacs.d以外的配置目录时出错·问题#3390

所以这是我的~/.emacs行为,应该与原始init代码类似,但具有可配置的init目录:

;;; .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目录的名称。所以现在您可以使用香草spacemacs启动第二个emacs守护程序

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

仍然使用emacsclient

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

我的用例非常简单,我很惊讶,我是唯一的一个:我有一个始终运行的emacs守护程序,可以在gui和控制台(例如ssh)上使用它。在此emacs中,我准备了所有文档和工作日志,因此它必须一直存在。但是,然后我想尝试一下spacemacs或其他分发软件包之一,甚至进行配置,直到我可以退出当前的配置或使用一些聪明的主意。和其他人一样,我想为我的同事创建一个简单的基本配置-并在运行的实例中使用org-mode对其进行记录。

由于我知道的唯一问题是async它不知道更改后的init目录,因此,我考虑了向其中添加一些配置的最佳方法,async该配置具有默认情况下应注入的变量,因此无需修补所有的调用async-start,就像spacemacs做了。


这真的很可爱,而且做工精美……直到我需要使用为止async。:-(既然您已经发布了几个月,您有解决方法吗?
Trey 2016年

不幸的是,并非如此-但是对于spacemacs而言,它是固定的,对于一般异步而言,我不确定是否必须进行任何更改,因为async-start启动emacs时不需任何操作,如果要使用某些变量,则必须将其传递。但是可以肯定,它将不错,很方便,如果可以使用一系列变量配置异步,则将在每次调用时使用async-start
Uwe Koloska

1
使用此方法,可能会在加载.emacs之前从默认的user-emacs-directory初始化其他变量。例如,我需要在(setq custom-theme-directory user-emacs-directory)这里添加。
glucas

1
我不知道该变量的设置位置,因为当我在最小的testenv中对其进行检查时,会得到:其值为“〜/ .emacs.d /”。原始值为“〜/ .emacsenv.d / init-test /”,因此它具有正确的值,但此值已被覆盖。
Uwe Koloska,

1
我问了这个问题很久之后,实际上我最终还是使用了这个答案。我没有更改已接受的答案,因为它已经很长了,并且因为我实际上并未对实现进行过多关注!不过,这个答案对我非常有用。
Croad Langshan

5

此处进行了说明,并且正在进行的PR会将其添加到文档中:

mkdir ~/spacemacs
git clone git@github.com:syl20bnr/spacemacs.git ~/spacemacs/.emacs.d
HOME=~/spacemacs emacs```

6
是的,我有时会更改HOME来尝试其他配置。缺点是HOME用于其他您可能不希望影响的事物。
glucas '16

3

它已经被回答并被接受,但是如果您想尝试一种可逆的新方法(超越emacs配置),我建议您花半个小时来熟悉GNU Stow。它有点像ln -s类固醇,可能有几种使用方法。您可以将整个设置放在一个子目录下(包括offlineimap配置,emacs配置等)-这是基于环境的方法-或对于每个应用程序都有一个单独的子目录。甜精神分裂症。

例如我〜/ Stow中与emacs相关的清单:

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

我设法使用了一个初始配置,一个“我坚持默认设置”配置,一个“我要自己滚动”。我可以打开和关闭这些功能,并始终保持它们可用。每个子目录都可以有一个相对于我的〜/的完整树,混合和匹配非常方便。


我确实已经在使用存储。但是您如何使用它呢?您只是通过使用收藏夹符号链接输入/输出想要使用的.emacs.d来“动态地界定”您的.emacs.d?您曾经同时运行两个吗?如果是这样,我猜这两个emacses都认为他们“拥有” .emacs.d。我想知道这是否会导致某些保存状态的异常,例如我不知道说lastf,savehist,autosave等。尤其是当emacs的两个副本以截然不同的配置运行时?
Croad Langshan

不,我只是根据需要切换配置。
Roman Grazhdan

2

我检查了@Uwe Koloska使用的补丁。它不包含在主分支中。我有些同意,我认为应该在emacs之外使用shell解决该问题,并使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的经验,所以我提出了这一点,更有经验的人可能会提出更好的建议。但是,它有效。

秀色可餐

然后为什么不添加图标:

图标

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

3
您的shell脚本应使用exec emacs "$@"
Uwe Koloska '16

是的,谢谢你的提示,只是固定的。
Marcs

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.