程式扎記: [GNU 程式設計] 用 Emacs 編輯原始程式

標籤

2012年3月3日 星期六

[GNU 程式設計] 用 Emacs 編輯原始程式

前言 : 
Emacs 是"高手級程式設計師" 喜愛的編輯器. 多年以來它一直是自由軟體裡的 "旗艦" 產品, 廣受大家歡迎. 對大多數人來說, Emacs 是他們使用過的第一個自由軟體, 也是唯一用過的自由軟體 ; 換句話說, 它是自由軟體中最不可或缺的核心. 

Emacs 的發展最初由Richard Stallman於1975年在MIT協同蓋伊·史提爾二世共同完成。這一創意的靈感來源於TECMAC和TMACS,它們是由蓋伊·史提爾二世、Dave Moon、Richard Greenblatt、Charles Frankston等人編寫的巨集純文字編輯器。自誕生以來,Emacs演化出了眾多分支,其中使用最廣泛的兩種分別是:1984年由Richard Stallman發起並由他維護至2008年的GNU Emacs,以及1991年發起的XEmacs。XEmacs是GNU Emacs的分支,至今仍保持著相當的兼容性。它們都使用了Emacs Lisp這種有著極強擴充性的程式語言,從而實現了包括程設、編譯乃至網路瀏覽等等功能的擴充套件. 

開始使用 Emacs : 
讓我們從頭開始, 先輸入 emacs 命令, 後面跟著一個檔名 : 
% emacs sources.c

你會看到畫面 : 
 

螢幕上半部是編輯檔案的視窗, 視窗下方是一條狀態列, 說明編輯中的緩衝區名稱 (通常就是檔名), 目前的編輯模式 (C 語言模式). 

停止執行 Emacs : 
如果你要跳出 Emacs, 請持續按著 Ctrl 鍵, 並按順序按下 x 鍵與 c 鍵. 假如並無 "尚未儲存" 的檔案, 那麼 C-x C-c 會回到 shell. 假如更動檔案又尚未儲存, Emacs 會問你是否要儲存這個檔案, 如底下所示 : 
 

如果輸入 y 並 Enter, Emacs 會儲存檔案並跳離. 如果輸入 n, Emacs 會提示另一個問題 : 
Modified buffers exist; exit anyway? (yes or no)

如果回答 yes 並 Enter, Emacs 將跳離 (不會儲存變動) ; 如果輸入 no 並 Enter, Emacs 會停留在編輯畫面而不跳離. 

C 語言模式下的基本編輯 : 
在 Emacs 中編輯相當簡單. 基本上只要輸入程式碼即可. 所有命令不是以控制字元就是以脫逸 (ESCAPE) 鍵做開頭 ; 其它任何輸入都會被當作編輯內容送到編輯緩衝區. 螢幕上的游標提示下一個字元即將出現的位置. 底下是我們輸入的一段函式 : 

- 游標移動 
現在你可以輸入一段文字, 但如何編輯? Emacs 對於螢幕上游標移動命令相當複雜, 除了鍵盤的方向鍵, 你可以使用組合鍵提升開發效率. 輸入 C-p (previous) 回到上一列 ; 輸入 C-n (next) 移到下一列. 同列中往回移動一個字元可以輸入 C-b (back) 往回移動一個字元 ; C-f (forward) 往後移動一個字元. 

當然需要移動一大段距離也不是難事 ; 要執行同一命令四次, 只要在命令前加上 C-u ; 舉例來說, C-u C-p 會往上移動四列. 你也可以使用 C-u C-u C-p 會往上移動 4x4=16 列. 你也可以以單字或單句來移動游標. 一個字是由任意大小寫及小寫字母, 數字及錢號所組合而成. Esc b 會將游標移到移到字的開頭 ; Esc f 會將游標移到字的結尾. 這些命令與 C-b 及 C-f 相當類似. 使用 Escape 鍵與 Ctrl 鍵的差異是前者是單字檔向而後者是字元導向. 

在任一列, C-a 移動到這列的開頭 ; C-e (end) 移動到這列的結尾. 前面再加上 "Escape" 鍵, 可分別移動到句子的頭跟尾. 在編輯檔案中, ESC > 會移動到檔案結尾, ESC < 會移動到檔案開頭. 假如檔案比螢幕還寬, ESC v 會 "往上" 移動一個螢幕 ; 而 C-v 會 "往下" 移動一個螢幕. 

某些命令專門用來編輯程式, 例如 ESC C-a (按一下 Escape 鍵再按 C-a ; 也可以同時按住 ALT 及 Ctrl 及 a 三個鍵) 這個命令會回到函式開始的左大括號 ; ESC C-e 會到函式結束的右大括號. ESC a 會到一段敘述的開頭 ; ESC e 則到敘述的結尾. 下面是目前討論過命令的摘要說明 : 
 

如果你想要直接跳到程式的某一行, 可以先 ESC x 進入 M-x 後, 再輸入 "goto-line" 並按下 Enter. 接著在提示後輸入行數即可前往指定行數的代碼 : 
 

- 刪除本文 
現在你可以在檔案中自由移動, 但如何刪除代碼呢? 最基本的刪除命令是 DEL 鍵, 會刪除游標前的一個字元. 另一個 Emacs 中的刪除命令式 C-d, 它會刪除游標後的字元. 或者你可以使用 C-k 刪除整列 (整列的內容, 但該列還是存在.). 你也可以使用 "抹除 (wipe)" 命令 C-w, 來刪除任何大小區域的文本. 底下是其步驟 : 
1. 利用按 C-@ 來標示起始區域. 這稱為 "設定記號"
2. 移動游標到區域結束的字元.
3. 按下 C-w

此時被抹除的代碼會進入剪貼區, 你可以使用 C-y 貼回代碼. 或是想複製一塊區域而非剪下, 可以使用 ESC w 來取代 C-w

- 標示區 
Emacs 的 C 語言模式提供關於標示的一些額外功能. 你常常要標示出一個函示, 例如將整個刪除, 移動等等. 透過 ESC C-h 命令可以很容易達成, 這會使游標停在函式的一開頭標示整個函式, 直到函式結束的位置. 藉由這個功能你可以很容易知道目前正在編輯哪一個函式. 

還原已刪除的本文 : 
當然你常常需要恢復剛剛刪除的代碼, 在 Emacs 中, 這稱為 "貼上 (yanking)", 對應命令為 C-y. 可以用來取回 "刪除" 的那些列或 "抹除" 的區域 : 你會用 C-k 會 C-w 剪下代碼並用 C-y 再貼回代碼. 事實上 C-y 唯一不能回復的就是單一字元的刪除. 另外 Emacs 保留了前 30 個刪除內容在緩衝區, 讓你可以使用 C-y 貼回. 底下是刪除與還原代碼命令的摘要說明 : 
 

搜尋及取代 : 
搜尋及取代是編輯器的基本功能 ; Emacs 也不例外. 它支援許多搜尋及取代的方式, 這裡討論常用的部分. 

標準的 Emacs 搜尋是不分大小寫的遞增搜尋. Emacs 不區分大小寫字母, 只依你輸入位置來搜尋. 讓我們在範例程式搜尋 "data". 首先輸入 C-s 進入搜尋 (在下方出現 I-search:) : 
 

接著輸入搜尋字串 "data". 你會發現代碼中符合搜尋字串都被反白, 接著你可以連續按下 C-s 在這些滿足搜尋條件中跳躍直到那個你要的 "data" 到達. 結束搜尋請按下 Enter : 
 

使用 C-s 是向前搜尋, 如果你想往後搜尋可以使用 C-r. 搜尋的下一步就是 "搜尋並取代". Emacs 提供一個陽春的 "取代字串" 命令, 無條件取代符合搜尋條件的字串. 然而這不是最常用的命令, 更有用的取代命令是 "查詢 - 取代", 鍵盤命令為 ESC % . 

底下我們示範將 "data" 改成 "mydata". 首先將游標移到檔案開頭並輸入 ESC % . 此時下方出現 "Query replace:" 
 

接著輸入 "data", 結束後按下 Enter. 接著出現 "Query replace data with:" 提示你輸入取代字串 : 
 

接著輸入 "mydata", 結束後按下 Enter. 接著滿足被取代字串 "data" 都會被反白 : 
 

接著你可以如下處理找到的字串 : 
* 輸入 SPACE 或 y 代表進行取代, 再找下一個 "data"
* 輸入 ! 代表全面取代 (取代所有 "data" 成 "mydata")
* 輸入 DEL 或 n 不取代目前的 "data", 跳到下一個 "data"
* 輸入 ESC 或 q 來跳出搜尋/取代, 目前位置的字串不會被取代.
* 輸入 . 取代目前位置的字串並結束 搜尋/取代
* 輸入 ^ 回前一個符合字串.
* 輸入 C-r 進入往回搜尋.
* 輸入 C-h 取得線上說明.

儲存及檢索檔案 : 
和其他編輯器一樣, Emacs 用來存放代碼的緩衝區, 並非磁碟上所儲存的檔案. 你在螢幕上所見都是緩衝區的內容. 將所見所做的異動存到磁碟上實際的檔案的動作稱為 "儲存" 檔案. 存檔的動作相當簡單, 只要輸入 C-x C-s 就可以完成 : 
 

另外如果你想要另存新檔, 輸入 C-x C-w ; 會在下方提示區裡, 帶著路徑提示 : 
 

假設你要在當前路徑下另存新檔 "abc.c", 則在提示後輸入 "abc.c" 後按下 Enter 完成動作 : 
 

多重視窗 : 
某些情況你可能需要開多個視窗進行比對或是參考, 要把 Emacs 螢幕分成兩個視窗可以使用 C-x 2 命令 : 
 

如果你要在視窗切換, 可以使用命令 C-x o (小寫的 O). 如果你要開新檔, 可以使用 C-x C-f (find-file), 此時會在下方提示區出現 "Find file: ~/", 接著輸入你要開啟檔名並按下 Enter 便可以進行開啟新檔的動作 : 
 

如果你要關閉多視窗, 你可以使用 C-x 0 (數字的 0) 來關閉當前游標所在的視窗 ; 或是 C-x 1 來刪除所有視窗, 除了游標所在的視窗. 當刪除一個視窗, 事實上並非刪除編輯中的緩衝區, Emacs 仍然會保留緩衝區的內容. 稍後如果你再 "編輯" 這個檔案時, Emacs 會提供編輯過的緩衝區 (假設你有異動). 就算你使用 C-x C-c 關閉 Emacs, 之前關閉的視窗如果有異動, 仍然會在此時提示擬進行存檔. 

縮排與註解的輔助 : 
對程式員來說, Emacs 的一項重要特色, 在於它展現程式風格的能力. 這會是你的代碼有更高的可讀性. 

不用離開 Emacs 進行編譯 : 
ESC x 後接著輸入 "compile" 命令可以自動建構程式, 讓你同時編輯就可以編譯程式. Emacs 會要求你輸入實際的編譯命令, 預設值為 make -k, 也就是說與程式相同的目錄中必須有一個 makefile (參考 使用make 自動編譯). 假設你接受預設值, 就輸入 Enter ; 否則修改這個預設值在按下 Enter. 在進行編譯時, Emacs 會進行下列步驟 : 
* 檢查是否有任何尚未儲存的檔案 ; 如果有便詢問你是否要儲存.
* 將螢幕分成兩個緩衝區 ; 第二個緩衝區顯示編譯結果.
* 執行編譯命令.

底下是使用編譯命令 g++ source.c 後的結果 : 
 

假設我們將 main() 函數中的 "key" 變數改為 "_key", 此時會編譯失敗, 並且你可以在編譯視窗檢視錯誤訊息. 如果你要跳到編譯失敗代碼, 可以使用 C-x ` (C-x 加上倒單引號). 這會讓 Emacs 分析編譯緩衝視窗的內容, 找出第一個錯誤訊息, 然後將游標定位在錯誤的位置上 : 
 

Shell 視窗 : 
你可以透過 ESC x 並鍵入 "shell" 命令, 在 Emacs 編輯視窗中執行 UNIX 的 shell 命令 : 
 

使用 Shell 視窗最大問題在於一般的鍵盤輸入慣例變得無效. 舉例來說, 你不能用 C-c 終止程式執行 ; C-z 也不能暫停程式 ; Emacs 會把這些按鍵視為它的命令. 要克服這個問題, shell 模式分出一個以C-c 為開頭的命令集, 你可以在 Shell 下慣用命令前加上 C-c : C-c C-c 為中止程式 ; C-c C-z 為暫停程式等. 

Shell 模式根據 cd, pushd 及 popd 來更改你預設的目錄 (當你開啟新檔時, 預設目錄會出現在下方提示區中.). 所以你可以切換不同目錄來編輯在該目錄下的檔案. 底下是 shell 模式下命令的摘要說明 :
 

標籤 (Tag) : 
Emacs 的 "標籤" 功能與 vi 內建的 "標籤" 功能相當類似. 它提供一種方式簡化原始程式的導覽. 標籤功能以 "標籤" 資料庫為基礎, 它是由名為 TAGS 的單一檔案所組成的資料庫. 檔案中列出函式名稱, (非必要) 型別定義 (typedef) 及它們出現在原始檔案中的位置. 命令 etags 會建立這個資料庫, 在 shell 中如下執行 : 
% etags -t list of source files

其中 'list of source files' 是 : 你想要在資料庫中建立索引的檔案. -t 選項是告訴命令要包含型別定義. 所以在原始檔案的目錄建立 TAGS 檔案, 必須下這樣的命令 : 
$ etags *.[ch]
$ ls
TAGS ...

一旦你建立標籤表格, 你就可以透過 Emacs 的 ESC . 命令來進行導覽 ; 下方提示緩衝區會出現提示問你要找的標籤為何 : 
 

輸入你想要的函式名稱後按下 Enter, 如果存在, Emacs 會將游標移到函式的第一列. 如果你是第一次使用這個功能, 它會提示你輸入 TAGS 的檔名, 如果是預設 "TAGS" 就直接 Enter. 以上面範例 Emacs 會跳到函式 "_binarySearch" 的開頭 : 
 

補充說明 : 
Emacs C mode 指令速查表 
Emacs 快速入門教學

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!