Emacs 入坑引導 - 打造自己的 Ruby IDE - Part 2

Emacs 入坑引導 - 打造自己的 Ruby IDE - Part 2

前言

我在 Part 1 簡單介紹了 Emacs 入門的基礎知識,包括基本按鍵操作、套件安裝及視窗管理等,熟練 Emacs 需要長期使用經驗的累積,大腦才會慢慢適應,Coding 的速度才會跟上思考。在 Part 2 我將繼續介紹如何透過設定 Emacs 來打造自己的 Ruby IDE 。

何謂 IDE ?

IDE 中文名為「整合開發環境」(Integrated Development Environment),一個單純的 Editor 如 Nano 等簡單的文字編輯器是無法被稱為 IDE 的,IDE 必須包含各種開發專案需要的工具,從 Code editing 、 Debugging 、 Compiling 、 Executing 等等,好的 IDE 還可以包含 Syntax highlighting 、 Code search 、 Refactoring 、 Auto formatting 、 Version control 、 Project management 、 Terminal 等。比較熱門的 IDE 有 Microsoft Visual Studio 、 Eclipse 、 NetBeans 等,每個 IDE 都有針對不同程式語言與框架的專案開發支援,如 Microsoft Visual Studio 支援 .Net Framework 的開發,Eclipse 則最主要用來開發 Java 。

Ruby IDE

若要開發 Ruby 或 Ruby on Rails 的話有現成的 IDE 嗎?答案是有,而且很多。例如 Ruby Mine 是 JetBrains 做的 Ruby IDE ,功能相當豐富,在 Ruby 圈也相當知名,可以幫你重構、跑測試、除錯、找定義等,還有漂亮的 UI ,當然還有一個特點就是「貴」。其他如 Eclipse 、 NetBeans 也都可以用來開發 Ruby ,但對我這種不用滑鼠黨的黨工實在無法用這些畫面上到處是 Button 的 IDE 。

那身為菜鳥 Rubyist 該從哪款 IDE 下手呢? AWS Cloud9 也許是個不錯的選擇。也許你會問明明有這麼多老少咸宜的 IDE 了,為什麼還要特地用 Emacs 呢?如果你是追求漂亮 UI 或喜歡用滑鼠 Coding 的菜鳥工程師的話,你可以選擇繼續留在舒適圈,使用別人幫你設定好的工具,專心學習 Coding 。如果你已經是個算是有點成熟的工程師了,就應該嘗試看看捨棄滑鼠、脫離漂亮 UI 的束縛,追求更高的開發效率,為自己打造一個量身訂做的 IDE ,讓自己更有 Style 、更 Special 一點。

第一步

雖然我在 Part 1 提到了一些初始設定,但我們還是重新來一遍吧!

建立設定檔

為了方便我們採用 .emacs 單一檔案的方式來管理設定,到 $HOME 目錄底下建立檔案:

$ cd ~
$ emacs .emacs

初始設定

讓我們將煩人的 Welcome 畫面取消,在 ~/.emacs 裡面加入:

(setq inhibit-startup-message t)

Emacs 預設開啟的 *scratch* Buffer 內會有一些預設的訊息在上面,同樣也可以把它取消掉,讓這個 Scratch 乾淨點:

(setq initial-scratch-message nil)

在視窗上面的選單也好煩,旁邊的捲軸也是,通通都可以把它給關掉:

(menu-bar-mode -1)
(toggle-scroll-bar -1)
(tool-bar-mode -1)

這樣畫面乾淨多了。

備份檔

Emacs 有一個非常佛心的功能,就是隨時會幫你備份正在編輯的檔案,當你的 Emacs 不小心因為某些事故被強制關閉了,就算檔案還沒儲存也不用擔心,Emacs 會幫你還原回來。那這些備份檔是被存在什麼地方呢? Emacs 預設會在與你編輯的檔案同一個目錄底下建立這些備份檔,而且還分為很多種。

例如當我新開一個檔案 hello.rb ,輸入一些字並儲存,切個 Buffer 再切回來,然後在輸入一些字但不儲存,之後到 Terminal 強制把 Emacs 關掉,這時候檢查目錄會像這樣:

drwxr-xr-x  2 mike mike 4096 Oct 19 20:19  ./
drwxr-xr-x 11 mike mike 4096 Oct 19 20:10  ../
-rw-r--r--  1 mike mike   20 Oct 19 20:18 '#hello.rb#'
-rw-r--r--  1 mike mike   19 Oct 19 20:17  hello.rb
-rw-r--r--  1 mike mike   14 Oct 19 20:11  hello.rb~

Emacs 幫你額外生了兩個備份檔,而且還不幫你刪掉,這會讓我們的專案目錄底下多出一堆垃圾,幸好可以透過設定將這些備份檔的產生位置移動到其他地方,在 ~/.emacs 中加入:

(setq create-lockfiles nil)
(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

接著重開 Emacs 後在試試同樣的步驟,檢查目錄就會發現 Emacs 已經不會自動幫你將備份檔生在跟正在編輯的檔案同一個目錄底下了,真是可喜可賀。

套件

在 Part 1 我提到過 Emacs 有自己的套件管理工具,我們可以懷著感恩的心透過它來使用許多高手大大們花費大量心力貢獻的套件。

MELPA

首先將 MELPA 這個 repository 加入到我們的 Emacs 中:

打開 ~/.emacs 將以下 Code 貼上:

(require 'package)
(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
                    (not (gnutls-available-p))))
       (proto (if no-ssl "http" "https")))
  ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired
  (add-to-list 'package-archives (cons"melpa"(concat proto"://melpa.org/packages/")) t)
  ;;(add-to-list 'package-archives (cons"melpa-stable"(concat proto"://stable.melpa.org/packages/")) t)
  (when (< emacs-major-version 24)
    ;; For important compatibility libraries like cl-lib
    (add-to-list 'package-archives'("gnu" . (concat proto "://elpa.gnu.org/packages/")))))
(package-initialize)

接著重開 Emacs 並輸入指令:

<M-x> package-list-packages

稍微等個幾秒鐘,看看套件的來源是否有 melpa ,這樣就成功了。

Ruby Mode

ruby-mode 是 Emacs 內建的套件之一,這個套件提供最基本的編輯 Ruby Code 的支援,當我們在編輯副檔名為 .rb 的檔案時,Emacs 就會自動將主 Mode 設為 Ruby ,讓我們隨便打開一個 Ruby 檔案試試:

<C-x> <C-f> hello.rb

最基本的語法高亮、自動縮排等都已經預設支援了。但光是這個 ruby-mode 也只能讓 Emacs 看起來是個普通的 Editor ,讓我們來安裝其他套件,慢慢將不足的部份補齊吧!

界面樣式

我想讀者們已經忍受不了 Emacs 醜醜的界面了,Emacs 預設提供了幾種主題給你選,但是一樣都很醜,讓我們來透過套件來安裝一些比較潮的吧!

Dracula Theme

Dracula 是一個相當熱門的主題樣式,它支援各種知名的 Editor ,甚至連 Terminal 也支援,事不宜遲馬上來裝裝看!

<M-x> package-install dracula-theme

接著在 ~/.emacs 內加入:

(load-theme 'dracula t)

重開 Emacs ,畫面就會稍微變漂亮一點囉!

字型

大部分的了對於寫 Code 的視覺上影響最大的就是字型了, Emacs 當然也可以設定自己想要的字型與大小,首先選擇一個自己喜歡的 Font ,例如我喜歡 Input 這個字型,把它裝到電腦上後,在 ~/.emacs 中加入:

(set-face-attribute 'default nil
                    :family "Input Mono"
                    :height 150
                    :weight 'normal
                    :width 'condensed)

這麼一來 Emacs 看起來就更現代化了。字的大小設定會依照每種不同的字型而有所不同,而如果要在 Coding 的時候即時挑整大小的話,可以透過 <C-x> -<C-x> + 來調整縮小和放大。

游標

Emacs 預設的游標類型是粗粗的方塊,但現代一點的 Editor 大多都是細細的棒子,如果不習慣的話同樣可以來設定:

(setq-default cursor-type 'bar)

這樣有沒有好多了?

整理設定檔

目前我們的 .emacs 大概長這樣:

(require 'package)
(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
                    (not (gnutls-available-p))))
       (proto (if no-ssl "http" "https")))
  ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired
  (add-to-list 'package-archives (cons"melpa"(concat proto"://melpa.org/packages/")) t)
  ;;(add-to-list 'package-archives (cons"melpa-stable"(concat proto"://stable.melpa.org/packages/")) t)
  (when (< emacs-major-version 24)
    ;; For important compatibility libraries like cl-lib
    (add-to-list 'package-archives'("gnu" . (concat proto "://elpa.gnu.org/packages/")))))
(package-initialize)

;; hello

(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages (quote (dracula-theme))))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )

;; Settings

(setq inhibit-startup-message t)
(setq initial-scratch-message nil)
(menu-bar-mode -1)
(toggle-scroll-bar -1)
(tool-bar-mode -1)

(setq create-lockfiles nil)
(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))


(load-theme 'dracula t)

(set-face-attribute 'default nil
                    :family "Input Mono"
                    :height 150
                    :weight 'normal
                    :width 'condensed)

(setq-default cursor-type 'bar)

自動補齊

在 Part 1 我們提到 companyivycounselswiper 這幾個強大的套件,先把它裝起來:

<M-x> package-install company
<M-x> package-install ivy
<M-x> package-install swiper
<M-x> package-install counsel

接著在 ~/.emacs 中加入:

(global-company-mode)
(ivy-mode 1)

Company Mode

company-mode 是個強大的文字自動補齊套件,與大部分現代 Editor 差不多,只要輸入一些幾個字就會幫你開出候補字選單,如下圖所示。

當選單出現後可以透過 <M-p><M-n> 來做上下選擇移動,之後按下 <C-m> 也就是 Enter 鍵決定,在最純 company-mode 的模式下通常會自動幫你搜尋你的 Buffer 之中曾經出現過的字來做候補,如果要進階一點如自動顯示 Function、Method 等等對於語言的支援的話可以在額外安裝針對特定語言的 company 套件,例如今天我想開發 Erlang ,就可以安裝 company-erlang 這個套件, Ruby 的話也有相關套件,會在之後提到。

Ivy

ivy 也是個自動補齊套件,應該說是一個框架,與 company-mode 不同的是, ivy 可以幫你為除了 Coding 之外如指令方面的輸入做自動補齊,我們可以試著按下 <M-x> 輸入指令看看,由於 ivy-mode 在 Emacs 有了出現在底下的選單,透過這個選單可以選擇候補指令、檔案等等的選擇,在輸入的同時還可只輸入片段的關鍵字,例如輸入 <M-x> fin fiivy 就會幫你過濾出包含 fin fi 的所有指令。

搜尋

上面提到 ivy 可以幫你做到指令、檔案搜尋時的自動補齊,但最重要的是它提供了一個可以展開的置底界面,它也可以用來顯示搜尋的結果。

Counsel

counsel 是依賴 ivy 這個框架的套件,提供了許多 ivy 本身不包含的強大功能,可以用它來做整個專案的檔案及文字的搜尋等等。無論今天在使用什麼 Editor 或 IDE , 專案內的全域搜尋都跟專案的開發效率有著極大的影響,可以說是在專案開發時最常用到的功能之一,因此相當重要。

The Silver Searcher (ag)

在開始使用 counsel 之前必須先安裝 the silver searcher 又稱 ag 的這個東西, ag 是個類似 ackgrep 的指令,可以幫你做某個檔案或目錄下的文字搜尋,但 ag 的速度更快,與 git 的支援也比較好,因此也被許多 Editor 整合進去。

詳細安裝方式請參考 the silver searcher 的 GitHub 頁面。

專案內檔案搜尋

要對整個專案進行搜尋必須使用 counsel-projectile 這個 counsel 的擴充套件,先把它裝上:

<M-x> package-install counsel-projectile

確保 ivy-modeenabled 的狀態,比較目前 Buffer 是在 Git 專案目錄底下,我們可以試著建立一個 Rails 專案來試試。

$ rails new hello
$ cd hello
$ emacs Gemfile

接著透過 counsel-projectile-find-file 這個指令來迅速地搜尋並打開 config/routes.rb 這個檔案,順便練習一下 ivy 的關鍵字搜尋。

<M-x> co pro fi fi <C-m>
[hello] Find file: rou <C-m>

很神奇地就這樣把 config/routes.rb 給開起來了!

趕快來把 counsel-projectile-find-file 設個 Shortcut ,打開 ~/.emacs 加入:

(global-set-key (kbd "C-c f") 'counsel-projectile-find-file)

如此一來就可以很方便又快速地來開啟檔案囉!完全不需要打開一層又一層的目錄,在搭配強大的 ivy 支援的 Buffer 切換,不需要大多數 Editor 或 IDE 提供的側邊目錄樹或上面的 Tab bar 就可以在檔案之間來去自如了。

專案內文字搜尋

那我想要在整個專案裡面搜尋某幾個字呢?這時候就需要強大的 ag 支援了。counsel-projectile-ag 這個指令就能夠很神奇地即時幫你搜尋整個專案內的所有文字,而且會幫你略過在 .gitignore 清單內的檔案。例如我想要搜尋 Hello 這個 Module 是在哪裡定義的:

<M-x> cou pro ag <C-m>
[hello] ag: mod hel <C-m>

哇!我的游標竟然 module Hello 的位置了!甚至我想搜尋 hello 這幾個字在專案裡面出現在哪些地方, counsel 也會即時地把所有結果列出來,透過 <C-p><C-n> 來上下選擇,瞬間就幫你開到指定的檔案的特定行數去,簡直太神奇了!

一樣趕快把它設個 Shortcut 。

(global-set-key (kbd "C-c s") 'counsel-projectile-ag)

要記得如果想要不分大小寫搜尋,就通通輸入小寫,一旦中間出現大寫字的話就會被認為要分大小寫搜尋。輸入空白鍵則表示零或多個任何文字,也可以利用正規表示法來尋找某個 Pattern 。

Buffer 內文字搜尋

Emacs 預設就有 search-forwardsearch-backward 這兩個指令讓你做文字搜尋了,但這樣還是有點不方便,這時就可以利用 swiper 這東西來加強整個 Buffer 內的文字搜尋。

直接透過指令 swiper 就可以看到利用 ivy 展開的選單,之後可以輸入要搜尋的文字,搜尋結果就會被詳細地列出來了,同樣可以透過上下鍵來進行選擇,並讓游標跟著移動。

例如我想要在 Gemfile 檔案內列出所有的 Gem 。

<M-x> swiper <C-m>
Swiper: gem

這樣比起原生的內建搜尋還要更加視覺化,操作也更加方便。

小結

以上我們將使用 Emacs 進行開發必不可少的重要插件一一做了個介紹,當然實際的使用還是得參考每個插件的文件去了解,並經常使用來熟悉。本章篇幅較短,但一次提及太多恐怕無法消化,最重要的還是要多加練習。配合上述所提到的工具基本上已經能夠進行大部分的開發工作了,但身爲一個 IDE 恐怕還不夠格,因此我會在 Part 3 進一步地將開發 Ruby 以及 Rails 所需的相關插件以及在 Emacs 的 Git 操作等做進一步的詳細介紹,讓我們的 Emacs 真正躍升爲一個名副其實的 Ruby IDE。