Emacsで関数ジャンプ(gtags)&pygments-parserを使用して色々な言語で関数ジャンプ

  • 6
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Emacs で関数ジャンプを行うために gtags を導入した話です。
また global-pygments-plugin を使って gtags が対応していない言語でも関数ジャンプをやってみた話です。

記事の中では gtags のインストール後に Pygments を導入しますが、
実際にやってみたら PythonPygments を先にインストールしておかないと、
gtags./configure でちゃんと設定が行われないようです。ご注意ください。

環境

  • Ubuntu 14.04

gtags を試す

gtags でソースコードの関数ジャンプをできるようにする
gtags は C/C++, Java, PHP などしか対応していないらしい
※まずは通常の gtags で色々試してみます。
※後述で global-pygments-plugin を適用して対応言語を増やしてみます。

ということで、

  1. 事前準備
    1. gtags のインストール(ソースコードから)
    2. Emacsからgtagsを使えるようにする
  2. 実践
    1. C++ で試してみる
    2. Java で試してみる

こんな感じで進めていきます。

事前準備

gtags のインストール(ソースコードから)

https://www.gnu.org/software/global/download.html
2016/08/10現在: 6.5.4 が最新

$ wget http://tamacom.com/global/global-6.5.4.tar.gz
$ tar -zxvf global-6.5.4.tar.gz
$ cd global-6.5.4
$ ./configure
$ make
$ make install
$ which gtags
/usr/local/bin/gtags

./configureで発生した問題

configure: checking "location of ncurses.h file"...
configure: error: curses library is required but not found.
If you are not going to use gtags-cscope, please try ./configure --disable-gtagscscope

なんか無いよ。とな。

$ sudo apt-get install ncurses-dev

上記でライブラリをインストールしてから再度 ./configure で問題なくOK

Emacsからgtagsを使えるようにする

gtags.elのパスを通す

(add-to-list 'load-path "/usr/local/share/gtags")

恐らく上記にあるはず・・・

.emacsの設定を追加

.emacs
(autoload 'gtags-mode "gtags" "" t)
(setq gtags-mode-hook
    '(lambda ()
        (local-set-key "\M-t" 'gtags-find-tag)    ;関数へジャンプ
        (local-set-key "\M-r" 'gtags-find-rtag)   ;関数の参照元へジャンプ
        (local-set-key "\M-s" 'gtags-find-symbol) ;変数の定義元/参照先へジャンプ
        (local-set-key "\C-t" 'gtags-pop-stack)   ;前のバッファに戻る
        ))

とりあえず c-modec++-mode の時に gtags-modeに入るようにする

.emacs
(add-hook 'c-mode-hook 'gtags-mode)
(add-hook 'c++-mode-hook 'gtags-mode)

実践

C++ で試してみる

https://github.com/chibi929/hello-gtags
上記の Cpp ディレクトリで試しています

ソースコードタグの準備

$ git clone git@github.com:chibi929/hello-gtags.git
$ cd hello-gtags/CppProject
$ gtags -v
[Thu Aug 11 01:01:24 JST 2016] Gtags started.
 Using default configuration.
[Thu Aug 11 01:01:24 JST 2016] Creating 'GTAGS' and 'GRTAGS'.
 [1] extracting tags of Sample.cpp
 [2] extracting tags of Sample.h
 [3] extracting tags of main.cpp
[Thu Aug 11 01:01:24 JST 2016] Done.

ジャンプ実行

例1-1(gtags-find-tag)

20160811011006.png

上記では main.cpp:L11: hoge() にカーソルを合わせて M-t を実行しています。
Find tag: (default hoge) となっており Enter を押すと main.cpp:L4: void hoge() に飛びます。

例1-2(gtags-find-tag)

20160811011059.png

上記では main.cpp:L13: sample.test() にカーソルを合わせて M-t を実行しています。
Find tag: (default test) となっており Enter を押すと Sample.cpp:L12: void Sample::test() に飛びます。

例2(gtags-find-rtag)

20160811011654.png

上記では Sample.cpp:L12: void Sample::test() にカーソルを合わせて M-r を実行しています。
Find tag (reference): (default test) となっており Enter を押すと以下のように Sample::test() の参照元を表示してくれます。

20160811011857.png

上記の例では2つのうちどちらかを選ぶとでそのファイルに飛びます。

例3(gtags-find-symbol)

省略。
変数の参照元や参照先へジャンプすることができます。

Java で試してみる

https://github.com/chibi929/hello-gtags
上記の Java ディレクトリで試しています

java-mode 時の gtags-mode の設定が必要

.emacs
(add-hook 'java-mode-hook 'gtags-mode)

あとは C++ の時と同じなので省略。

global-pygments-plugin を試す

global-pygments-pluginGNU GLOBAL 6.3.2 から取り込まれたプラグインらしい
gtags の欠点だった対応言語が少ないという点を改善してくれるとのこと
global-pygments-plugin を使用するには Pygments というものが必要らしい
Pygments を使用するには Python 2.6 以上 が必要らしい

ということで、
1. Python 2.6 以上の準備
2. Pygments の準備
3. global-pygments-plugin を利用
といった感じだろうか。

Python 2.6 以上の準備

せっかくなので pyenv を導入
内容は省略

$ pyenv versions
  system
* 2.7.12 (set by /home/chibi/.pyenv/version)
  3.5.2

$ python --version
Python 2.7.12

$ pip --version
pip 8.1.1 from /home/chibi/.pyenv/versions/2.7.12/lib/python2.7/site-packages (python 2.7)

とりあえずこんな感じ

Pygments の準備

$ pip install Pygments
$ pygmentize -V
Pygments version 2.1.3, (c) 2006-2015 by Georg Brandl.

global-pygments-plugin を利用

.bashrc に設定を追加

.bashrc
export GTAGSCONF=/usr/local/share/gtags/gtags.conf
export GTAGSLABEL=pygments

上手く動かない!!

pygments_parser.py でエラー!!

$ gtags --gtagslabel=pygments
Traceback (most recent call last):
  File "/usr/local/share/gtags/script/pygments_parser.py", line 27, in <module>
    import pygments.lexers
ImportError: No module named pygments.lexers
gtags: unexpected EOF.

/usr/local/share/gtags/script/pygments_parser.py#!/usr/bin/python が、
実際に利用している python を指していないせいだとか。
りあえず無理矢理書き換えてみるとエラーが消えた。

タグが定義されていない!!

$ gtags -v --debug
[Thu Aug 11 23:24:28 JST 2016] Gtags started.
 Using configuration file '/usr/local/share/gtags/gtags.conf'.
 Using configuration label 'pygments'.
 Using plug-in parser.
[Thu Aug 11 23:24:28 JST 2016] Creating 'GTAGS' and 'GRTAGS'.
DBG: Original skip list:
HTML/,HTML.pub/,tags,TAGS,ID,y.tab.c,y.tab.h,gtags.files,cscope.files,cscope.out,cscope.po.out,cscope.in.out,SCCS/,RCS/,CVS/,CVSROOT/,{arch}/,autom4te.cache/,*.orig,*.rej,*.bak,*~,#*#,*.swp,*.tmp,*_flymake.*,*_flymake,*.o,*.a,*.so,*.lo,*.zip,*.gz,*.bz2,*.xz,*.lzh,*.Z,*.tgz,*.min.js,*min.css
DBG: Regular expression of the skip list:
(/\.[^/]+$|/\.[^/]+/|/GTAGS$|/GRTAGS$|/GSYMS$|/GPATH$|/HTML/|/HTML\.pub/|/tags$|/TAGS$|/ID$|/y\.tab\.c$|/y\.tab\.h$|/gtags\.files$|/cscope\.files$|/cscope\.out$|/cscope\.po\.out$|/cscope\.in\.out$|/SCCS/|/RCS/|/CVS/|/CVSROOT/|/\{arch\}/|/autom4te\.cache/|/[^/]*\.orig$|/[^/]*\.rej$|/[^/]*\.bak$|/[^/]*~$|/#[^/]*#$|/[^/]*\.swp$|/[^/]*\.tmp$|/[^/]*_flymake\.[^/]*$|/[^/]*_flymake$|/[^/]*\.o$|/[^/]*\.a$|/[^/]*\.so$|/[^/]*\.lo$|/[^/]*\.zip$|/[^/]*\.gz$|/[^/]*\.bz2$|/[^/]*\.xz$|/[^/]*\.lzh$|/[^/]*\.Z$|/[^/]*\.tgz$|/[^/]*\.min\.js$|/[^/]*min\.css$)
DBG: .[/GPATH] => SKIPPED
DBG: .[/GTAGS] => SKIPPED
DBG: .[/GRTAGS] => SKIPPED
./Main.rb
 [1] extracting tags of Main.rb
[Thu Aug 11 23:24:28 JST 2016] Done.

$ gtags -d GTAGS
 __.COMPNAME     __.COMPNAME
 __.COMPRESS     __.COMPRESS ddefine ttypedef
 __.VERSION  __.VERSION 6

すごく苦しんだ。なぜダメなのか。
どうやら gtags インストール時の ./configure が影響しているようだ。
つまり Pygments インストール前に ./configure を実行しているため設定が何か漏れている気がする。
gtags をインストールしなおすといけた。
ちなみに上記で引っかかっていた #!/usr/bin/python の部分も pyenv 導入前に ./configure をしていたせいのようだ。

更に 追記 を行いましたので まとめ をご確認下さい。

Ruby で試してみる

https://github.com/chibi929/hello-gtags
上記の Ruby ディレクトリで試しています

.emacs
(add-hook 'ruby-mode-hook 'gtags-mode)

C++ , Java と同様に gtags-mode に入るようにする

$ gtags -v
[Thu Aug 11 23:56:50 JST 2016] Gtags started.
 Using configuration file '/usr/local/share/gtags/gtags.conf'.
 Using configuration label 'pygments'.
 Using plug-in parser.
[Thu Aug 11 23:56:50 JST 2016] Creating 'GTAGS' and 'GRTAGS'.
 [1] extracting tags of Sample.rb
 [2] extracting tags of Main.rb
[Thu Aug 11 23:56:50 JST 2016] Done.

$ gtags -d GTAGS
 __.COMPNAME     __.COMPNAME
 __.COMPRESS     __.COMPRESS ddefine ttypedef
 __.VERSION  __.VERSION 6
Sample  1 @n 1 class @n
hoge    2 @n 3 def @n
test    1 @n 2 def @n

Emacs での実行は C++ と同じなので省略

最後に

helm-gtags-mode を導入した内容も書こうと考えていましたが、
操作は gtags-mode と変わらないと思いますので書きませんでした。
実際に使う時は helm-gtags-mode を導入して使おうと思います!

色々な言語で関数ジャンプ というタイトルだけどデフォルト以外だと Ruby しか試していません。
まぁどれも同じだと思っています。C++, Javaの流れを見ても1個だけやればよさそう・・・。

まとめ

global-pygments-plugin を使う場合は先に環境を準備しましょう。
今回、まずは通常の gtags から使ってみようとしたため、後から Pygments を入れました。
その影響で gtags --gtagslabel=pygments が上手く動いてくれず、Rubyのソースコードタグが上手く生成されませんでした。

ということで、
1. python & pip の準備
2. Pygments の準備
3. GNU GLOBAL(gtags) の準備
という感じで進めていきましょう。

そもそも ctags , etags , gtags の違いもわかっていませんでしたが、
Emacsでタグジャンプ機能を使用する
こちらの記事で理解しました。

追記

別の環境で入れてみたら gtags -d GTAGS でダンプしてもどうにも空っぽ
Exuberant Ctags も入れないとダメかも?
GNU GLOBALの対応言語を大幅に増やすPygmentsパーサーを導入する
上記の記事によると Exuberant Ctags 5.5 以上 が必要とのこと。

$ ctags --version
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Aug 15 2016, 11:30:15
  Addresses: <dhiebert@users.sourceforge.net>, http://ctags.sourceforge.net
  Optional compiled features: +wildcards, +regex

入れてみたら期待するタグが定義されていた。

参考サイト

Helm-Gtags-Modeを導入してソースコードの読解する
GNU GLOBALへのPygmentsパーサー取り込みでソースコード読みが信じられないくらいに捗るはず
こちらの記事を参考にさせていただきました。ありがとうございました。