[请教] c++ 方法定义包括在 namespace 里面 无法通过 <SPC s j> 或者 imenu-list 显示 函数列表

c++ 方法定义包括在 namespace 里面 无法通过 SPC s j 或者 imenu-list显示 函数列表

有些同学喜欢把函数的定义写在 namespace 里面,或者模板文件里,这样如何才能显示方法列表,特别是大文件,查看方法就很不方便,大家有什么好方法吗?

namespace test
{
    void method1() {
    }

     void method2() {
    }
}

我这里可以啊,默认 imenu-list 配置

难道是我的什么配置有冲突?

建议在 Vallina Emacs 上测试一下

C-h v imenu-create-index-function, 当它是imenu-default-create-index-function的时候,会使用imenu-generic-expression,是一些用来生成imenu的正则,否则还要具体研究那个index function

我列了一些信息,能否帮忙看一下, 多谢了,

imenu-create-index-function is a variable defined in ‘imenu.el’.
Its value is ‘imenu-default-create-index-function’

  Automatically becomes buffer-local when set.
  This variable may be risky if used as a file-local variable.

Documentation:
The function to use for creating an index alist of the current buffer.

It should be a function that takes no arguments and returns
an index alist of the current buffer.  The function is
called within a ‘save-excursion’.

See ‘imenu--index-alist’ for the format of the buffer index alist.

//--------------------------------------------------------------------------------------------------------------------

imenu-generic-expression is a variable defined in ‘imenu.el’.
Its value is shown below.

  Automatically becomes buffer-local when set.
  This variable may be risky if used as a file-local variable.

Documentation:
List of definition matchers for creating an Imenu index.
Each element of this list should have the form

  (MENU-TITLE REGEXP INDEX [FUNCTION] [ARGUMENTS...])

MENU-TITLE should be nil (in which case the matches for this
element are put in the top level of the buffer index) or a
string (which specifies the title of a submenu into which the
matches are put).
REGEXP is a regular expression matching a definition construct
which is to be displayed in the menu.  REGEXP may also be a
function of no arguments.  If REGEXP is a function, it is
expected to search backwards, return non-nil if it finds a
definition construct, and set ‘match-data’ for that construct.
INDEX is an integer specifying which subexpression of REGEXP
matches the definition’s name; this subexpression is displayed as
the menu item.
FUNCTION, if present, specifies a function to call when the index
item is selected by the user.  This function is called with
arguments consisting of the item name, the buffer position, and
the ARGUMENTS.

The variable ‘imenu-case-fold-search’ determines whether or not
the regexp matches are case sensitive, and ‘imenu-syntax-alist’
can be used to alter the syntax table for the search.

If non-nil this pattern is passed to ‘imenu--generic-function’ to
create a buffer index.

For example, see the value of ‘fortran-imenu-generic-expression’
used by ‘fortran-mode’ with ‘imenu-syntax-alist’ set locally so that
characters which normally have "symbol" syntax are considered to have
"word" syntax during matching.

Value:
((nil "^\\<.*[^[:alnum:]_:<>~]\\(\\([[:alnum:]_:<>~]*::\\)?operator\\>[ 	]*\\(()\\|[^(]*\\)\\)[ 	]*([^)]*)[ 	]*[^ 	;]" 1)
 (nil "^\\([[:alpha:]_][[:alnum:]_:<>~]*\\)[ 	]*([ 	]*\\([^ 	(*][^)]*\\)?)[ 	]*[^ 	;(]" 1)
 (nil "^\\<[^()
]*[^[:alnum:]_:<>~]\\([[:alpha:]_][[:alnum:]_:<>~]*\\)\\([ 	
]\\|\\\\
\\)*(\\([ 	
]\\|\\\\
\\)*\\([^ 	
(*][^()]*\\(([^()]*)[^()]*\\)*\\)?)\\([ 	
]\\|\\\\
\\)*[^ 	
;(]" 1)
 ("Class" "^\\(template[ 	]*<[^>]+>[ 	]*\\)?\\(class\\|struct\\)[ 	]+\\([[:alnum:]_]+\\(<[^>]+>\\)?\\)\\([ 	
]\\|\\\\
\\)*[:{]" 3))
Local in buffer IpSessionAdapter.cc; global value is nil

//----------------------------------------------------------------------------------------------------------------

cc-imenu-c++-generic-expression is a variable defined in ‘cc-menus.el’.
Its value is shown below.

Documentation:
Imenu generic expression for C++ mode.  See ‘imenu-generic-expression’.

Value:
((nil "^\\<.*[^[:alnum:]_:<>~]\\(\\([[:alnum:]_:<>~]*::\\)?operator\\>[ 	]*\\(()\\|[^(]*\\)\\)[ 	]*([^)]*)[ 	]*[^ 	;]" 1)
 (nil "^\\([[:alpha:]_][[:alnum:]_:<>~]*\\)[ 	]*([ 	]*\\([^ 	(*][^)]*\\)?)[ 	]*[^ 	;(]" 1)
 (nil "^\\<[^()
]*[^[:alnum:]_:<>~]\\([[:alpha:]_][[:alnum:]_:<>~]*\\)\\([ 	
]\\|\\\\
\\)*(\\([ 	
]\\|\\\\
\\)*\\([^ 	
(*][^()]*\\(([^()]*)[^()]*\\)*\\)?)\\([ 	
]\\|\\\\
\\)*[^ 	
;(]" 1)
 ("Class" "^\\(template[ 	]*<[^>]+>[ 	]*\\)?\\(class\\|struct\\)[ 	]+\\([[:alnum:]_]+\\(<[^>]+>\\)?\\)\\([ 	
]\\|\\\\
\\)*[:{]" 3))

这个正则里面没有namespace也没有void字样,肯定匹配不到,楼上可以的估计是开了lsp,最好的办法是用lsp,imenu肯定是最准的,不然就自己往那一堆正则里加一条。

这个正则 怎么加呀? 我看到正则 就头疼 :sweat:

是的这个正则如同天书,所以还是把lsp配好吧

我在公司的环境,装不了 lsp, 唉

这个问题一直困扰着我,今天突然发现一个现象,就是只要我把namespace里面的函数定义顶格写,imenu-list 就能显示出来,后来又试了一下,不管什么内容,只要顶格写,他就显示出来,当然,一般情况下,函数体是不会顶格写的。

与其顶格写,不如改一下 c++ imenu 正则表达式:

(with-eval-after-load 'cc-menus
  ;; Replace (nil "^..." ...) with (nil "^[ \t]*..." ...) to match function with leading spaces.
  (cl-loop for key-val in cc-imenu-c++-generic-expression
           unless (car key-val)
             do (setf (cdr key-val)
                      (push (concat "^[ \t]*" (substring (nth 1 key-val) 1))
                            (nthcdr 2 key-val))))

  ;; Match namespace (base on the class regexp)
  (setq cc-imenu-c++-generic-expression
        `(,@cc-imenu-c++-generic-expression
          ("Namespace"
           ,(concat
             "^[ t]*"                             ; beginning of line is required
             "\\(namespace\\)[ \t]+"
             "\\("                                ; the string we want to get
             "[" c-alnum "_]+"                    ; namespace name
             "\\(<[^>]+>\\)?"                     ; possibly explicitly specialized
             "\\)"
             "\\([ \t\n]\\|\\\\\n\\)*[:{]")
           2))))

主要 imenu 的机制太弱了,远不如 font lock 灵活。

1 个赞