目次: Linux
先日(2025年10月27日の日記参照)はGNU global + pygmentsでC/C++/Pythonのタグジャンプができる環境を整えましたが、微妙に動かない事態に遭遇したのでトラブルシューティングのメモを残しておきます。
Ubuntu 24.04は定義や参照へのジャンプができるため機能的には問題ありませんが、gtagsを実行する度に妙な警告が出ます。
$ gtags --gtagslabel=pygments
/usr/share/global/gtags/script/pygments_parser.py:92: SyntaxWarning: invalid escape sequence '\s'
tag = re.sub('\s+', '', tag) # remove newline and spaces
/usr/share/global/gtags/script/pygments_parser.py:161: SyntaxWarning: invalid escape sequence '\s'
match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + '\s+(.*)$', line)
エラーの箇所を見るとglobalのヘルパースクリプト(/usr/share/global/gtags/script/pygments_parser.py)が間違っているっぽいので、下記のように修正すると警告が出なくなります。
--- pygments_parser.py.org 2025-10-26 22:48:13.811340349 +0900
+++ pygments_parser.py 2025-10-26 22:47:41.250646696 +0900
@@ -89,7 +89,7 @@
# we can assume index are delivered in ascending order
while self.lines_index[cur_line] <= index:
cur_line += 1
- tag = re.sub('\s+', '', tag) # remove newline and spaces
+ tag = re.sub(r'\s+', '', tag) # remove newline and spaces
if self.options.strip_punctuation:
tag = tag.strip(PUNCTUATION_CHARACTERS)
if tag:
@@ -158,7 +158,7 @@
line = self.child_stdout.readline()
if not line or line.startswith(TERMINATOR):
break
- match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + '\s+(.*)$', line)
+ match = re.search(r'(\S+)\s+(\d+)\s+' + re.escape(path) + r'\s+(.*)$', line)
if match:
(tag, lnum, image) = match.groups()
if self.options.strip_punctuation:
この現象を確認した環境は以下の通りです。
$ global --version global (GNU Global) 6.6.11 Powered by Berkeley DB 1.85 and SQLite3 3.45.1. Copyright (c) 1996-2023 Tama Communications Corporation License GPLv3+: GNU GPL version 3 or later <http://www.gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ dpkg -l | grep global ii global 6.6.11-1 amd64 Source code search and browse tools $ pygmentize -V Pygments version 2.17.2, (c) 2006-2023 by Georg Brandl, Matthäus Chajdas and contributors. $ dpkg -l | grep pygme ii python3-pygments 2.17.2+dfsg-1 all syntax highlighting package written in Python 3
だいぶ長くなってしまいましたが、これでDebian/Ubuntuともに快適globalタグジャンプ生活が送れるはずです。やったぜ。
この記事にコメントする
目次: Linux
先日(2025年10月27日の日記参照)はGNU global + pygmentsでC/C++/Pythonのタグジャンプができる環境を整えましたが、微妙に動かない事態に遭遇したのでトラブルシューティングのメモを残しておきます。
DebianやUbuntuではpython-is-python3をインストールすると/usr/bin/pythonがpython3を指すようになります。しかし何か事情があってPythonをPython3に固定すると困る人はpython-is-python3をインストールしていないでしょう。そのときはglobalがこんなエラーを出します。
$ gtags --gtagslabel=pygments /usr/bin/env: 'python': No such file or directory gtags: unexpected EOF.
何かの理由で/usr/bin/pythonをpython3に固定しない場合、globalのヘルパースクリプト(/usr/share/global/gtags/script/pygments_parser.py)の先頭にあるpythonをpython3に書き換えればエラーが解消されます。かなり強引ですけど。
せっかちさんのために結論を先に書いておくと、Debian Testingではexuberant-ctagsだと動作しません。universal-ctagsに入れ替えてください。
Debian Testingではglobal, python3-pygments, exuberant-ctagsの組み合わせだと、C/Pythonともに定義個所と参照個所の検索ができません。参照個所へのタグジャンプができないのは致命的に使いにくくて困ります。
$ global -x cfunc_b
$ global -rx cfunc_b
$ global -x pyfunc_b
$ global -rx pyfunc_b
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
この現象を確認した環境は以下の通りです。
$ gtags --version gtags (GNU Global) 6.6.14 Powered by Berkeley DB 1.85 and SQLite3 3.46.1. Copyright (c) 1996-2024 Tama Communications Corporation License GPLv3+: GNU GPL version 3 or later <http://www.gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ dpkg -l | grep global ii global 6.6.14-1.1 amd64 Source code search and browse tools $ pygmentize -V Pygments version 2.18.0, (c) 2006-2024 by Georg Brandl, Matthäus Chajdas and contributors. $ dpkg -l | grep pygments ii python3-pygments 2.18.0+dfsg-2 all syntax highlighting package written in Python 3
たぶん何かの設定間違いですよね。なんだろう?
Debian Testingでは最新版もしくはかなり新しいバージョンが採用されているはずですが「定義個所、参照個所が検知できない問題」が発生します。原因がさっぱりわからないのでglobalのソースコードを見ました。
# Debian Testingのglobalのコード
# global-6.6.14/plugin-factory/pygments_parser.py
def handle_requests(langmap, options):
# Update ctags's path from the configuration file
global UNIVERSAL_CTAGS
path = load_ctags_path()
if path != '':
UNIVERSAL_CTAGS = path
if UNIVERSAL_CTAGS != '' and UNIVERSAL_CTAGS != 'no':
pygments_parser = PygmentsParser(langmap, options)
try:
ctags_parser = CtagsParser(UNIVERSAL_CTAGS, options)
parser = MergingParser(ctags_parser, pygments_parser)
except Exception as e:
parser = pygments_parser
else:
parser = PygmentsParser(langmap, options)
#...
# (比較用)Ubuntu 24.04のglobalのコード
# global-6.6.11/plugin-factory/pygments_parser.py
def handle_requests(langmap, options):
# Update ctags's path from the configuration file
global EXUBERANT_CTAGS
path = load_ctags_path()
if path != '':
EXUBERANT_CTAGS = path
if EXUBERANT_CTAGS != '' and EXUBERANT_CTAGS != 'no':
pygments_parser = PygmentsParser(langmap, options)
try:
ctags_parser = CtagsParser(EXUBERANT_CTAGS, options)
parser = MergingParser(ctags_parser, pygments_parser)
except Exception as e:
parser = pygments_parser
else:
parser = PygmentsParser(langmap, options)
#...
コードからはDebian Testing側はuniversal-ctagsを参照していて、Ubuntu 24.04側はexuberant-ctagsを参照しているように見えます。公式サイト(https://www.gnu.org/software/global/)を改めて確認すると、"supports 25 languages by Pygments + Universal Ctags plug-in parser."と書いてありました。これは知らなかったです。
Internet Archiveで見ると2016年11月くらいにExuberant CtagsからUniversal Ctagsに表記が変わっていました。Release noteを見ると6.6.11(2023年11月リリース)でExuberant Ctagsがサポート外と記述されています。なぜ6.6.11を採用しているUbuntu 24.04でExuberant Ctagsが使えるのか謎が残りますが、深追いしてもあまり意味はないでしょう……。
$ sudo apt-get purge exuberant-ctags $ sudo apt-get install universal-ctags
話を戻すと、Debian Testingでは上記のようにexuberant-ctagsをアンインストールして、universal-ctagsをインストール(Debian系ならalternativesで切り替えても良いかも)すれば良いはずです。
#### Cの関数定義、参照個所を探す
$ global -x cfunc_b
cfunc_b 1 b.c int cfunc_b(int b)
$ global -rx cfunc_b
cfunc_b 3 a.c int cfunc_b(int b);
cfunc_b 7 a.c return cfunc_b(a) + 1;
#### Pythonの関数定義、参照個所を探す
$ global -x pyfunc_b
pyfunc_b 1 b.py def pyfunc_b(b: int):
$ global -rx pyfunc_b
pyfunc_b 1 a.py from b import pyfunc_b
pyfunc_b 4 a.py return pyfunc_b(a) + 1
#### grepモードでCもPythonも網羅的に探す
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
改善されました。良かった良かった。次回はUbuntuです。
この記事にコメントする
目次: Linux
プログラムの関数、変数の定義元や参照先に一瞬で飛べるタグジャンプ機能を使っている人は多いと思います。私もGNU globalを使ってタグを生成、vim/gvimでタグジャンプを利用していて、とても便利です。
今まではC/C++のコードを読むことが多かったため、global単体で事足りました。最近はPythonのコードを読むことも増えまして、Pythonもタグジャンプできるように環境を整えることにしました。global単体ではPythonに対応していないので、プラグインとしてpygmentsを使います。exuberant-ctagsのインストールもお忘れなく。
もっとも単純なセットアップ方法&使い方はこんな感じです。
$ sudo apt-get install global python-is-python3 python3-pygments exuberant-ctags $ gtags --gtagslabel=pygments
下記のテストプログラムを使って、タグが正しく作成されたか確認しましょう。
//// a.c
#include <stdio.h>
int cfunc_b(int b);
int cfunc_a(int a)
{
return cfunc_b(a) + 1;
}
int main(int argc, char *argv[])
{
int a = 5;
printf("%d\n", cfunc_a(a));
return 0;
}
//// b.c
int cfunc_b(int b)
{
return b + 2;
}
#### a.py
from b import pyfunc_b
def pyfunc_a(a: int):
return pyfunc_b(a) + 1
if __name__ == "__main__":
print(f"{pyfunc_a(5)}")
#### b.py
def pyfunc_b(b: int):
return b + 2
テストとして基本的な機能3つを確かめます。
#### Cの関数定義、参照個所を探す
$ global -x cfunc_b
cfunc_b 1 b.c int cfunc_b(int b)
$ global -rx cfunc_b
cfunc_b 3 a.c int cfunc_b(int b);
cfunc_b 7 a.c return cfunc_b(a) + 1;
#### Pythonの関数定義、参照個所を探す
$ global -x pyfunc_b
pyfunc_b 1 b.py def pyfunc_b(b: int):
$ global -rx pyfunc_b
pyfunc_b 1 a.py from b import pyfunc_b
pyfunc_b 4 a.py return pyfunc_b(a) + 1
#### grepモードでCもPythonも網羅的に探す
$ global -gx func
func 3 a.c int cfunc_b(int b);
func 5 a.c int cfunc_a(int a)
func 7 a.c return cfunc_b(a) + 1;
func 13 a.c printf("%d\n", cfunc_a(a));
func 1 a.py from b import pyfunc_b
func 3 a.py def pyfunc_a(a: int):
func 4 a.py return pyfunc_b(a) + 1
func 7 a.py print(f"{pyfunc_a(5)}")
func 1 b.c int cfunc_b(int b)
func 1 b.py def pyfunc_b(b: int):
参照個所を探す機能は地味に便利なので、CでもPythonでも動作してくれるのはありがたいですね。
こんなあっさり動けば苦労はないですが、実はDebian TestingでもUbuntu 24.04でも微妙に動きませんでした。あまり使われていないのかもしれない。悲しい。次回はトラブルシューティング編です。
この記事にコメントする
| < | 2025 | > | ||||
| << | < | 11 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | - | - | - | 1 |
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | - | - | - | - | - | - |
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: