Elisp 09:庫

上一章:文本跨行提取segmentfault

從第 1 章就定義了的 princ\' 函數被我一路使用至今,我一直以爲它頗有用處,特別是在我調試程序的時候。我認可,用這種辦法調試程序很原始。不過,筷子也很原始。爲了避免再張貼完整的代碼之時附上它的定義,我決定創建一個 Elisp 庫,用於存放它的定義以及從此我定義的其餘函數。bash

庫文件

我將這個庫的所有代碼存放在一份名爲 newbie.el 文件裏,目前只有 princ\' 的定義:函數

(defun princ\' (x)
  (princ x)
  (princ "\n"))

可是,newbie.el 應當放在何處?操作系統

EMACSLOADPATH

系統環境變量 EMACSLOADPATH 可爲庫文件指定路徑。假設我將 newbie.el 放在 $HOME/.my-scripts/elisp 目錄裏,那麼在個人機器上,因爲我用的 Shell 是 Bash,所以可在 $HOME/.bashrc 文件裏設定調試

export EMACSLOADPATH=$HOME/.my-scripts/elisp:$EMACSLOADPATH

在當前終端裏執行code

$ source $HOME/.bashrc

或從新打開一個終端窗口,令上述設定生效。接口

庫的載入

假設我要寫一個 foo.el 程序,它須要調用 newbie.el 裏定義的函數 princ\',只需在調用 princ\' 以前,載入 newbie.el 便可。例如ip

(load "newbie")
(princ\' "Hello world!")

在終端執行 foo.el 程序,get

$ emacs -Q --script foo.el

程序輸出emacs

Loading /home/garfileo/.my-scripts/elisp/newbie.el (source)...
Hello world!

load 函數是 Elisp 的內建函數,它的第一個參數是庫文件名,可是沒有擴展名。由於 load 函數會在 $EMACSLOADPATH 指定的目錄中自動搜索三種庫文件。對於上例,load 函數會依序搜索 newbie.elc,newbie.el,newbie.ext 這三個文件,只要搜到其中之一,搜索過程便終止,而後將搜到的文件內容載入至當前程序。newbie.ext 中的「ext」取決於系統平臺,在 Linux 系統裏,「ext」是「so」;在 Windows 系統裏,「ext」是「dll」;亦即 newbie.ext 能夠是 C 語言接口的共享庫。沒錯,Elisp 能夠載入 C 庫,可是須要爲它們編寫接口綁定,這是後話,暫且不表。

若是不但願程序執行時在終端輸出庫的加載信息,只需令 load 函數的第三個參數爲 t

(load "newbie" nil t)

其中,第 2 個參數是被迫寫上的,由於沒有第 2,怎麼會有第 3 呢?第 2 個參數若是是 nilload 函數在搜索不到待載入的庫文件時會在終端裏輸出錯誤信息,不然不會。

load-path

系統變量 EMACSLOADPATH 的設定,依賴於具體的操做系統。不依賴操做系統的庫文件搜索路徑的設定方法也是有的。Emacs 有個全局變量 load-path,它是列表。

若是我將 foo.el 程序修改成

(load "newbie" nil t)
(princ\' load-path)

執行該程序,在個人機器上會獲得如下結果:

(/home/garfileo/.my-scripts/elisp /usr/share/emacs/27.2/lisp ...)

不難發現,我經過 EMACSLOADPATH 設定的路徑也被加入到了這個列表。

用 Elisp 語言如何操縱列表,如今應該是不廢吹灰之力,所以將 foo.el 程序寫成

(setq load-path (cons "$HOME/.my-scripts/elisp" load-path))
(load "newbie" nil t)
(princ\' "Hello world!")

沒什麼理由不會在終端裏輸出

Hello world!

不過,Elisp 對列表提供了幾個能夠添加元素的函數,例如 push。如下代碼

(push "$HOME/.my-scripts/elisp" load-path)

(setq load-path (cons "$HOME/.my-scripts/elisp" load-path))

等價。

結語

能少些一些代碼,很不錯。

相關文章
相關標籤/搜索