绕开 Emacs 自带的 Customize 系统

Emacs 的 Customize 系统并不是个可选功能,有些地方强制使用它,比如 package.el,还有些不少变量不知不觉就保存了下,如 Global Minor Mode。这两天 Emacs 用到一半突然 XX Mode 就自动开了,刚刚才意识到是 Customize 系统引起的。

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(basic-auto-number 10)
 '(chunyang-display-mark-and-pos-mode nil)
 '(custom-enabled-themes (quote (sanityinc-tomorrow-eighties)))
 '(org-agenda-files (quote ("~/foo.org")))
 '(package-selected-packages
   ...)
 '(paradox-github-token t)
 '(pdf-view-midnight-colors (quote ("#b2b2b2" . "#292b2e")))
 '(safe-local-variable-values
   ...)
 '(transient-mark-mode t))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(org-checkbox ((t (:inherit org-todo)))))

所以我打算绕开 Emacs 自带的 Customize 系统:设置 custom-file,但不加载它。

(setq custom-file "~/.emacs.d/custom.el")
;; (load custom-file)

这方法貌似陈斌的配置里就这样用? 取而代之的是一个他自己custom的配置

陈斌有加载的:

看来是我记错了 :smile:

这么说,设成NUL不就行了。。。

默认值就是 nil,这样会直接把 Customize 设置保存到你的 init file 中,十分疯狂。

我指/dev/null或Windows下的nul。。。emacs里是null-device

不加载 custom.el,那么 safe-local-variable-values 存放在哪里?配置代码里?但是不可能预料到会有什么 variable 和 value,所以只好每次打开文件都要回答 yes/no 了:

或者把检测关掉。

除此之外,还有些 package 在首次启用的时候,会根据当前系统/环境/shell记录一些信息到 custom.el,供下一次启动使用。如果下一次启动没有读取到相关信息,这些 package 会不会再写一次 custome.el

如果有 package 设置了某些我不希望的 custom 变量值,我这样处理:

(unless (eq some-variable expected-value)
  (customize-set-variable 'some-variable expected-value))

这比完全抛弃 custom.el 要简单。

另外,customize-set-variable 不会立即写文件(所以对启动速度影响很小),只有当某个 package 触发了 (custom-save-all) 或手动 [Apply and Save] 了 custom,才会写入文件。

1 个赞

修改下package的功能,不保存到 custom.el 就可以了。Centaur Emacs 里有这样的配置。

其实我觉得emacs搞这个safe variable不是很有必要,它保护的主要是用户不想执行某些配置代码。其实用户不想执行,为什么不把这些东西去掉。。。

打开陌生文件的时候就有必要了

我觉得Emacs可以提供一个统一的保存状态的接口,类似于网页的cookie和cocoa的plist。省得各种包在.emacs.d下面创建各种点文件。

customize有这种效果,但是这个不是其主要目的。

另外,customize能不能直接导出setq代码而不是放到customize文件里?感觉这样反而实用一点。

没错,不放在 custom.el,就得放在别的地方。总是需要有个地方保存当前环境相关的信息,这个地方肯定不是配置代码文件。

比如我在公司和个人电脑上分别设置不同的用户名、email 等信息,这些放在配置代码里是不合适的,custom.el 是个很好的选择(把它当作全局的 .dir-locals.el 就很好理解了)

我配置了 dark 和 light 两套 theme,当其中一套用太久,视觉疲劳了,就通过 theme/switch-to-xxx 换另一套,并且希望接下来很长时间都接着使用这套 theme。配置代码是无法察觉我的选择的,所以我在调用 theme/swith-to-xxx 函数的时候,往 custom.el 写一个 theme:selected-theme 标志,来记录当前 theme 的名字。

当我在一台全新的 mac 上使用 Emacs,初始化的同时要设置 iTerm2.app 的快捷键(以便我在 Emacs 中操控 iTerm2):

(add-hook 'after-init-hook
            (lambda ()
              (unless osx:iterm-key-mappings-p
                (message ">>> osx/set-iterm-key-mappings")
                (osx/set-iterm-key-mappings)
                (customize-save-variable 'osx:iterm-key-mappings-p t))))

这个过程相当耗时,如果不在 custom.el 做标记,我如何以最小代价知道外部 Terminal 的快捷键已经设置过了?

1 个赞

从使用经验上看,主要是 package.el 安装删除包时保存了配置。平时只要不直接使用 customize 系统就不会再保存。我的解决方案是屏蔽掉 package 的保存动作,另外设置一个 custom.el,方便查看和管理。

可能我没有完全理解,看起来你的需求用定义一个变量(defvar/setq)不能解决吗?

不在于使用 defvar/setq 还是 customize-set-variable,而是有些变量的值不是配置代码能推断出来的,必须人参与决策(根据各种因素:公/私电脑,系统,终端,theme,local-variables。。。)

这个决策的结果,必须有个地方存放(不管是存放在 custom.el 还是别的文件),就像 cookie(而我们的配置文件则相当于 js 代码),否则每次启动 Emacs 都要重新交互一遍。

2 个赞

这点完全同意。