如何优雅得为不从package.el安装的包生成autoloads?

Emacs插件的机制本来就是基于Elisp热替换环境和各种 hook, advice

所以相互依赖本身就很脆弱, 如果建立依赖的机制, 只要一个包升级挂了, 其他稳定的包都会挂, 即使其他包一点毛病都没有.

想遇到这种依赖底层的函数的问题, 比如判定光标是否在字符串中, 我都会在我的很多插件中重复一部分的代码 (名字改一下):

(defun color-rg-current-parse-state ()
  "Return parse state of point from beginning of defun."
  (let ((point (point)))
    (beginning-of-defun)
    (parse-partial-sexp (point) point)))

(defun color-rg-in-string-p (&optional state)
  (or (nth 3 (or state (color-rg-current-parse-state)))
      (and
       (eq (get-text-property (point) 'face) 'font-lock-string-face)
       (eq (get-text-property (- (point) 1) 'face) 'font-lock-string-face))
      (and
       (eq (get-text-property (point) 'face) 'font-lock-doc-face)
       (eq (get-text-property (- (point) 1) 'face) 'font-lock-doc-face))
      ))

(defun color-rg-string-start+end-points (&optional state)
  "Return a cons of the points of open and close quotes of the string.
The string is determined from the parse state STATE, or the parse state
  from the beginning of the defun to the point.
This assumes that `color-rg-in-string-p' has already returned true, i.e.
  that the point is already within a string."
  (save-excursion
    (let ((start (nth 8 (or state (color-rg-current-parse-state)))))
      (goto-char start)
      (forward-sexp 1)
      (cons start (1- (point))))))

这样做的好处是, 所有插件都可以单文件保持独立, 互相不影响.

Package.el给人的假象有三个:

  1. 稳定可以升级, 其实并不是, Emacs这种基于 api/hook 约定的插件机制注定一个包挂了, 会导致升级影响很多, 排错要花巨大的时间, 为什么? 因为当你发现错误的时候, 本地的Elisp插件文件都换了一大批, 没有git怎么回滚定位问题?

  2. 插件是稳定无bug的版本, 没有人懂所有的Elisp插件, 也没有任何开发者都会保证自己的 master 分支稳定, 所以, 如果觉得只要更最新的git就是最稳定的版本, 本身这种假设就是不适合用户的, 除非你就想天天帮别人提issue和修bug.

  3. 政治正确的, 感觉不使用ELPA就是不正确的, ELPA才是正确的方式. 我个人认为, Emacs在Elisp上就没有版本管理的强制约束, 更没有API兼容性的要求, 基本上都是看开发者的心情, 所以改API是非常正常的事情, 只要自己的插件不挂就可以了.

什么是我的建设性意见?

  1. Package.el只适合入门, 你可以快速体验Emacs功能的时候用, 这就是Package.el最大的价值, 值得肯定
  2. 学Elisp编程, 学的越多, 你才会真正的用好Emacs, 甚至按照自己的要求随便玩不会挂
  3. 基于Git和Submodule去管理你自己的插件, Elisp本来就是放到 load-path 以后, 就随便 require 的机制, 基于 Git 管理, 随时挂了都可以回滚
  4. 插件都有核心功能和锦上添花的功能, 核心功能可以用就没有必要天天升级, 工具是Emacs, 而不是我们.
  5. 不要去教条的把Linux包管理的概念套用在Emacs, 然后就认为有包管理器就一定好, Emacs这种热替换的解释器本身就变化很快, 热替换是它的优点和自由, 版本管理和依赖管理是无法约束它的, 让它又复杂适应用户需求又不会挂.

这个世界上稳定、最新和个性化只能取一个平衡, 让自己舒服后赶紧干活去, 没有完美的方案, 也不要期望天天升级就会稳定.

唯一保证Emacs永远稳定的方法就是学Elisp编程, 没有别的更好的方法.

12 个赞