子配置文件怎么require比较优雅?

最近又看了不少配置,所以又要提一些问题……

大家觉得一堆子文件全部都在init.el中require比较好,

还是弄一个诸如init-core.el之类的“分文件”,在init.el中require这个分文件,然后在init-core.el之类的分文件中再去require下级的子文件比较好?

我选择在一个 org 文件中 require 所有依赖 :stuck_out_tongue_closed_eyes:

好吧……没玩过那么高端的

写一个宏在配置的同时自动 require

我开始写配置了,配置的前两个函数是这样的:

;;; Load Path
(defun add-to-load-path (&rest dir)
  "Add DIRs to `load-path'."
  (let ((arg (car dir)))
    (when arg
      (add-to-list 'load-path arg)
      (add-to-load-path (cdr dir)))))

(defun add-to-load-path-if-exists (&rest dir)
  "Add existed DIRs to `load-path'."
  (mapc (lambda (x)
          (when (file-exists-p dir)
            (add-to-load-path dir)))
        dir))

其实是 Spacemacs 两个函数的重写:

(defun add-to-load-path (dir) (add-to-list 'load-path dir))

(defun add-to-load-path-if-exists (dir)
  "If DIR exists in the file system, add it to `load-path'."
  (when (file-exists-p dir)
      (add-to-load-path dir)))

感觉药丸。

我目前还是简单粗暴的在init.el中require所有的文件……

毕竟我想不出缩小init.el有什么好处……

;;; Misc
(defmacro repeat-def-syntax (func rule &rest args)
  "Repeat FUNC with RULE on cadr of ARGS as second argument, and an optional
third argument."
  (declare (indent 2))
  (append '(progn)
          (loop for i in args
                collect (list
                         func
                         (car i)
                         (funcall rule (cadr i))
                         (or (cl-caddr i))))))


(defvar inferno-start-directory
  user-emacs-directory
  "Inferno start directory.")
(repeat-def-syntax defconst
    (lambda (x) (expand-file-name inferno-start-directory x))
  (inferno-init-directory
   "boot/"
   "Inferno essentials.")
  (inferno-lib-directory
   "lib/"
   "The function and variable library of inferno.")
  (inferno-config-directory
   "etc/"
   "Per-package related configurations.")
  (inferno-lisp-directory
   "lsp/"
   "Additional lisp scripts.")
  (inferno-resource-directory
    "share/"
    "Where the extra resources go.")
  (inferno-user-directory
   "usr/"
   "Users own .emacs.d."))

这就是奇妙的宏。

(eval-when-compile
  (if (featurep 'core-lib)
      (require 'core-lib)
      (signal 'quit '("kernel.el is not compiled. You must run install script to compile inferno first."))))

把这段放在配置主体的前面,这样就可以防止配置未被编译,主要依赖未安装的情况下被加载,同时不给编译好的配置增加冗沉代码。

有时候,简单粗暴是最有效的方式,因为毕竟是一套配置,只要满足自己的需要就可以了, 模块化等增强扩展能力的方式有时候有杀鸡牛刀的感觉

(defmacro repeat-declare-syntax (mark form &rest args)
  "Repeat MARK with coresponding FORM on each of ARGS as arguments.
If FORM is a function, it is only applied to the secound element of ARGS"
  (declare (indent 2))
  (append '(progn)
          (loop for i in args
                collect `(,mark
                          ,(if (and (listp i) (not (eq (car i) 'quote)))
                               (car list)
                             i)
                          ,@(cond ((or (not (listp i)) (eq (car i) 'quote))
                                   nil)
                                  ((functionp form)
                                   (list (funcall form (cadr i))
                                         (cl-caddr i)))
                                  ((not form)
                                   (cdr i))
                                  (t
                                   (loop for x in form
                                         for y in (cdr i)
                                         collect (funcall x y))))))))


(repeat-declare-syntax require nil
  'inferno-pkg
  'foo
  'bar
  ...)

升级版。让你节约好几个字节,减少复制粘贴。