如何使用生成字符串的函数覆盖类型为string的Emacs defcustom
实现方案
你可以通过拆分通用逻辑到全局配置、项目仅传专属参数的方式实现需求,具体操作如下:
1. 全局配置(写入 init.el)
将两个Python环境变量的通用构建逻辑封装为独立函数,全局生效:
;; 封装Python环境变量设置逻辑,接收项目专属的direnv-python路径作为入参 (defun my-setup-python-project-env (direnv-python-path) (when (and projectile-project-root direnv-python-path) ;; 生成虚拟环境根路径并赋值给defcustom变量(buffer本地生效) (setq-local python-shell-virtualenv-root (expand-file-name direnv-python-path projectile-project-root)) ;; 生成pytest可执行文件路径并赋值 (setq-local python-pytest-executable (expand-file-name (concat direnv-python-path "/bin/pytest") projectile-project-root))))
注:如果需要兼容未启用projectile的场景,可以把
projectile-project-root替换为Emacs内置的(project-root (project-current))获取项目根路径。
2. 项目配置(写入对应项目的 .dir-locals.el)
每个项目仅需指定专属的direnv-python路径即可,无需重复写构建逻辑:
((nil . ((eval . (my-setup-python-project-env ".direnv/python-3.7.2")))))
如果需要在项目其他配置中复用direnv-python的值,也可以显式声明为目录局部变量:
((nil . ((direnv-python . ".direnv/python-3.7.2") (eval . (my-setup-python-project-env direnv-python)))))
原理说明
- 类型为string的
defcustom本质上是可修改的配置变量,setq-local设置的buffer本地变量优先级高于defcustom的全局默认值,仅对当前项目的文件生效,不会修改全局配置。 - 函数最终赋值给两个变量的是
expand-file-name返回的字符串,和defcustom要求的string类型完全匹配,不会触发类型校验错误。
内容的提问来源于stack exchange,提问作者Cor
相关产品推荐
相关产品推荐

