我正在为imenu-create-index-function
生成一个函数,为csharp-mode.el
它可以工作,但提供完全不可接受的性能。有任何解决方法吗?
我看了js.el,这是现在包含的重新加载的“espresso”,从第23版开始,进入emacs。它非常好地索引Javascript文件,使用匿名函数和常用的各种编码样式和模式做得很好。例如,在javascript中可以做到:
(function() {
var x = ... ;
function foo() {
if (x == 1) ...
}
})();
...定义x
为“私有”或其他代码无法访问的范围。 js.el使用regexp很好地索引它,并且它也在该范围内索引内部函数(匿名或非匿名)。它运作迅速。一个大模块可以在不到一秒的时间内建立索引。
我尝试在csharp模式下使用类似的方法,但它要复杂得多。在Js中,索引的所有内容都是函数。因此,起始正则表达式是“功能”,在任何一端都有一些细节。找到function
关键字后,会有4到8个其他正则表达式通过looking-at
进行尝试 - 数量取决于设置。关于js模式的一个好处是你可以打开或关闭各种编码风格的regexp,以加快我想的速度。默认的“样式”适用于我尝试过的大多数代码。
这在csharp模式下不起作用。它工作,但它的性能很差,不足以使它变得不可用。我认为原因是
C#中没有单个标记关键字,因为function
在javascript中表现。在C#中,我需要查找命名空间,类,结构,接口,枚举等。
有很多灵活性可以定义csharp结构。作为一个示例,类可以定义基类以及实现的接口。另一个例子:方法的返回类型不是简单的类似字符串的字符串,但可能像Dictionary<String, List<String>>
那样混乱。索引例程需要处理所有这些情况,并捕获匹配项。这使得它运行起来很懒散。
我使用了很多looking-back
。我在当前方法中使用的标记是开放的大括号。一旦我找到其中一个,我使用looking-back
来确定卷曲是一个类,接口,枚举,方法等。我读到looking-back
可能很慢;我不清楚它比looking-at
慢多少。
一旦我找到一对开合的curlies,我会调用narrow-to-region
来索引里面的内容。不确定这是否会杀死性能。我怀疑它不是主要的罪魁祸首,因为我看到的perf问题发生在具有一个命名空间和2或3个类的模块中,这意味着narrow总共被称为3或4次。
我的问题是:您是否有任何关于加快C#缓冲区中类似imenu索引的提示?
我在考虑:
避免looking-back
。我不确切知道如何执行此操作,因为当re-search-forward
找到关键字class
时,游标已经位于类声明的中间。 looking-back
似乎很重要。
而不是使用open-curly作为标记,使用enum,interface,namespace,class等关键字
避免narrow-to-region
任何艰难的建议?进一步的建议?
我尝试过的东西,我并不热衷于重新访问:为C#构建一个基于智慧的解析器,并依靠语义来进行索引。我发现语义非常非常(等)难以使用,难以发现和有问题。我有一段时间的语义工作,但后来升级到v23.2,它破了,我再也不能让它工作了。简单的事情 - 比如索引命名空间关键字 - 需要很长时间才能解决。我对此非常不满意,不想再试一次。
答案 0 :(得分:0)
我真的不知道C#语法,如果没有查看你的elisp,很难给出答案,但无论如何都要进行。
looking-back
可能会非常慢。这是我试验的第一件事。有一点很重要的是使用limit
arg来限制搜索到当前行的开头。另一种方法是,当你点击开放的卷曲做backward-char
然后backward-sexp
(或其他)来到前一个单词的前面,然后使用looking-at
。
使用关键字搜索而不是开放卷曲可能就是我要做的。也许类似于(re-search-forward "\\(enum\\|interface\\|namespace\\|class\\)[ \t\n]*{" nil t)
,然后在第一个捕获组上使用match-string-no-properties
来查看找到了哪些关键字。这也可能有助于解决looking-back
问题。
我不知道narrow-to-region
有多贵,但是当你找到一个开放的卷曲做save-excursion
forward-sexp
并保持point
作为限制时,可以避免您(我假设递归)搜索的当前迭代。