Emacs加载前的setq设置

7
当定制Emacs时,我应该在加载包之前还是之后设置相应的变量?
例如,
(setq some-variable some-value)
(require 'some-package)

或者

(require 'some-package)
(setq some-variable some-value)

在我看来,大多数情况下两者都有效,除非某些包在加载后明确要求使用init。我说的对吗?


在大多数情况下,你不需要(require 'mode),除非你需要调用某些非自动加载的函数! - gavenkoa
2个回答

6
如果变量是用户选项,则在加载包之前执行。该包包含一个 defcustom ,用于定义选项,但是 defcustom 不会设置值,如果变量已经有值(例如,来自您的 setq )。
同样,如果变量是全局定义的变量而不是用户选项,即使用 defvar 由包定义。 defvar defcustom 一样,不会覆盖现有值。
另一方面,根据变量,有时您希望在加载包后更改其值。这完全取决于包的功能以及如何使用该变量。 无论我上面说了什么,在init文件中使用 setq 更改全局变量值(无论是否为选项),通常都是一个坏主意
对于选项,最好使用自定义UI进行自定义,或者在init文件中使用其中一个函数 custom-set-variables customize-set-variable (即明确地自己)。这是因为定义选项的 defcustom 可以具有“触发器”用于值初始化和更新(它还可以有其他特殊处理)。给定的 defcustom 可以依赖于在文件中出现在其前面的其他内容来评估其默认值表达式。
如果您只是使用 setq 来初始化或更新选项,则会绕过任何此类特殊处理,这可能不是您想要的,并且可能会导致意外情况。
同样,在一般情况下,除非您确定自己在做什么,否则简单地在非选项(即 defvar )变量上使用 setq 可能是一个坏主意。 我的建议:使用Customize,但不要让它写入您的init文件。相反,定义变量 custom-file (实际上,它是一个选项,但您不能真正像使用选项一样使用它),以便Customize将写入该单独的文件并使您的init文件供您手动修改。 (您仍然可以在init文件中使用 customize-set-variable 。)
如果您这样做,您需要从init文件中加载文件 custom-file 。您可以决定在init文件中的哪个时间点执行该操作,即您的init文件中的某个变量设置是否应在加载 custom-file 之前或之后(Customize管理的设置)。

我正在考虑使用“Customize”,但在这种情况下,您必须将所有自定义内容放在一个文件中。我仍然更喜欢像“prelude”中那样在“xxx-conf.el”中单独配置每个包。 - gongzhitaao
1
根据您的意思,您不必将所有自定义内容放在一个文件中。Customize会将其处理的所有自定义内容放在一个文件中,但您的其他自定义内容可以分散在任意数量的文件中。我认为这是个好主意,然而,通过定义变量custom-file并在适当的时候从您的init文件中加载该文件,可以将Customize管理的内容保持在init文件之外。 - Drew
从第一段可以得出结论,(load custom-file) 应该在 (package-initialize) 之前吗? - Jisang Yoo
@JisangYoo:也许吧 - 我对 package.el 不是很了解。我想,custom-file 中唯一的东西应该来自 Customize,我认为这可能是一个不错的选择。其他人可能有不同的意见。 - Drew

1
您说得对,通常这两种情况都是可以接受的。但在特定情况下不一定如此。
您必须明白,例如,如果您在运行Python进程后设置了python-shell-interpreter,它不会更改Python可执行文件。您必须杀死Python缓冲区并再次运行它,以使更改生效。
此外,有些变量绑定在文件加载时取决于另一个变量的值。因此,对基本变量的更改不会传播到派生值。只需阅读源代码以检查此内容即可。
因此,如果您将代码放置在.emacs中,则这两种情况大多相同,除非模式文档另有说明(请在手册中阅读有关Emacs加载过程的内容,在该阶段Emacs不处理任何用户缓冲区)。
但是,如果您在某些缓冲区处理之后更改变量,则可能无法正常工作。当Emacs处理用户缓冲区时,它可以初始化/填充内部缓存。很难找到这些缓存(您必须阅读源代码或文档)并理解如何重置或触发重新加载(将其设置为nil或调用某些mode-reinit函数)。
某些软件包(例如Gnus)允许清除卸载(gnus-group-exit),因此您可以像以前未加载一样重新加载它...
无论如何,我发现阅读Emacs源代码非常容易-如果您遇到问题,只需查看变量/函数声明以了解其设置方式和使用的值。
这是我的.emacs中的一个示例,在加载之前需要调整模式(因此本机Emacs不使用;,如果我更喜欢与Cygwin一起工作,则使用:在INFOPATH环境变量中)。
;; Assume that cygwin-mount already activated.
(when (featurep 'cygwin-mount)
  (setenv "INFOPATH" "/usr/share/info/:~/usr/share/info/:")
  ;; Redefine path-separator to UNIX to update Info-directory-list.
  (let ( (path-separator ":") )
    (require 'info)
    (info-initialize)
    ))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接