這篇文章本來是『走近 Emacs』的內容,當時由於考慮到 Emacs 的用戶未必寫 C/C++ 代碼,因此就將它隔離了出來。前端
當你用 Emacs 打開或新建一份擴展名爲 .c
的文件時,Emacs 會自動開啓內置的 C 模式。這個模式提供了語法高亮、自動縮進等基本功能。同時 Emacs 也容許用戶深度定製符合本身使用習慣的代碼編輯功能,前提是你須要對 Emacs Lisp 擴展語言有必定了解。linux
若是你不熟悉也不打算學習 Emacs Lisp 語言,那就只能將他人寫好的配置代碼扔到 $HOME/.emacs
或 $HOME/.emacs.d/init.el
文件中。如今推薦使用後者做爲 Emacs 的配置文件。c++
不少年前我從一個我忘記了他的網絡 ID 的傢伙那裏抄來一段 C 代碼的配置:程序員
;;;; c mode ;;;; (defvar xgp-cfsi-left-PAREN-old nil "Command used to input \"(\"") (make-variable-buffer-local 'xgp-cfsi-left-PAREN-old) (defun xgp-cfsi-modify-alist (alist term new) (let ((tl (assq term (symbol-value alist)))) (if tl (setcdr tl new) (add-to-list alist (cons term new))))) (defun xgp-cfsi (style) "Deciding whether using CFSI." (interactive "Style: ") (c-set-style style) (setq indent-tabs-mode nil c-hanging-semi&comma-criteria (quote (c-semi&comma-inside-parenlist))) (xgp-cfsi-modify-alist 'c-hanging-braces-alist 'class-open nil) (xgp-cfsi-modify-alist 'c-hanging-braces-alist 'class-close nil) (local-set-key " " 'self-insert-command)) (defun xgp-cfsi-erase-blanks () "Erase all trivial blanks for CFSI." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "[ \t]+$" nil t) (replace-match "" nil nil)))) (defun linux-c-mode() (define-key c-mode-map [return] 'newline-and-indent) (setq imenu-sort-function 'imenu--sort-by-name) (interactive) (imenu-add-menubar-index) (which-function-mode) (c-toggle-auto-state) (c-toggle-hungry-state) (setq indent-tabs-mode nil) (xgp-cfsi "linux")) (add-hook 'c-mode-common-hook 'linux-c-mode)
這樣配置以後,C/C++ 代碼編輯功能會強大一些。例如,敲擊 Backspace 鍵能夠連續刪除多行空行;在代碼行尾鍵入 ; 會自動換行;代碼縮進長度變爲 8 個空白字符……這些配置,我用了不少年,到如今也不知道它具體都作了些什麼。正則表達式
C++ 的代碼,由於我平時寫的不太多,因此沒做配置。不過上述的 C 模式配置的這些功能,也適合 C++ 代碼的編輯。segmentfault
你如今所用的 Emacs 版本應該是 >= 24,若是不是,想辦法升級吧。不然本節內容不太適合你閱讀,除非你懂得如何手動安裝 Emacs 擴展包。bash
若是用過 Visual C++.net 或者 Eclipse,想必會對它們的代碼編輯器提供的代碼自動提示功能念念不忘,於是抱怨 Emacs 的 C 模式未提供此功能。事實上是有的,可是要實現 C/C++ 代碼的自動提示,這須要 Emacs 懂得如何去解析 C/C++ 代碼,似這類繁重又專業的任務讓一個文本編輯器來作,不合常理,更況且 Emacs 並不是 C/C++ 程序員的專用編輯器。網絡
Emacs 可以作到的事情必需要與文本編輯直接相關,可是它有能力藉助其餘工具彌補自身不足。像 C/C++ 代碼分析這樣的任務,交給一個專業的 C/C++ 編譯器最好不過了。雖然藉助咱們所熟悉的 gcc 是可行的,但它不如另外一款編譯前端 clang 好用,由於後者在設計時就考慮到了與代碼編輯器的整合。編輯器
咱們所要作的首先是想辦法安裝 clang。Gentoo Linux 用戶只需:ide
$ sudo emerge -avt clang
而後先去幹別的事吧,clang 畢竟是 C++ 寫的 C/C++ 編譯器,是個挺大的項目,編譯耗時會挺長,長的我都忘記了到底須要多久,彷佛比編譯 libreoffice 或者 firefox 快一些。
Emacs 自己是沒法與 clang 溝通的,可是 Emacs Lisp 能夠強大到容許 Emacs 用戶自行編寫擴展包以實現 Emacs 與 clang 的溝通。因而就有人寫出了 company 這個擴展包。
在 Emacs 24 以前的時代,要爲 Emacs 安裝擴展包,須要從網絡上下載擴展包,而後複製到 Emacs 所能搜索到的目錄,最後在 Emacs 配置文件中對擴展包進行配置。
從 Emacs 24 開始,Emacs 對擴展包進行統一管理,極大程度上簡化了擴展包的搜索與安裝過程。打開 Emacs,而後執行 M-x list-packages
,若是網速足夠快,應該很快就能看到 Emacs 官方提供的擴展包列表。
待軟件包列表出現後,執行 C-s M-r ^ +company
,回車便可讓光標跳到 company 擴展包信息所在的文本行,繼而敲擊 i
鍵(表示要安裝該擴展包),再敲擊 x
鍵(表示執行安裝過程),稍等片刻,Emacs 會自動從下載 company 擴展包並安裝至 $HOME/.emacs.d
目錄。
提示:
C-s
是開啓 Emacs 查找模式,M-r
是將查找模式切換爲正則表達式查找模式,而^ +companyy
是用於匹配『位於行首且由多個空格與company
字符串構成的字符串』的正則表達式。
若是之後要刪除 company 擴展,步驟與安裝步驟相似,只是將 i
鍵替換爲 d
鍵(表示刪除)。
company 安裝完畢後,在 Emacs 配置文件中作如下配置:
;; 代碼補全 (add-hook 'c-mode-hook 'company-mode) (add-hook 'c++-mode-hook 'company-mode)
這樣即可將 company 掛接到 Emacs C 模式上。這樣,每當 Emacs 打開 C/C++ 文件時company 模式便會被自動開啓。
下圖是 company 與clang 成功『溝通』後的結果:
因爲 clang 默認會去 Linux 標準目錄 /usr/include
中去搜索庫的頭文件,可是有些庫的頭文件是安裝在非標準位置的。例如 PCL 庫的頭文件,默認安裝在 usr/include/pcl-1.7
,若要對 PCL 庫函數進行自動補全,那麼就須要將這個路徑告訴 clang。eigen 庫也存在這個問題。解決方法是在項目源碼的頂層目錄下建立 .dir-locals.el
文件,內容相似於:
((nil . ((company-clang-arguments . ("-I/usr/include/pcl-1.7/" "-I/usr/include/eigen3/")))))
若是誰有更好的讓 clang 自動搜索庫的頭文件路徑的方法,還請不吝賜教。