imenu可以定位C/C++文件里的函数,配合anything使用,非常方便。可是我却发现,它无法定位带有函数指针作为参数的函数,如gcc/genattrtab.c里面的
static rtx substitute_address (rtx exp, rtx (*no_address_fn) (rtx), rtx (*address_fn) (rtx))
查看imenu的代码后发现,原来imenu是一个framework,具体的定位功能,是由相应的major mode实现的,我发现的问题,其实是cc-mode的实现有缺陷。在报了bug几天后,CC mode maintainer解决了这个问题。如果暂时没法(或不愿意)升级到最新的开发版,可以在自己的.emacs
文件里添加如下配置,对于已经打开的文件,需要revert-buffer
才能奏效。两个setq
语句是从lisp/progmodes/cc-menus.el
里摘录出来,如果下面的代码看不清楚,可以从源文件里直接复制。
(eval-after-load 'cc-mode '(progn (setq cc-imenu-c++-generic-expression `( ;; Try to match ::operator definitions first. Otherwise `X::operator new ()' ;; will be incorrectly recognised as function `new ()' because the regexps ;; work by backtracking from the end of the definition. (nil ,(concat "^\\< .*" "[^" c-alnum "_:<>~]" ; match any non-identifier char ; (note: this can be `\n') "\\(" "\\([" c-alnum "_:<>~]*::\\)?" ; match an operator "operator\\>[ \t]*" "\\(()\\|[^(]*\\)" ; special case for `()' operator "\\)" "[ \t]*([^)]*)[ \t]*[^ \t;]" ; followed by ws, arg list, ; require something other than ; a `;' after the (...) to ; avoid prototypes. Can't ; catch cases with () inside ; the parentheses surrounding ; the parameters. e.g.: ; `int foo(int a=bar()) {...}' ) 1) ;; Special case to match a line like `main() {}' ;; e.g. no return type, not even on the previous line. (nil ,(concat "^" "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name "[ \t]*(" ; see above, BUT "[ \t]*\\([^ \t(*][^)]*\\)?)" ; the arg list must not start "[ \t]*[^ \t;(]" ; with an asterisk or parentheses ) 1) ;; General function name regexp (nil ,(concat "^\\< " ; line MUST start with word char ;; \n added to prevent overflow in regexp matcher. ;; http://lists.gnu.org/archive/html/emacs-pretest-bug/2007-02/msg00021.html "[^()\n]*" ; no parentheses before "[^" c-alnum "_:<>~]" ; match any non-identifier char "\\([" c-alpha "_][" c-alnum "_:<>~]*\\)" ; match function name "\\([ \t\n]\\|\\\\\n\\)*(" ; see above, BUT the arg list "\\([ \t\n]\\|\\\\\n\\)*" ; must not start "\\([^ \t\n(*]" ; with an asterisk or parentheses "[^()]*\\(([^()]*)[^()]*\\)*" ; Maybe function pointer arguments "\\)?)" "\\([ \t\n]\\|\\\\\n\\)*[^ \t\n;(]" ) 1) ;; Special case for definitions using phony prototype macros like: ;; `int main _PROTO( (int argc,char *argv[]) )'. ;; This case is only included if cc-imenu-c-prototype-macro-regexp is set. ;; Only supported in c-code, so no `:<>~' chars in function name! ,@(if cc-imenu-c-prototype-macro-regexp `((nil ,(concat "^\\< .*" ; line MUST start with word char "[^" c-alnum "_]" ; match any non-identifier char "\\([" c-alpha "_][" c-alnum "_]*\\)" ; match function name "[ \t]*" ; whitespace before macro name cc-imenu-c-prototype-macro-regexp "[ \t]*(" ; ws followed by first paren. "[ \t]*([^)]*)[ \t]*)[ \t]*[^ \t;]" ; see above ) 1))) ;; Class definitions ("Class" ,(concat "^" ; beginning of line is required "\\(template[ \t]*<[^>]+>[ \t]*\\)?" ; there may be a `template < ...>' "\\(class\\|struct\\)[ \t]+" "\\(" ; the string we want to get "[" c-alnum "_]+" ; class name "\\(< [^>]+>\\)?" ; possibly explicitly specialized "\\)" "\\([ \t\n]\\|\\\\\n\\)*[:{]" ) 3))) (setq cc-imenu-c-generic-expression cc-imenu-c++-generic-expression)))
看了下wiki,感觉功能上和ecb有点类似,不知您平常是怎么用的,体验如何
配合anything使用,anything-config.el里面有anything-c-source-imenu,直接拿来用。
话说如果开启了 ido-ubiquitous 的话,anything 就没什么作用了吧,感觉两者功能差不多?
没有接触过ido,有机会学习一下。