如何使用自定义user-emacs-directory启动emacs


57

我正在开发一个自定义的小型Emacs配置,我想与一些朋友分享为git存储库,以供他们用作自己未来配置的基准。

为此,我需要某种方法来测试我的配置,而我能想到的最简单的解决方案是:

$ emacs --eval "(setq user-emacs-directory \"~/Code/my_custom_emacs.d/\")"

但是我似乎无法使其正常工作。

任何帮助,不胜感激。


3
我通读了有关Emacs调用的附录C命令行参数,.emacs.d除非找到HOME,否则我找不到用于启动带有自定义目录的Emacs的简单命令行选项,这对我来说似乎很麻烦。人们在下面提供了解决方法,但对我来说,这听起来像是对Emacs本身非常合理的功能要求。
David J.


5
@DavidJames您说得对:Emacs的错误跟踪器中实际上有一个有关此的愿望清单项目
ffevotte'3

2
更新:该功能似乎对Emacs开发人员不那么感兴趣:该请求已被标记wontfix并在错误跟踪器中关闭。
ffevotte's

@Francesco:我尝试了一种动态方法,该方法允许将用户Emacs目录放在“〜”之外。也许您会尝试一下。
2013年

Answers:


38

我使用的基本方法是$HOME通过运行来修改:

env HOME=/path/to/dir emacs

然后,您使用 /path/to/dir/.emacs.d

您可能还希望将该虚假主目录中的重要文件或目录符号链接回真实文件或目录,以便Emacs可以看到它们。


2
这很完美!
Mattias Bengtsson 2014年

8
根据Emacs手册-用于Emacs调用的附录C命令行参数-环境变量-常规变量,HOME设置“文件在目录树中的位置;用于以波浪号(〜)开头的文件名的扩展。” 当您想快速导航或从实际主文件夹中查找文件时,更改HOME听起来像是麻烦的秘诀。
David J.

2
David James:是的,这种方法有点烦人。如前所述,您将需要复制或符号链接需要 Emacs才能在HOME下看到的内容,如果要访问真实的主目录,则需要使用绝对路径(也可以在其中添加符号链接) )。
phils 2015年

3
您还可以尝试在初始化期间在Emacs中恢复原始HOME。我没有尝试过,但是似乎值得研究。
phils 2015年

1
@phils:我尝试了您的建议。
2013年

39

下面是我用来.emacs.d并行维护多个目录的方法。

  1. emacs是这样启动的:

    alias emacs='emacs -q --load "/path/to/init.el"'
    
  2. 每个init.el文件都是这样开始的,以正确设置user-init-fileuser-emacs-directory变量:

    (setq user-init-file (or load-file-name (buffer-file-name)))
    (setq user-emacs-directory (file-name-directory user-init-file))
    

我发现这在过去几个月中非常可靠地工作。这里有几点评论:

  • 它会中断emacs-init-time,它仅报告加载默认系统配置所需的时间,而不报告您自己的初始化文件。如果您有兴趣对基准时间进行基准测试,则必须采用另一种方式(例如,请参见如何测量elisp代码的性能?)。

  • 它不等同于正常的启动,您需要注意一些特定的问题。尤其是:

    • after-init-hook加载初始化文件之前运行。
    • *scratch*创建缓冲区之前加载init文件。您必须显式更改其模式(而不是使用initial-major-mode)。
    • 您需要显式调用package-initialize;它不会自动完成
  • init.el可以任意选择的路径;特别是,init.el不必将其所在的目录命名为.emacs.d。例如,我可以使用它.emacs.d.23并排使用.emacs.d.24,以便能够在不同版本的emacs之间切换(我正在使用的系统已经过时,并且我无法在使用的所有计算机上安装emacs 24)。

  • 此工作流程不需要修改环境(尤其是HOMEenvvar),如果您从emacs中运行程序(可能会受到修改后的环境的影响),则可能需要这样做。


1
如果您将--loaded文件视为初始化文件,则(实际上)会更改正常的执行顺序。对于初学者来说,在我看来,将不会发生正常的(默认)软件包初始化,并且after-init-hook它将评估(伪)初始化文件之前运行。当然,可以解决这些问题,但是请注意,使用指定的路径作为init文件,这与Emacs并不完全相同。
菲尔2014年

2
@phils是的,您是对的。实际上,这确实改变了正常的执行顺序,并不等同于使用常规的初始化文件。我修改了答案,以反映您的观点after-init-hook。但是我不得不说,尽管我一直在使用这种技术,但是我从来没有遇到任何问题after-init-hook(但是我没有明确使用它,也许我很幸运我使用的软件包不依赖它) 。“正常(默认)包初始化不会发生”是什么意思?
ffevotte 2014年

1
我的意思是在那种情况下command-line不会打电话package-initialize。您需要在伪造的init文件中手动调用它。
菲尔2014年

1
@phils谢谢。我将此添加到了答案中,并提到最初的主要模式也必须特别注意。
ffevotte 2014年

这很完美..谢谢!!!
斯特赖克

15

你可以符号链接 ~/.emacs.d,这就是我所做的

  1. 尝试保持我的emacs配置~/.emacs.d为导向,即所有与emacs相关的配置文件应位于该文件夹中

  2. 然后,我有一个~/.emacs_configs文件夹,其中所有配置文件夹(基本上是一个带有init.el其余配置的文件夹)都存在,因此我的个人配置文件夹将为~/emacs_configs/iqbal,一个前奏分发将位于~/emacs_configs/prelude

  3. 在我的个人emacs配置很早的时候,我user-emacs-directory使用以下命令将设置为配置的完整路径

    (setq user-emacs-directory (file-truename "~/.emacs.d/"))
    
  4. 最后,我将符号链接~/.emacs.d到我实际要使用的配置,例如。使用我的配置我会做的ln -s ~/emacs_configs/iqbal .emacs.d。如果要尝试一些配置,只需将配置文件夹复制到~/emacs_configs/whatever_name并更改符号链接

第三步的优点是,即使我.emacs.d在emacs运行时更改了符号链接,以我的个人配置启动的emacs也不会受到影响。

另一个优点是,由于HOMEemacs可能需要与之交互的外部程序未更改,因此不受影响


1
这是否意味着我们可以将所有单独的emacs配置进行调整,以(setq user-emacs-directory (file-truename "~/.emacs.d/"))使它们都可以不受影响地同时运行?
user1011471

1
从理论上讲是可以的,但是在实践中可能会有一些库对路径进行硬编码~/.emacs.d而不是使用user-emacs-directory。我遇到过至少一个这样的库,但是不幸的是忘记了这个名字。
伊克巴尔·安萨里


5

我从EmacsWiki找到了这个简洁的解决方案:

emacs -q -l ~/my-init-file.el

(不完全使用自定义目录,但效果很好,因为您很可能始终只有一个条目文件)


仅供参考,这是多余的,来自2年前@Francesco的评论。
布莱斯


3

加载初始化文件之前设置var :

emacs -q --eval '(setq alt-conf t)' --load ~/.emacs

然后,在您的init文件中(在本例中为~/.emacs):

(defvar alt-conf nil)

(if alt-conf
    (let ((default-directory "~/src/elisp-test/"))
      (normal-top-level-add-subdirs-to-load-path)
      (various-alt-config-stuff)
      (message "Alternate conf"))
  (message "Regular conf"))

非常优雅,我最喜欢的系统,因为一切都应该保留在Emacs的域中。谢谢。
gsl

1

通过扩展@phils的答案,我制作了这个小shell脚本(称为testrun.sh)来测试我的新emacs配置。在其他情况下也可以这样做(例如,在测试可能会破坏emacs的init.el更改时)。

#!/bin/bash

cd $(dirname "${BASH_SOURCE[0]}")
[ -d .testrun ] || mkdir .testrun
cd .testrun
[ -h .emacs.d ] || ln -s .. .emacs.d

env HOME=`pwd` emacs

rm .emacs.d
cd ..
rm -rf .testrun

1

这是一个基于@Phil的答案和注释的小脚本,有关更改HOME环境变量,然后在Emacs中恢复它。

#!/bin/bash

# Use it like this:
#   /path/to/this/script  EMACS_USER_DIRECTORY  [OTHER EMACS ARGS]

# You can never be too careful
set -e

# First arg = emacs user directory
#   (get a canonical, absolute path)
EMACS_USER_DIRECTORY=$(readlink -f "$1")
shift
if [ ! -d "${EMACS_USER_DIRECTORY}" ]; then
    echo "Non-existent directory: '${EMACS_USER_DIRECTORY}'"
    exit 1
fi

# Bootstrap directory
BOOTSTRAP=$(mktemp --directory --tmpdir .emacs-bootstrap.XXXXXX)
mkdir "${BOOTSTRAP}/.emacs.d"

# Bootstrap init file
cat >"${BOOTSTRAP}/.emacs.d/init.el" <<EOF
  ;; # Correctly set-up emacs-user-directory
  (setq user-emacs-directory "${EMACS_USER_DIRECTORY}/")
  (setq user-init-file (concat user-emacs-directory "init.el"))

  ;; # Reset the HOME environment variable
  (setenv "HOME" "${HOME}")

  ;; # Load the real init file and clean-up afterwards
  (unwind-protect (load user-init-file)
    (delete-directory "${BOOTSTRAP}" :recursive))
EOF

# Forward remaining arguments to emacs
exec env HOME="${BOOTSTRAP}" emacs "$@"

1

如果用例是在Linux计算机的所有用户之间共享单个emacs配置“ .emacs.d”目录,则此解决方案https://emacs.stackexchange.com/a/4258/5488在大多数情况下都可以使用,但是在某些情况下在emacs尝试将临时文件写入到user-emacs-directory的情况下(例如.ido.last文件)。在这种情况下,如果共享配置目录对所有用户都具有写许可权,则它将起作用,但可能不是理想的解决方案,因为每个系统用户可能不想共享同一目录来存储临时文件。在这种情况下,以下解决方案将是更好的选择。

通用共享配置文件.emacs.d / init.el应该以

;; should come before calling package-initialize as it will populate
;; everything under common config "~/.emacs.d/elpa"
(setq user-init-file (or load-file-name (buffer-file-name)))
(setq package-user-dir (concat (file-name-directory user-init-file) "elpa"))

(package-initialize)

使共享的配置.emacs.d具有对所有用户的读取权限(不需要写入权限)

another_user $ emacs -q --load /path/to/shared/config/.emacs.d/init.el

每个用户都有自己的“〜/ .emacs.d /”目录,但仅用于保存临时文件,但软件包和其他配置是从共享config目录中加载的。

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.