用ctags索引Android资源定义的.xml和.png文件
看着Android的那一堆资源定义文件,真是头疼啊,只能一点一点的grep,有点不 便呢。
今日突发奇想,能不能把它当成一种编程语言,用编程语言索引之王—— ctags-exuberant来处理它呢?试试看!
先打开man手册看一眼?不用了,我以前搞过linux kernel kconfig脚本的ctags
处理,这回打开 $HOME/.ctags
复习一下先:
--langdef=kconfig --langmap=kconfig:(Kconfig) --regex-kconfig=/^(menu)?config[ \t]*([a-zA-Z0-9_]+)/CONFIG_\2/d,definition/
照葫芦画瓢,所以我们的layout、strings等xml可以这样写它们的语言定义之正则表达式:
--langdef=androidxml --langmap=androidxml:.xml --regex-androidxml=/android:id="@\+id\/([^"]*)"/\1/d,id/ --regex-androidxml=/name[ \t]*=[ \t]*"([^"]*)"/\1/d,resource/
试了一下,嗯,索引之王ctags-exuberant,果然是,行!科科科…
接下来,要对.png文件进行索引!什麻?你问有没有听错?.png文件不是图片吗, 怎么可能把它当成编程语言文件进行索引呢?是这样的,.png图片文件是一种资 源,而Android会为每一项资源生成一个id,放在它自动生成的R.java文件中。但 你索引这些R.java的话,就真的是“索”然无味啊,找到一堆id,根本不明白它们哪个是哪个:
public static final int app_name=0x7f050000; public static final int eglconfig_prompt=0x7f050001; public static final int eglconfig_text=0x7f050002; public static final int logging_prompt=0x7f050003; public static final int logging_text=0x7f050004;
BUT!人生最厉害就是这个BUT!png资源对应的id名字就是该png文件名去掉.png 扩展名而已啊!(请问这是什么编程模式?真的是,行!)
但这个功能没法简单的hack ctags-exuberant来搞定了,但是因为我是通过 gtags-plugin来调用ctags的,所以我们可以掉头去搞gtags的plugin-example, 结果见图:
尤其爽的是,在Emacs底下,“编辑”.png文件的话,会把它以图片方式打开,而不 是一堆乱码。这样才够直观嘛!另外,很多layout下的.xml文件名也会被当作一 个id出现在源码中,所以我们也一并处理了,gtags的patch如下(已经checkin到 我的配置系统 ):
diff --git a/gcode/global/plugin-example/exuberant-ctags.c b/gcode/global/plugin-example/exuberant-ctags.c index b7ea5dd..09048d0 100644 --- a/gcode/global/plugin-example/exuberant-ctags.c +++ b/gcode/global/plugin-example/exuberant-ctags.c @@ -249,16 +249,42 @@ put_line(char *ctags_x, const struct parser_param *param) param->put(PARSER_DEF, tagname, lineno, param->file, p, param->arg); } +static int handle_special_files(const struct parser_param *param, int filename_len, const char* ext, const char* fakeline) +{ + int extlen = strlen(ext); + if (filename_len > extlen && ! strcmp(param->file + filename_len - extlen, ext)) { + char filename[1024]; + char* p = param->file + filename_len - extlen; + while (p > param->file && *--p != '/') + ; + p++; + strncpy(filename, p, sizeof filename); + filename[param->file + filename_len - p - extlen] = '\0'; + param->put(PARSER_DEF, filename, 1, param->file, fakeline, param->arg); + return 1; + } + return 0; +} + void parser(const struct parser_param *param) { char *ctags_x; + int filename_len; assert(param->size >= sizeof(*param)); if (op == NULL) start_ctags(param); + filename_len = strlen(param->file); + + handle_special_files(param, filename_len, ".xml", "xml:\t***"); + if (handle_special_files(param, filename_len, ".9.png", "9png:\t***") || + handle_special_files(param, filename_len, ".png", "png:\t***")) { + return; + } + /* Write path of input file to pipe. */ fputs(param->file, op); putc('\n', op);
事实上,我还想把Android的颜色资源id真的用它所代表的颜色画出来呢。下次吧!
<color name="link_text_dark">#5c5cff</color>