將Emacs打造為C++ IDE 第二趴(譯)

Table of Contents

  1. 將Emacs打造為C++ IDE 第二趴
    1. 更快的啟動速度 - The Emacs Server and Client
    2. Ivy 和 Swiper
    3. 通過Tags在代碼庫中導航
    4. 使用ClangFromat優(yōu)化代碼格式
    5. C++ 11及以上 的語法高亮
    6. YouCompleteMe - 快速代碼補全
    7. YouCompleteMe 提示
    8. Git 源代碼管理
    9. 快速啟動
    10. 我的配置文件/安裝

翻譯自https://nilsdeppe.com/posts/emacs-c++-ide2

<a id="org495a654"></a>

將Emacs打造為C++ IDE 第二趴

2017-12-27 Nils

2018-02-10 更新

一年前,我寫了一篇關(guān)于將Emacs作為C++ IDE的博客。過去一年中,許多小的改進使我得到一份完全不同的配置,一份更快,并且更加好用的配置。
在這篇博客中,我將會展示我正在使用的功能的截圖,并在最后提供我的整個配置(init)文件。配置文件中含有詳盡的注釋來說明發(fā)生了什么。
如果仍有不明白的,留下你的評論,我將會盡力解釋清楚。

變化預覽:

首先我簡要列出變化的大綱和原因:

  • 使用Emacs server-client: 打開emacsclient比打開Emacs更快
  • 更省電: RTags 相較于它提供的功能,它所使用的cpu過多
  • 更好的tags導航:再次,RTags使用了太多的cpu(在筆記本上真的很糟糕),而且對于擁有超過100,000行C++的大型項目也無法很好的擴展。
  • cmake-ide很笨拙: 就是這樣。它需要為每一個大型項目進行大量的配置,并且過分依賴于RTags。
  • 自動補全使用company-mode和semantic,irony。此外rtags真的慢,特別是針對大型項目
  • Ivy 原來是一個更快,更輕量級的Helm替代品,可以很好的滿足我的需求。

我繼續(xù)研究替代配置的最大原因是RTag太過CPU密集了。如果我允許的話,它將耗盡8個超線程,并且每次我在低級頭文件中更改某些內(nèi)容時,
它將重新解析整個項目。 這種操作在筆記本電腦上代價太高昂了。 如果你有一個功能強大的桌面并且不關(guān)心電池續(xù)航時間可能沒問題,但是當
你在旅途中時,這種配置就不太現(xiàn)實了。

<a id="org067ff74"></a>

更快的啟動速度 - The Emacs Server and Client

隨著Emacs配置復雜性增加,可能令人討厭的一件事是啟動時間增加。有幾種方法可以解決這個問題。一個看起來很有希望但我還沒有嘗試的是[use-package] [se-package]。
基本的想法似乎是懶洋洋地加載軟件包,以便分散加載時間而不是一次性加載。

我選擇使用Emacs Server - Client方法。 這意味著我使用systemd在登錄時啟動Emacs一次,然后使用emacsclient連接到正在運行的會話。
我用來連接Emacs的別名是 alias ec=“emacsclient -c”
我的systemd文件位于 ~/.config/systemd/user/emacsd.service 中,內(nèi)容如下:

[Unit]
Description=Emacs: the extensible, self-documenting text editor
Documentation=man:emacs(1) info:Emacs

[Service]
Type=forking
ExecStart=/usr/bin/emacs --daemon
ExecStop=/usr/bin/emacsclient --eval "(progn (setq kill-emacs-hook nil) (kill-emacs))"
Restart=on-failure
Environment=DISPLAY=:%i
# Provide access to SSH
Environment=SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
# Setup modules
Environment=PATH="/home/nils/Research/mosh/install/bin/:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.1.1/catch-1.9.4-qgdxfjhwk4mqhelhn2ggxmvyxvx6xm3k/bin:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/gsl-2.3-hsntrnj45jqjdmb6fq74tnxkmqxekts6/bin:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/openblas-0.2.19-if6giqoypphsmgle4anxox5kmb23g3vj/bin:/home/nils/Research/install/bin:/home/nils/.gem/ruby/2.4.0/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/home/nils/Research/spack/bin:/opt/intel/bin:/opt/intel/vtune_amplifier_xe_2017.2.0.499904/bin64:/home/nils/Research/llvm/build/bin:/home/nils/Research/templight-tools/build/bin:/home/nils/Research/standardese/build/tool:$PATH"
Environment=CPATH="/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/brigand-master-pcaoburzhlfibhh4mvmcia2e6dkbry5x/include:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.2.0/kvasir-mpl-develop-hr2lgqezjkiif3vbjsoxccorj2f5wppm/include:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.1.1/catch-1.9.4-qgdxfjhwk4mqhelhn2ggxmvyxvx6xm3k/include:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/yaml-cpp-master-gmc3k4n2vsvmqwjcyqrxwaz2h5fukxc2/include:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/gsl-2.3-hsntrnj45jqjdmb6fq74tnxkmqxekts6/include:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/openblas-0.2.19-if6giqoypphsmgle4anxox5kmb23g3vj/include:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/libxsmm-1.8.1-mevsuzxzo47g33rihi4t7fdohp3ga7gk/include:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.2.0/blaze-3.2-mnkglifq5s6ib5ltbvil4xt66fekqq2l/include:/home/nils/Research/install/include::/opt/petsc/linux-c-opt/include:$CPATH"
Environment=LD_LIBRARY_PATH="/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/yaml-cpp-master-gmc3k4n2vsvmqwjcyqrxwaz2h5fukxc2/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/gsl-2.3-hsntrnj45jqjdmb6fq74tnxkmqxekts6/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/openblas-0.2.19-if6giqoypphsmgle4anxox5kmb23g3vj/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/libxsmm-1.8.1-mevsuzxzo47g33rihi4t7fdohp3ga7gk/lib:/home/nils/Research/install/lib:::/opt/petsc/linux-c-opt/lib:$LD_LIBRARY_PATH"
Environment=LIBRARY_PATH="/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/yaml-cpp-master-gmc3k4n2vsvmqwjcyqrxwaz2h5fukxc2/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/gsl-2.3-hsntrnj45jqjdmb6fq74tnxkmqxekts6/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/openblas-0.2.19-if6giqoypphsmgle4anxox5kmb23g3vj/lib:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/libxsmm-1.8.1-mevsuzxzo47g33rihi4t7fdohp3ga7gk/lib:/opt/petsc/linux-c-opt/lib:$LIBRARY_PATH"
Environment=CMAKE_PREFIX_PATH="/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/brigand-master-pcaoburzhlfibhh4mvmcia2e6dkbry5x:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.2.0/kvasir-mpl-develop-hr2lgqezjkiif3vbjsoxccorj2f5wppm:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.1.1/catch-1.9.4-qgdxfjhwk4mqhelhn2ggxmvyxvx6xm3k:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/yaml-cpp-master-gmc3k4n2vsvmqwjcyqrxwaz2h5fukxc2:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/gsl-2.3-hsntrnj45jqjdmb6fq74tnxkmqxekts6:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/openblas-0.2.19-if6giqoypphsmgle4anxox5kmb23g3vj:/home/nils/Research/spack/opt/spack/linux-antergos17-x86_64/gcc-6.3.1/libxsmm-1.8.1-mevsuzxzo47g33rihi4t7fdohp3ga7gk:/home/nils/Research/spack/opt/spack/linux-antergosrolling-x86_64/gcc-7.2.0/blaze-3.2-mnkglifq5s6ib5ltbvil4xt66fekqq2l"
TimeoutStartSec=0

[Install]
WantedBy=default.target

最重要的部分是 Environment=SSH_AUTH_SOCK 這行。 這確保你可以從Emacs會話中訪問你的SSH代理。 如果沒有此行,你每次使用時都需要重新輸入SSH密鑰的密碼。
第14-18行是我工作中所需要使用的各種環(huán)境變量。
你可以創(chuàng)建文件執(zhí)行 systemctl --user enable emacsd.service && systemctl --user start emacsd.service 來啟動后臺運行的Emacs進程,并將其設(shè)置為在登錄時啟動。
可以使用 systemctl --user restart emacsd.service 重新啟動Emacs守護程序。

<a id="orgb01775a"></a>

Ivy 和 Swiper

我已經(jīng)轉(zhuǎn)而使用Ivy進行模糊匹配而不是Helm。IvyHelm小很多,因為它只是其他軟件包的底層補全引擎。 需要注意的重要一點是,
我還使用ripgrep進行更快速的搜索。 如果你沒有或無法安裝ripgrep,那么只需從我的init文件中刪除任何引用ripgrep或rg的行。
在下面的截屏視頻中,我展示了在打開文件時以及使用project-find-file時使用Ivy的模糊匹配。
為了易于使用,我已將 C-x M-f 映射到project-find-file。因此我沒有必要使用projectile。

另一個基于Ivy構(gòu)建的有用插件是swiper,它取代了Emacs中的標準搜索。swiper不是必須手動在文件中跳轉(zhuǎn),而是在擴展的minibuffer(迷你緩沖區(qū))中顯示所有匹配項。
這意味著正向和反向搜索實際上是相同的,并且兩者都可以重新映射到swiper。

<a id="orgf979a77"></a>

通過Tags在代碼庫中導航

RTags類似的有CTags和]GTags。它們允許你在代碼庫中快速的跳轉(zhuǎn)到類或者函數(shù)的定義。例如,假設(shè)我想查看我正在查看的代碼中使用的函數(shù)的定義,我可以按 M-. 跳轉(zhuǎn)到定義。
一旦我從函數(shù)定義中得到了我需要的信息,我可以按 M-, 跳轉(zhuǎn)回之前的位置。類似的 M-t 顯示Tags數(shù)據(jù)庫中所有的光標所在位置的單詞(the word-at-point).希望以上的用例
講清楚了如何使用tags。我想要的是一個解析快速,準確的tags實現(xiàn)。在嘗試了五個不同的方案后,我最終確定了Universal-CTags作為標簽數(shù)據(jù)庫的生成器。第一步是在你的系統(tǒng)中
安裝Universal-CTags.你應該通過運行 ctags --version 來驗證是否安裝了Universal-CTag而不是其他實現(xiàn)。

在Emacs中的Tags導航,我使用的是counsel-etags.盡管它還很年輕,但效果非常好。我的配置會在每次保存文件時或距離上次構(gòu)建Tags數(shù)據(jù)庫已經(jīng)3分鐘了就會觸發(fā)Tags數(shù)據(jù)庫的重建,
這可以確??梢詫Ш降叫碌念惢蚝瘮?shù)上。請注意,在撰寫本文時,我使用能夠在文件名和目錄名中使用通配符的函數(shù)覆蓋了默認提供的自動更新函數(shù)。默認情況下,只有文件名支持通配符。
下面是源代碼導航的演示。

<a id="orgff64883"></a>

使用ClangFromat優(yōu)化代碼格式

如果你不使用ClangFormat,你應該認真考慮它。 這是我簡單的Emacs配置:

;; clang-format can be triggered using C-c C-f
;; Create clang-format file using google style
;; clang-format -style=google -dump-config > .clang-format
(require 'clang-format)
(global-set-key (kbd "C-c C-f") 'clang-format-region)

<a id="orgf42ec64"></a>

C++ 11及以上 的語法高亮

內(nèi)置的語法高亮顯示在現(xiàn)代C++方面做得不是很好。
幸運的是有一個補救措施:modern-cpp-font-lock。 配置使用:

(require 'modern-cpp-font-lock)
(modern-c++-font-lock-global-mode t)

<a id="orgef98bac"></a>

YouCompleteMe - 快速代碼補全

代碼補全最重要的兩個部分是速度和準確性。如果其中任何一個不達標,則代碼補全對經(jīng)驗豐富的開發(fā)人員來說沒有用。對我來說重要的第三個標準是代碼補全引擎使用的CPU資源少于
編譯代碼所需的CPU資源,否則我可能只使用編譯器給我的建議。我還希望能夠在旅行時使用代碼補全,CPU使用率低意味著更長的電池續(xù)航時間。我找到的最佳解決方案是
帶有emacs-ycmdYouCompleteMeDaemon。ycmd使用libclang來查找和補全,因此即使對于大型項目也是如此準確和快速。此外,它只解析你當前打開的文件,這與一些重新
解析整個項目的完成框架不同。

首先你必須安裝ycmd 服務,這里有相關(guān)的說明。接下來在Emacs中安裝emacs-ycmd軟件包,該軟件包hook到companyflycheck,以提供補全和動態(tài)語法檢查。在下面的截屏視頻中,
我展示了使用代碼補全和語法檢查功能將容器的大小輸出到標準輸出。minibuffer末尾出現(xiàn)的錯誤消息告訴我們<iostream>標頭未包含在內(nèi)。

在我的init文件中,我將ycmd,company和flycheck的設(shè)置分為三個不同的部分,以便將來更容易維護。 有了ycmd,company和flycheck,我的CPU在大多數(shù)時間都處于空閑狀態(tài),
因此我可以獲得非常快速且非常準確的補全,因此我也獲得了很長的電池壽命。 最后,任務完成了!

<a id="org3e3c240"></a>

YouCompleteMe 提示

在一個相當復雜的C ++ 14項目中我使用YCMD,它使用了許多新的語言特性,并且有很多類和函數(shù)模板。為了獲得非常好的代碼補全,我為YCMD開發(fā)了一個python腳本,
它非常積極地找到頭文件的編譯標志。 這樣的腳本是必要的原因是因為compilecommands.json文件不包含頭文件的任何編譯標志,因為它們沒有被編譯。
我在這里分享了腳本作為一個要點。 該腳本必須放在~/ .ycmextraconf.py中,以便Emacs配置查找并使用它。 如果你不想使用該腳本,請在配置中刪除這行

另一件需要注意的事情是,讓YCMD,或者更具體地說是libclang,與預編譯頭文件很好地協(xié)同工作需要一些工作。 有關(guān)詳細信息,請參閱YCMD GitHub上的此問題。
簡短的說法是,如果使用預編譯的頭文件,則可能需要使用系統(tǒng)libclang構(gòu)建YCMD,方法是將–system-libclang傳遞給構(gòu)建腳本。

<a id="orge2f720e"></a>

Git 源代碼管理

我還使用magit在Emacs中執(zhí)行我的所有g(shù)it操作,并使用git-gutter向我顯示我在當前文件中更改了哪些行。 Magit功能非常豐富,我強烈建議你閱讀冗長的文檔。
通過不再輸入長git命令,你將很快節(jié)省你的投資時間。 magit網(wǎng)站上還有截屏視頻,所以我不會在這里顯示任何內(nèi)容。

<a id="org6e44cf0"></a>

快速啟動

注意:此部分是在2018年2月10日添加的。配置的功能不會更改,但加載速度更快。

我沒有做太多的python開發(fā),我特別試圖避免使用筆記本,但有時我別無選擇。我發(fā)現(xiàn)Web瀏覽器是一個糟糕的開發(fā)環(huán)境,所以我開始使用EIN來編輯Jupyter筆記本。
這使得該過程更加可以容忍。 不幸的是,啟動Emacs時啟動Jupyter服務器需要大約2.5秒,這很長一段時間。 我在我的開發(fā)機器上使用Emacs服務器,但是當我在
超級計算機上工作時,我通常不會,或者在我登錄時仍然必須加載它。我決定做一些研究并使用use-package來加速加載時間。
結(jié)果是我的Emacs啟動時間從~4.7s下降到約0.6s而不會丟失功能。 雖然我喜歡它是0.1秒,0.6秒使啟動時間非常容易。
除了我在Gist中分享了我最近版本的~/ .emacs.el文件之外,我不會再說這些了。

<a id="orgf14c7c1"></a>

我的配置文件/安裝

我在這里將我的init文件在Gist上共享。 要完全替換當前配置,你需要做的就是安裝ycmd并更改安裝ycmd的路徑(在.emacs.el文件中搜索/ home / nils / Research / ycmd)。
要確保Emacs加載新的init文件,請確保沒有/.emacs或/.emacs.d/init.el文件。 啟動Emacs時確保你有Internet連接,因為它會自動為你下載并安裝任何丟失或過時的軟件包。
如果一切正確,你不應在* Messages , warnings ycmd-server * buffer中收到任何錯誤或警告。

我現(xiàn)在將指導一步一步來安裝我的配置。

前期準備條件:

Emacs 24.5或更新的版本
YCMD及其要求(例如glibc 2.14或更新版本)
ripgrep(可選,如果沒有,請從init中刪除與ripgrep有關(guān)的行)
安裝:

復制~/.emacs~/.emacs.el,以及~/.emacs.d
刪除~/.emacs,~/.emacs.el~/.emacs.d/init.el,無論你使用哪個
Gist復制到~/.emacs.el。
啟動Emacs。如果Emacs沒有立即開始安裝軟件包,請按M-x并運行l(wèi)ist-packages,然后關(guān)閉并再次啟動Emacs。
如果任何軟件包無法自動安裝,請按M-x并運行l(wèi)ist-packages手動安裝它們,但大多數(shù)軟件包將自動安裝。
編輯~/.emacs.el將/home/nils/Research/ycmd/ycmd替換為你選擇安裝ycmd并重新啟動Emacs的路徑。
ycmd Gist復制到~/.ycmextraconf.py
注意:在我安裝此配置的一臺機器上,我必須注釋掉(require 'yasnippet)部分,啟動Emacs并讓所有內(nèi)容安裝,然后取消注釋該部分并重新啟動Emacs。

摘要
在這篇文章中,我簡要概述了我對Emacs配置所做的主要更改。我已經(jīng)花了相當多的精力來清理和組織我的Emacs init文件,所以希望在這里分享它足以讓你入門。
如果沒有,請對你想要我解釋的內(nèi)容發(fā)表評論,我將更新此帖子并提供更多信息。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容