第一聲問候

前一篇《 Emacs 是一臺計算機

理解了 Emacs 身爲計算機的本質以後,在 Emacs 裏編程就瓜熟蒂落了。不過,在此以前,還須要略微介紹一下 Emacs 最基本的操做。html

系統的不一致,使人有點煩躁

如今,也能夠坦然地說,Emacs 是一臺虛擬的計算機,目前,它只能在宿主操做系統中運行,而這個宿主操做系統能夠是 Windows、Linux 或 Mac OS X。因爲這個世界上絕大多數計算機所運行的操做系統不外乎這三者之一,所以無需擔憂無 Emacs 可用。node

如今假設你對本身所用的操做系統足夠熟悉,至少達到可以從 https://www.gnu.org/software/... 頁面找到與本身所用的操做系統匹配的 Emacs 版本的安裝包併成功安裝的程度,那麼我就假設你的操做系統中已經存在了一個可用的 Emacs。此外,我還得假設你知道怎麼打開你所用的操做系統的命令行窗口。編程

命令行窗口,在 Windows 裏,叫控制檯或命令行提示符,而在 Linux 與 Mac OS X 裏,則稱爲終端(Terminal)。segmentfault

實際上,Windows 裏所謂的命令提示符,這真的是一個很奇葩的名字,它其實是以命令行窗口中裏 > 符號的名字。在 Linux 與 Mac OS X 的終端裏,命令提示符是 $。所謂命令提示符,意思是在這個符號的後面能夠輸入命令,這個符號自己不須要你輸入。下文以 $ 做爲命令提示符。編輯器

啓動 Emacs 的命令以下:函數

$ emacs

執行這條命令以後,能夠獲得如圖 1 所示的窗口,這或許是你有生以來第一次看到 Emacs,記住這一天。工具

接下來,在 Emacs 裏執行第一個命令 C-x C-f。這是 Emacs 特點的組合按鍵序列的表現形式,其含義:摁住 Ctrl 鍵,單擊 x 鍵;摁住 Ctrl 鍵,單擊 f 鍵。執行這一命令後,觀察 Emacs 窗口,它的底欄應該會出現 Find file: ... 字樣,其中 ... 是 Emacs 的當前工做目錄的路徑。在此,我不得不繼續假設你知道在一個操做系統中一個工做目錄的路徑指的是什麼。或許 Windows 用戶對此不甚瞭解,下面略做解釋。spa

當你打開 Windows 命令提示符窗口的時候,窗口中應該會出現像下面這樣的字樣:操作系統

C:\Users\用戶名 >

這個 C:\Users\用戶名 就是當前的工做目錄的路徑。命令行

再回到 C-x C-f 按鍵在 Emacs 底欄召喚出來的 Find file: ...,如今,在 ... 以後輸入 foo.txt,而後擊回車(Enter)鍵,這樣便在工做目錄中建立了一份名稱爲 foo.txt 的文本文件。這份文件沒有什麼特殊意義,它只不過是爲了讓你體驗 Emacs 而隨便建立的一份文本文件。

從如今開始,將 Emacs 用於接受咱們輸入 foo.txt 文件名的底欄稱爲微緩衝區(Minibuffer)。微緩衝區是咱們向 Emacs 傳遞各類按鍵序列以及命令的通道。

當 Emacs 在工做目錄中建立一份新的文件時,它會在微緩衝區上方的窗口中爲這份文件建立一個緩衝區。這個緩衝區就叫緩衝區,它對應一塊內存區域,能夠與硬盤上的文件相關,也能夠無關。之後,當我談及「緩衝區」的時候,指的就是微緩衝區上方的緩衝區。

咱們在緩衝區中編輯文本,在須要將所編輯的內容保存到與緩衝區相關聯的文件裏之時,只需向 Emacs 發出 C-x C-s 指令——摁住 Ctrl 鍵,擊 x 鍵;摁住 Ctrl 鍵,擊 s 鍵。

C-x C-fC-x C-s 這樣的組合鍵,因爲每組按鍵都須要摁住 Ctrl 鍵,所以能夠採用相似「英文連讀」的方式減小按鍵次數,即摁住 Ctrl 鍵,依次單擊 xf,或依次單擊 xs

咱們對 Emacs 的操做暫時只需瞭解這麼多。假若你學有餘力,可繼續閱讀我寫的另外一份文檔 [1]。

hello, world

這個世界上,被重複寫過最多的一個程序,它的名字叫 hello world。始做俑者是《The C Programming Language》的做者 Brain Kernighan。無數初學編程的人,用這個程序向計算機軟件世界發出了第一聲問候。

在 Emacs 中,咱們不妨也貫徹一下這個儀式。在上一節所創建的 foo.txt 文件緩衝區裏輸入 hello, world

對此,請不要吝惜發出~噫~的聲音!

若真的是這樣的 hello world,不管是誰,都會感到失望。不過,因爲我此前將 Emacs 的窗口(還記得俄羅斯方塊嗎)稱爲顯示器。這種直接在緩衝區裏鍵入 hello, world 的方式其實很黑客,這是直接修改 Emacs 的顯存內容啊!

發出~噫~的聲音的人說,散了,散了,他就這兩下子!

固然不是。要經過一段程序,在 Emacs 窗口中顯現 hello, world,這須要瞭解一下 Emacs 的啓動配置文件 init.el。要了解這個文件,須要繼續爲三大操做系統的不一致而煩躁。

Emacs 的 HOME 目錄

init.el 文件是 Emacs 的啓動配置文件。它應該位於 HOME 目錄的 .emacs.d 子目錄中。

對於 Windows 用戶,假若你的操做系統安裝在 C 盤。對於 Windows 7 或更新的版本,Emacs 會將 C:\Users\<用戶名>\AppData\Roaming 做爲默認的 HOME 目錄。對於 Windowx 2000 或 XP,Emacs 會將 C:\Documents and Settings\<用戶名>\Application Data 做爲 HOME 目錄。對於……Windows 就是這樣麻煩啊,假若對此很煩躁,建議使用 Linux,或閱讀 Emacs 文檔中對 Windows 的 HOME 目錄的說明 [1]。

對於 Linux 與 Mac OS X 而言,因爲它們有點血緣關係,所以它們的 Emacs HOME 目錄就是 $HOME~,亦即操做系統的 HOME 目錄。

函數

init.el 文件是 Emacs 的配置文件。如今,假定你已經可以在本身的系統中找到 Emacs 的 HOME 目錄。接下來,就在這個目錄中建立 .emacs.d 目錄,而後使用 Emacs 在這個目錄建立 init.el 文件。使用其餘文本編輯器並不是不可,可是不要浪費使用 Emacs 編輯文件的實踐機會。

每當 Emacs 啓動時,它都會讀取 init.el,認真貫徹這個文件中的一些設定。所以,咱們能夠在這個文件中寫一個 hello world 程序,讓 Emacs 可以在緩衝區中顯現 hello, world。之後,這個文件就是咱們在 Emacs 環境裏的編程實驗場地。

在開始寫這個 hello world 程序以前,先體驗一下如何經過 init.el 調整 Emacs 的外觀。

在 init.el 文件中寫入如下內容:

; 關閉菜單、工具欄、滾動條
(tool-bar-mode 0)
(menu-bar-mode 0)
(scroll-bar-mode 0)

而後從新啓動 Emacs,發現它的菜單、工具欄以及滾動條都不見了。

上述內容,以 ; 開頭的語句是 Emacs Lisp 的註釋語句,會被 Emacs 忽略。以後的三行語句,對於 Emacs 而言,是三個程序,由於以前很認真地說過,Emacs 是計算機。init.el 中的內容,對於 Emacs 而言就是一組指令,而每條指令均可以視爲一個程序。

因爲咱們一般所遇到的程序每每是由很複雜的代碼構成。將這簡短的三行代碼視爲三個程序,有煞有介事之嫌。那麼,咱們就將它們稱爲表達式。對於 Emacs 而言,init.el 中的每對小括號包含的文本,只要它不屬於註釋語句,對於 Emacs 而言都是表達式,要牢記這一點。

(tool-bar-mode 0) 爲例,這個表達式可讓 Emacs 在啓動時關閉工具條。假若將這個表達式改成 (tool-bar-mode 1),那麼下次開啓 Emacs 的時候,工具條又會被打開。顯然,是語句中的 01 決定着 Emacs 是關閉仍是打開工具條。

假設你曾經認真學過中學數學,想必還記得函數吧?y = f(x),以映射的記法可寫爲 f: x -> y。假若將 tool-bar-mode 視爲 f,將 01 視爲 x,將工具條的關閉與打開這兩種狀態視爲 y,那麼 (tool-bar-mode 0)(tool-bar-mode 1) 在 Emacs 環境中所產生的做用,像不像 f: x -> y?

所以,像 tool-bar-mode 這樣的事物,在 Emacs 裏,是函數。上面在 init.el 中寫入的三行語句,其實是對三個函數進行求值。是誰在對函數進行求值,是 Emacs Lisp 解釋器!

定義一個函數

接下來,咱們能夠在 init.el 中定義一個函數,即在 init.el 文件的尾部新開一行,而後寫入如下內容:

(defun hello-world ()
  (interactive)
  (insert "hello, world"))

假若你的確是按照我說的,使用 Emacs 編輯 init.el 文件,那麼此刻只需使用 C-x C-s 即可將上述內容保存到 init.el 文件中,

如今關閉 Emacs,而後從新啓動它,再從新打開剛纔建立的 foo.txt 文件。這樣 Emacs 便會從新讀取 init.el 文件,可是此次它會讀取上述語句。先不考慮 Emacs 對它們做何處置,如今,先在 Emacs 中嘗試輸入 M-x hello-world <RET> 命令,看看會緩衝區裏會出現什麼。這條命令裏的 M-x 表示摁住 Alt 鍵,而後單擊 x,而後鬆開 Alt 鍵,接下來繼續輸入 hello-world,而後單擊回車鍵。因爲在 Emacs 中,每當使用 C-xM-x 時,Emacs 都會認爲你要向它發出命令,因此它會使用微緩衝區接受你後續的輸入。個人表述雖然有些冗長,可是假若你真的動手嘗試兩三次,就自會明白這一切。

向 Emacs 發送 M-x hello-world <RET> 命令以後,結果會怎樣呢?結果就是在 Emacs 當前的緩衝區裏出現了 hello, world

這是咱們向 Emacs 世界發出的第一聲真正的問候。

函數的定義是表達式

對於 Emacs 而言,像

(defun hello-world ()
  (interactive)
  (insert "hello, world"))

這樣的語句,雖然它彷佛有些特殊——能夠造成一條指令,但它依然是一個表達式。上文曾說過,在 init.el 中,每對小括號包含的文本,只要它不屬於註釋語句,對於 Emacs 而言,都是表達式。上述文本雖然比 (tool-bar-mode 0) 這樣的表達式更復雜了一些,但因爲它是以 ( 開始又以 ) 結尾,因此它是一個表達式。前文也說過,Emacs Lisp 解釋器會對錶達式進行求值。那麼對於上述表達式,求值結果是什麼呢?如今若不過於探究細節的話,不妨將這個求值結果視爲在 Emacs 環境裏定義了一個名爲 hello-world 的函數,而且這個函數不接受任何參數。

不接受任何參數的函數,至關於一個常量函數,相似於 y = 1 這樣的函數。所以,上述的 hello-world 函數是一個常量函數,函數值永遠爲 (insert "hello, world"),這對於 Emacs 而言,又是一個表達式,而這個表達式是對 insert 這個函數進行求值。求值結果是什麼?就是在緩衝區中出現 hello, world,這就是 Emacs 對在響應 M-x hello-world <RET> 命令後,對 hello-world 函數的最終求值結果。

爲何 hello-world 的求值結果不是 (interactive) 呢?能在不清楚 (interactive) 這個表達式的含義的前提下提出這個問題的人,都是好同窗。

hello-world 函數進行求值,本質上是對 hello-world 所包含的一組表達式進行求值。hello-world 包含了兩個表達式:

(interactive)
(insert "hello, world")

它們構成了 hello-world 函數的實體。函數的實體與函數的名稱經過 (defun ...) 表達式綁定到一塊兒,這就是所謂的函數定義。

Emacs Lisp 解釋器對 (defun ...) 這種表達式的求值邏輯較爲特殊,它會順序地對嵌入這一表達式中的子表達式按照前後進行排序,將最後一個表達式的求值結果做爲函數的求值結果。

(interactive) 也是一個表達式,暫時不須要關心它對 Emacs 起到了什麼做用—— Emacs Lisp 解釋器對它的求值結果,因爲它位於 (insert "hello, world") 以前,因此它的求值結果沒有資格做爲 hello-world 的求值結果。

公僕與民衆

那麼,(interactive) 的求值結果是什麼?讓 (defun ...) 定義的函數成爲 Emacs 命令——可在微緩衝區執行的命令。

能夠試着從 hello-world 函數中去掉 (interactive),即 hello-world 的定義變爲:

(defun hello-world ()
  (insert "hello, world"))

而後保存 init.el 文件,再從新啓動 Emacs,再從新打開剛纔建立的 foo.txt 文件,而後再次執行 M-x hello-world <RET> 命令,就會發現,Emacs 根本不知道你在作什麼。

所以,在 Emacs 的世界裏,有兩種函數,一種是能夠做爲命令執行的函數,它們就像一般所謂的程序同樣,另外一種則是普通的函數,它們默默無聞、甘於奉獻,爲那些能夠做爲命令使用的函數貢獻了光和熱。

重啓不是必要的

在上文中,每次修改了 init.el 文件的內容以後,爲了驗證修改的結果,須要關閉 Emacs 再從新啓動它,而後再次打開 foo.txt。這種操做過於繁瑣,形成了人民日益增加的美好生活須要和不平衡不充分的發展之間的矛盾。

事實上,咱們能夠打開兩個 Emacs 窗口,一個用於編輯 init.el,另外一個用於體驗 init.el 中的改動的效果,即用於編輯 foo.txt 文件。不妨前者稱爲「哼」窗口,將後者稱爲「哈」窗口。咱們在「哼」窗口中所做的任何改動,保存到 init.el 文件中以後,在「哈」窗口中,只需執行 M-x load-file <RET> ~/.emacs.d/init.el <RET>,即可讓修改後的 init.el 在「哈」窗口中生效。這條命令中的 ~ ,Emacs 會將其視爲 HOME 目錄路徑的簡寫。

之後,隨着對 Emacs 熟悉程度的增進,或者在閱讀文檔 [1] 以後,會發現打開兩個 Emacs 窗口也是沒必要要的。

下一篇勤勞,仍是懶惰?

[1] 走近 Emacs

[2] Emacs 文檔對 Windows 系統中的 HOME 目錄的說明

相關文章
相關標籤/搜索