Emacs递归添加目录下所有插件
Emacs
2022-03-02 1155字

Emacs社区默认用下面的方式递归扫描目录下所有插件,并添加到Emacs加载路径 load-path 中:

(let ((default-directory "plugin_directory"))
  (normal-top-level-add-subdirs-to-load-path))

但是像EAF这种插件,子目录下有成千个NPM模块,会极大的增加Emacs启动扫描目录的时间,加之Emacs自身的 normal-top-level-add-subdirs-to-load-path 函数实现过于复杂,自己重新写了一个新的函数专门用于递归添加目录下所有插件。

(require 'cl-lib)

(defun add-subdirs-to-load-path (search-dir)
  (interactive)
  (let* ((dir (file-name-as-directory search-dir)))
    (dolist (subdir
             ;; 过滤出不必要的目录,提升Emacs启动速度
             (cl-remove-if
              #'(lambda (subdir)
                  (or
                   ;; 不是文件的都移除
                   (not (file-directory-p (concat dir subdir)))
                   ;; 目录匹配下面规则的都移除
                   (member subdir '("." ".." ;Linux当前目录和父目录
                                    "dist" "node_modules" "__pycache__" ;语言相关的模块目录
                                    "RCS" "CVS" "rcs" "cvs" ".git" ".github")))) ;版本控制目录
              (directory-files dir)))
      (let ((subdir-path (concat dir (file-name-as-directory subdir))))
        ;; 目录下有 .el .so .dll 文件的路径才添加到 load-path 中,提升Emacs启动速度
        (when (cl-some #'(lambda (subdir-file)
                           (and (file-regular-p (concat subdir-path subdir-file))
                                ;; .so .dll 文件指非Elisp语言编写的Emacs动态库
                                (member (file-name-extension subdir-file) '("el" "so" "dll"))))
                       (directory-files subdir-path))
          
          ;; 注意:add-to-list 函数的第三个参数必须为 t ,表示加到列表末尾
          ;; 这样Emacs会从父目录到子目录的顺序搜索Elisp插件,顺序反过来会导致Emacs无法正常启动
          (add-to-list 'load-path subdir-path t))

        ;; 继续递归搜索子目录
        (add-subdirs-to-load-path subdir-path)))))