如何提供需要修补flymake的模块,启动时间最短(=自动加载),对用户的emacs.el影响最小?
我正在研究flymake-for-csharp模块。它适用于flymake,教它如何使用C#代码文件更灵活。例如,flymake-for-csharp不仅可以使用makefile,还可以使用.csproj文件,也可以直接调用csc.exe。
模块工作正常。我现在正试图让它自动加载。
这是挑战。
要定义哪些语言可以使用flymake,flymake.el包含一个文件扩展名列表(.java,.cs,.c等)以及每种语言的init和cleanup例程。在默认的flymake.el中有一个C#条目,但正如我所说,默认的C#行为不够灵活。为了使其更灵活,我需要替换flymake alist中的C#条目,以便它指向flymake-for-csharp模块中的新init / cleanup逻辑。雅跟我?
在运行时修补alist没问题。它看起来像这样:
(let (elt
(csharp-entry nil)
(masks flymake-allowed-file-name-masks))
;; Find the existing C# entry
(while (consp masks)
(setq elt (car masks))
(if (string= "\\.cs\\'" (car elt))
(setq csharp-entry elt))
(setq masks (cdr masks)))
;; remove the original entry for C# ...
(if csharp-entry
(setq flymake-allowed-file-name-masks
(delete csharp-entry flymake-allowed-file-name-masks)))
;; Now add a new entry for C#, with the custom init and cleanup methods.
(setq flymake-allowed-file-name-masks
(cons
'("\\.cs\\'" flymake-for-csharp-init flymake-for-csharp-cleanup)
flymake-allowed-file-name-masks)))
长期解决方案是说服flymake和emacs的作者接受目前在flymake-for-csharp中的逻辑。然后alist将获得更灵活的init / cleanup例程, bob是你的叔叔。
但是现在我想让flymake-for-csharp与现有的(内置)flymake.el一起工作。问题在于:我如何制作flymake-for-csharp自动加载,同时仍然修补alist?
理想情况下,我希望用户的emacs.el看起来像这样:
(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil)
...可能有一个小(eval-after-load ..
部分。
但是你看,函数flymake-for-csharp-init
只会在之后被调用 flymake alist被修补以包含C#的新条目。
这种鸡与蛋的情况有什么办法吗?
我想到的一种方法是使用(require 'flymake-for-csharp)
代替autoload
。在flymake-for-csharp模块中,只运行补丁逻辑,然后以其他方式使用自动加载功能。这是个好主意吗?这是否需要我在2个不同的文件中提供flymake-for-csharp?
我想到的另一种方法是在flymake.el上使用eval-after-load
。在那我可以提供补丁功能。结合这个问题:
仅当flymake自动加载时才会起作用吗?当(外部)eval-after-load被评估时,已经加载的模块的eval-after-load中的逻辑会发生什么?
如何在不影响用户的emacs.el的情况下执行此操作?
总之, 如何交付需要修补flymake的模块,启动时间最短(=自动加载),对用户的emacs.el影响最小?
答案 0 :(得分:1)
如果我理解正确,让用户将其添加到.emacs
可以解决问题:
;;;###autoload
(eval-after-load "flymake" '(code-that-patches-flymake-allowed-file-name-masks))
(autoload 'flymake-for-csharp-init "flymake-for-csharp" nil nil)
现在,如果您与使用您的软件包的人合作,您可以使用loaddefs.el trick通过在;;;###autoload
之前放置eval-after-load
评论来自动加载此代码包中的行,然后重建loaddefs.el
文件。
但是,如果您希望在互联网中使用通用解决方案,则需要用户在.emacs
中同时包含这两行。
对您的清理代码发表评论,我相信它可以简化为:
(let ((csharpentry (assoc "\\.cs\\'" flymake-allowed-file-name-masks)))
(when csharpentry
(setcdr csharpentry '(flymake-for-csharp-init flymake-for-csharp-cleanup))))