歡迎您光臨本站 註冊首頁

emacs 小技巧:根據主模式載入配置

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  

很多人的配置文件,各種主模式的配置寫在一起的,可能既有 c 又有 lisp 又有 js 什麼的,其實大部分情況下你不會同時用那麼多。

於是有了另一種方式,拆分到文件,每種模式用一個單獨的文件。在主配置文件里寫上 (load 'xxx)

但是這挺麻煩的,你要新建一個文件名為 xxx,然後主配置文件里又得寫 load xxx,這顯然是重複勞動……這是我最痛恨的……因為我一年級就上了好幾次

於是我弄了一個文件夾,按順序自動 load 裡面的文件,當然不是隨便 load,得符合條件才行。比如我設定的條件是擴展名為 el。

這樣一來,不想 load 的文件改下擴展名就可以了……我還弄了一個函數,專門給文件添加/刪除擴展名 .bak 但是時間長了也挺麻煩的,因為要手動改,而且下次才能生效…… 你還得自己 load-file

……其實一般情況下,這不是什麼問題,你就是給每種模式寫上幾萬行的配置,都寫在一個文件里,對於現在的機器而言,壓力也不是太大……但是咱追求的不是方便,而是折騰

好了,開始動手

  (let (name        (dir (expand-file-name "_major-mode/" *init-dir*)))    (mapcar     (lambda(x)       (setq name             (file-name-sans-extension (file-name-nondirectory x)))       (add-hook  (concat-symbol name "-mode-hook")                 `(lambda()(load ,x))))     (directory-files dir t "\\.el\\'")))  
簡單的說,假設 ~/init.emacs/_major-mode/ 目錄下有 3 個文件 emacs-lisp.el nxml.el js2.el.bak ,則會:

在 emacs-lisp-mode-hook 里添加 (lambda nil (load "~/init.emacs/_major-mode/emacs-lisp.el"))

在 nxml-mode-hook 里添加 (lambda nil (load "~/init.emacs/_major-mode/nxml.el"))

裡面用到的 concat-symbol

(defun concat-symbol (&rest lst)    (read (apply 'concat (mapcar (lambda(x)(if (symbolp x) (symbol-name x) x)) lst))))  
需要注意的是,這簡直就是一個特大號的 hook ,所以不用在裡面再寫什麼 add-hook 'xxx-mode-hook 了,裡面所有的東西都相當於在 xxx-mode-hook 里。

如此一來,就產生了另一個問題,每打開一個 a.xxx 文件,xxx-mode-hook 就要運行一次,然後 load 一次,真二,實際上只要 load 一次就可以了。

這個問題可以用 require 來解決,但缺點是,你要在新建一個文件為 xxx.el ,還要在裡面寫 provide 'xxx ,並且還要把當前目錄加到 load-path,重複勞動還是比較多。

另一種方案就是 load-once

  (defmacro load-once (&rest s)    (let* ((name (file-name-sans-extension                  (file-name-nondirectory                   (or load-file-name (buffer-file-name)))))           (a (concat-symbol "*load-once--" name "*")))      `(if (boundp ',a)           nil         ,@s         (setq ,a t))))  

在 xxx.el 裡面只運行一次的部分可以寫在 load-once 裡面,像這樣

  (load-once   (foo)   (bar)  )  
基本上,你把所有內容都寫在 load-once 裡面就對了,不管這個文件被 load 了多少次,都只運行一次。

這種方法的缺點是,需要在文件開頭和結尾分別寫 (load-once 和 ),而 provide 只要寫在一處; 每種模式被 load 后,自動生成了一個值為 t 的變數 *load-once--xxx* 、*load-once--yyy* ……

所以,我覺得我有責任給你一個十分專業的建議:你自己看著辦

我的配置文件

或者也可以根據 buffer-name 來判斷

  (let* ((dir (expand-file-name "_extensions/" *init-dir*))         (ext (mapcar               (lambda(x)(cons (file-name-sans-extension (file-name-nondirectory x)) x))               (directory-files dir t "\\.el\\'"))))    (add-hook 'find-file-hook              `(lambda ()                 (load (or                        (cdr (assoc (or (file-name-extension (buffer-name))                                        (and (string-equal "*" (substring (buffer-name) 0 1))                                             (substring (buffer-name) 1 -1)))                                    ',ext))                        (make-temp-name ""))                       t))))  
假設在 init-dir/_extensions/ 目錄下文件為: xml.el el.el js.el eshell.el

普通文件通過擴展名來載入配置,xxx.js -> load js.el

以 * 開頭的臨時文件則去掉第一個和最後一個字元后,通過得到的名字來載入配置,eshell -> load eshell.el



[火星人 ] emacs 小技巧:根據主模式載入配置已經有387次圍觀

http://coctec.com/docs/linux/show-post-65264.html