大昔に取り組んでいた自作OS、せっかくなので再挑戦してみようと考えた.CLionとかそこらへんのIDEを使用しても良かったけれど,せっかくだからEmacs で C, C++ の環境を整えるたいので,メモしとく.
基本的にC/C++ Development Environment for Emacsに全部書いてあったのでつまんでみる.
helm+helm-gtags もしくは ggtags を使う.
自分は helm-gtags を使うことになるだろう.
1.GTAGS
プロジェクトのルートディレクトリで gtags コマンドを実行すると,以下のファイル群が生成されるはず.
1 2 3 4 | |
それぞれ以下の情報を保持している.
- GTAGS : 定義
- GRTAGS : 参照
- GPATH : パス名
2.基本操作
作業を快適にするために把握しておくべきEmacsにおける基本操作は以下
| コマンド | コマンド名 | 概要 |
|---|---|---|
| C-M-f | forward-sexp | 閉じカッコの前に行く |
| C-M-b | backward-sexp | 閉じカッコの後ろに行く |
| C-M-k | kill-sexp | 閉じカッコ内を削除する |
| C-M- |
mark-sexp | 閉じカッコ内を選択する |
| C-M-a | beginning-of-defun | 関数の前に行く |
| C-M-e | end-of-defun | 関数の後ろに行く |
| C-M-h | mark-defun | 関数を選択する |
3.定義参照
3.1.バッファ内参照
ggtags-mode
Imenuを使用する
(setq-local imenu-create-index-function #'ggtags-build-imenu-index)
helm
moo-jump-localを使用する
3.2.プロジェクト内参照
ggtags-mode
| コマンド | コマンド名 | 概要 |
|---|---|---|
| M-. | ggtags-finde-tag-dwim | ・定義にポイントしていれば参照先を表示する ・参照にポイントしてれば定義を表示する ・include ヘッダーをポイントしていればそのヘッダーを表示する ・その他の場所であれば定義,参照一覧が表示され,絞り込みができる |
| M-, | pop-tag-mark | ジャンプ元へ戻る |
| M-n, M-p | 候補内移動 | |
| M-g s | 候補内検索 |
helm-mode
| コマンド | コマンド名 | 概要 |
|---|---|---|
| M-. | helm-gtags-dwim | ggtags-find-tag-dwim と一緒 |
| M-, | tags-loop-continue | pop-tag-mark と一緒 |
| C-j | helm-gtags-select | 空白部分で M-. するのと一緒.定義や山椒を一覧から絞り込み&ジャンプできる |
4.参照元ジャンプ
gtags-mode
ggtags-find-reference, ggtags-find-tag-dwimを使う
helm-gtags
| コマンド | コマンド名 | 概要 |
|---|---|---|
| C-c g r | helm-gtags-find-rtag | ・関数内で呼び出したら,その関数についての参照先を検索する ・関数名上で呼び出したら,参照先のリストを表示する ・変数名にポイントしていたら,なにもしない |
| C-c g s | htlm-gtags-find-symbol | 変数名ポイント時に参照元を検索する |
| C-c g a | htlm-gtags-tagas-in-this-function | 現在の関数が参照する関数一覧 |
5.ファイル検索
ggtags-mode
ggtags-find-file
helm-gtags
helm-gtags-find-files
正直Projectile使ったほうが良いとのこと.
6.過去に訪れたタグへジャンプ
ggatgs-mode
ggtags-view-tag-history(C-c g h)
helm-gtags
helm-gtags-show-stack
7.Speedbar
ソースツリーを見れるパッケージ.ただのソースツリーではなくて,戻り値や関数なども一覧できるのが便利っぽい.
| コマンド | 操作 |
|---|---|
| SPC | 子ノードを開く |
| RET | ノードを別ウインドウで開く |
| U | 親ノードへ移動 |
| n,p | ノードを上下移動 |
| M-n,M-p | 現在の階層内でノードを上下移動 |
| b | Speedbarのバッファリストに戻る |
| f | ファイルリストに戻る |
7.1.sr-speedbar
Speedbarを便利にするパッケージ.
- 起動/終了
- sr-speedbar-open, sr-speedbar-toggle : 開く
- sr-speedbar-cloe, sr-speedbar-toggle : 閉じる
- 改善点
- フレームの代わりにEmacs windowを使用する
C-x 1でSpeedbarを除くすべてのウインドウを削除するC-x oでSpeedbarに移動するのを防ぐ(sr-speedbar-skip-other-window-pをtにする)
8.Company-mode (補完)
company-mode を使う.company-mode はEmacsのための補完フレームワーク.
1
2
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
8.2.使い方
| コマンド | 操作 |
|---|---|
| M-n,M-p | 候補移動 |
| RET,TAB | 候補決定 |
| C-s,C-r,C-o | 候補検索 |
| M-(数値) | 候補簡易選択 |
| 選択中候補のドキュメントを表示 | |
| C-w | 選択中候補のソースコード表示 |
company-backendsで候補に使用するリソースを指定する.
8.3.C言語の補完
C言語でcompanyの補完を利用するためには,以下を記述する.
1
2
3
(delete 'company-semantic company-backends)
(define-key c-mode-map [(tab)] 'company-complete)
(define-key c++-mode-map [(tab)] 'company-complete)
上記の設定では,company-semanticを削除している.理由は後述.company-semanticについてはCEDITの項で詳しく説明する.
companyの補完として,以下の二つが働く.
8.3.1.company-clang
補完候補の取得のためにclangを使用する.プロジェクトではなく,ヘッダファイルによって補完を行う.デフォルトではcompany-clangはcompany-semanticのサブセットであるため,上記設定を行っていれば他に特別な設定はいらない.
上記せて血でcompany-semanticを削除したのは,そうしないとcompany-completeがcompany-clangではなくcompany-semanticを使用してしまうため.これは,company-backends内の優先度がそうなっているため生じる.
補完候補をプロジェクト内から取得するためには,.dir-locals.elをプロジェクトルートに配置する必要がある.
1 2 | |
helmを使っているなら,C-x C-fによるファイル検索中に,対象ファイル選択状態からC-c iによって絶対パスを挿入できる.
nilを指定すると設定をすべてのサブディレクトリ,ファイルに適用し,non-nilであれば設定を適用するメジャーモードを指定できる.company-clang-argumentsはインクルードパスを指定するリストである.
8.3.2comapny-gtags
GNU GlobalのGTAGSから補完候補を取得する.プロジェクトによる補完を行うことができる.
8.4.ヘッダーの補完
プロジェクト内のヘッダーを補完したいなら,company-c-headersを使用する.以下のようにcompany-backendsに追加すれば良い.
1
| |
C++でヘッダーの補完を行いたいならば,パスを追加する必要がある.company-c-headerはシステムのインクルードパスとして/usr/include/と/usr/local/include/しか含んでいない.例としては以下のように追加する.
1
| |
9.CEDET
CEDETはCollection of Emacs Development Environment Toolsの略称.CEDETのデメリットは,Emacs Lispで書かれているため,Emacsのパフォーマンスに影響すること.23.2以降のEmacsにはマージされているので,インストールの必要はない.
最新版は以下のようにダウンロードすれば良い.
1
2
3
4
5
$ git clone http://git.code.sf.net/p/cedet/git cedet
$ cd cedet
$ make # wait for it to complete
$ cd contrib
$ make
Emacs からロードする.
1
2
(load-file (concat user-emacs-directory "/cedet/cedet-devel-load.el"))
(load-file (concat user-emacs-directory "cedet/contrib/cedet-contrib-load.el"))
9.1.Semanticマイナーモード
Semanticは,ソースコードパーサを利用して構文を考慮した補完を行ってくれるパッケージ.
9.1.1セットアップ
1 2 3 4 5 6 7 | |
9.1.2.semantic-mode
Semantic-modeでは,Emacsは現在のバッファをパースする.シンボルにカーソルを合わせるとsemanticはすべてのincludeファイルを読みに行くので,たまに時間がかかる.しかし一回パースすれば終わりなので,問題はない.
9.1.3.パスの追加
Semantic のデフォルトのインクルードパスはsemantic-dependency-system-include-pathに格納されており,追加したい場合は以下のようにする.
1 2 3 | |
9.1.4.company-modeにおけるSemantic-mode
company-modeにはcompany-semanticコマンドがあり,これがSemanticDBを補完候補の取得に利用する.company-semanticの良いところは,semantic-ia-complete-symbolが改善されているところ.元は1文字以上タイプしていなければ補完を検索してくれなかったが,company-semanticではプレフィクスなしで補完してくれる.
global-sematicdb-minor-mode- パース結果をキャッシュする.キャッシュ結果は
semanticdb-default-save-directory変数内のパスに保存されるが,デフォルトでは~/.emacs.d/semanticdbいかに保持される
- パース結果をキャッシュする.キャッシュ結果は
global-semantic-idle-scheduler-mode- このモードが有効になっていると,バッファーが期限切れになっていた時,ユーザがタイプしていない間にパーサをし直す.これがオフだと,バッファはコマンドによって手動でパースし直さなければならない
9.2.CEDETのその他の機能
Semanticがソースコードをパースし作成したデータベースは,コードの補完の他にも様々な使い道がある.コードナビゲーションや定義元・参照元ジャンプなど.
9.2.1.Senator
CEDETの一部で,SEmainticNAvigaTORの略称.
9.2.2.デバッグ
GDBとかGUDとかがあるらしい.
あとは気が向いたら.