ztlevi
2017 年12 月 13 日 00:00
1
如何在imenu--generic-function
定义function regex的时候ignore一些case。
目前的正则表达式是这样的。但是这样会匹配到if
语句,希望能够将if, while
之类的ignore掉。
("Function" "^[ \t]*\\([A-Za-z_$][A-Za-z0-9_$]+\\)[ \t]*([a-zA-Z0-9, ]*) *\{ *$" 1) ;; xxx (e) { }
有试过这个,但是并不行。
("Function" "^[ \t]*\\([^if|while|for][A-Za-z_$][A-Za-z0-9_$]+\\)[ \t]*([a-zA-Z0-9, ]*) *\{ *$" 1) ;; xxx (e) { }
参考的陈斌大神的博客。Why Emacs is a better editor, part two | Chen's blog
LdBeth
2017 年12 月 13 日 00:55
2
Emacs 的正则怕是做不到。
这个不行是因爲 就算 [^if|while|for]
排除了这三個词,[A-Za-z_$][A-Za-z0-9_$]+\
也会把这三個词匹配进去。
如果这么写能排除 if/while/for,那函数名当中是不是也不能有这三个词?
ztlevi
2017 年12 月 13 日 01:46
4
这是山人配置里的一个正则,看上去区别只是while|for后面多了个空格。我也不知道这个正则的规则到底怎么样的。感觉imenu又加了一些规则,像是\\( \\)
中间的,好像就是能显示在imenu里面的string。
("Function" "^[ \t]*\\([^while|for ][a-zA-Z0-9_$]*\\)[ \t]*([a-zA-Z0-9_$,/\\* ]*)[ \t]*" 1)
ztlevi:
这是山人配置里的一个正则,看上去区别只是while|for后面多了个空格。我也不知道这个正则的规则到底怎么样的。感觉imenu又加了一些规则,像是\\( \\)
中间的,好像就是能显示在imenu里面的string。
("Function" "^[ \t]*\\([^while|for ][a-zA-Z0-9_$]*\\)[ \t]*([a-zA-Z0-9_$,/\\* ]*)[ \t]*" 1)
这个表达式有问题吧,[^a-z]
表示不匹配 a 到 z 范围 内的字符,[^az]
表示不匹配 ‘a’ 和 ‘z’ 两个 字符。所以整个表达式相当于把所有 ‘w’ ‘h’ ‘i’ ‘l’ ‘e’ ‘f’ ‘o’ ‘r’ 开头的函数都过滤掉了:
#+BEGIN_SRC emacs-lisp :results output
(with-temp-buffer
(insert "\
if () {}
while () {}
for () {}
ixxx () {}
fxxx () {}
wxxx () {}
foo () {}
bar () {}
quux () {}")
(goto-char (point-min))
(while (re-search-forward
"^[ \t]*\\([^while|for ][a-zA-Z0-9_$]*\\)[ \t]*([a-zA-Z0-9_$,/\\* ]*)[ \t]*"
nil t)
(princ (format "(match-string 1) => [%s]\n" (match-string 1)))
))
#+END_SRC
#+RESULTS:
: (match-string 1) => [bar]
: (match-string 1) => [quux]
for 后面那个空格应该是不起作用的,因为被前面的规则吃了。for 前面的 ‘|’ 应该也是没有起到“或”的作用,而是作为普通字符。
1 个赞
imenu-generic-expression
的正则表达式参数也可以是一个函数:
(MENU-TITLE REGEXP INDEX [FUNCTION] [ARGUMENTS...])
^^^^^^
REGEXP is a regular expression matching a definition construct
which is to be displayed in the menu. REGEXP may also be a
function , called without arguments. It is expected to search
backwards. It must return true and set ‘match-data’ if it finds
another element.
所以你可以在函数里面排除掉不想要的结果。我自己举了一个简单的例子,试了下是可以的:
假设文件内容为:
# foo
# bar
# baz
# auz
再设我想得到 # xxx
这样的 Imenu,但是排除掉 bar
,可以通过:
(defun foo-imenu-generic-expression-regexp ()
(if (re-search-backward "^# \\(.*\\)" nil t)
(if (string= (match-string 1) "bar")
(foo-imenu-generic-expression-regexp)
t)
nil))
(setq imenu-generic-expression '((nil foo-imenu-generic-expression-regexp 1)))
得到了预期的结果:
2 个赞
排除需要 (?!pattern)
,但是 emacs 目前不支持,看样子也没打算要支持:
所以你只能像楼上说的,再过滤一遍。或者再找找其他特征,你这是什么语言,函数定义会跟 if/while 混淆?
Update
如果是 elisp,并且过滤的是函数调用(不是定义),那你几乎把所有源代码都列出来了,意义何在?
况且 if/while… 这些在 lisp 中也是函数。
ztlevi
2017 年12 月 13 日 17:57
10
是js的,react里面会有,像
ComponentDidMount() {
}
render(){
}
就没有任何函数定义的keyword。
if / while 不会出现在顶层吧,我看 js2-imenu-extra-generic-expression 根本就不考虑这个问题:
("Function" "^[ ]*\\([A-Za-z_$][A-Za-z0-9_$]+\\)[ ]*([a-zA-Z0-9, ]*) *{ *$" 1)
ztlevi
2017 年12 月 14 日 07:12
12
顶层是什么意思?感觉默认给的问题都多多少少有点,像你给的这个,小括号里都不允许_.'"
,但写参数经常会用啊。
这个正则不能处理 default parameter, object destruct 和换行。
比如下面这个函数就匹配不到。
ShareNormal ({picName = "",
title = "",
reportIDLaunch = 0,
getGroupMsgTicket = false,
reportID = 0,
cbSuccess = undefined,
cbFailed = undefined} = {}){
我改了一下可以支持了:
^[ \t]*\\(async\\)?[ \t]*\\([A-Za-z_$][A-Za-z0-9_$]+\\)[ \t]*([\{a-zA-Z0-9, \\\)\('\"=\t\n\}]*) *\{ *
1 个赞
ShareNormal ({picName = ")",
title = " \") {",
reportIDLaunch = 0,
getGroupMsgTicket = false,
reportID = 0,
cbSuccess = undefined,
cbFailed = undefined} = {}){
这个呢?
现在可以了,你试试,添加了 ‘()\
在默认参数里面的支持
ztlevi
2018 年11 月 15 日 04:10
16
其实我发现像tide
和lsp-javascript-typescript
现在都支持imenu了,根据lang server的相对比较准确。