Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Emacs 使用regexp为imenu的文件编制索引,性能是不可接受的_Emacs_Elisp - Fatal编程技术网

Emacs 使用regexp为imenu的文件编制索引,性能是不可接受的

Emacs 使用regexp为imenu的文件编制索引,性能是不可接受的,emacs,elisp,Emacs,Elisp,我正在为imenu create index function生成一个函数,用于索引源代码模块,例如 它可以工作,但提供了完全不可接受的性能。有解决这个问题的建议吗 背景 我看了一下js.el,它是从v23.2开始重新标记的“espresso”,现在包含在emacs中。它很好地索引了Javascript文件,很好地处理了匿名函数和各种常用的编码样式和模式。例如,在javascript中,可以执行以下操作: (function() { var x = ... ; function

我正在为
imenu create index function
生成一个函数,用于索引源代码模块,例如

它可以工作,但提供了完全不可接受的性能。有解决这个问题的建议吗

背景 我看了一下js.el,它是从v23.2开始重新标记的“espresso”,现在包含在emacs中。它很好地索引了Javascript文件,很好地处理了匿名函数和各种常用的编码样式和模式。例如,在javascript中,可以执行以下操作:

(function() {
    var x = ... ; 
    function foo() {
       if (x == 1) ...
    }
})();
…定义
x
为“私有”或无法从其他代码访问的范围。js.el使用regexps很好地对其进行了索引,它还对该范围内的内部函数(匿名或非匿名)进行了索引。它工作得很快。一个大模块可以在不到一秒钟的时间内建立索引

我试着在csharp模式下采用类似的方法,但它相当复杂。在Js中,所有被索引的东西都是一个函数。因此,起始正则表达式是“函数”,两端都有一些详细说明。一旦发现出现
函数
关键字,则有4-8个其他regexp可通过
查看
-数量取决于设置。js模式的一个优点是,您可以为各种编码样式打开或关闭regexp,以加快速度。默认的“样式”适用于我尝试的大多数代码

这在csharp模式下不起作用。它可以工作,但是它的性能很差,以至于不能很好地使用。我想原因是

  • C#中没有单个标记关键字,因为
    function
    在javascript中起作用。在C#中,我需要查找名称空间、类、结构、接口、枚举等

  • csharp构造的定义具有很大的灵活性。例如,类可以定义基类以及实现的接口。另一个例子:方法的返回类型不是一个简单的类似于字符串的单词,而是一些混乱的东西,比如
    字典
    。索引例程需要处理所有这些情况,并捕获匹配项。这使得它运行缓慢

  • 我用了很多的
    回首往事
    。我在当前方法中使用的标记是开放的花括号。一旦我找到其中一个,我就使用
    回溯
    来确定卷曲是否是一个类、接口、枚举、方法等。我读到
    回溯
    可能很慢;我不清楚它比看要慢多少

  • 一旦我找到一对开合的卷发,我就调用
    窄到区域
    ,以索引里面的内容。不确定这是否会降低性能。我怀疑这不是罪魁祸首,因为我看到的性能问题发生在具有一个名称空间和2或3个类的模块中,这意味着窄带被调用的次数是总数的3或4倍

问题是什么? 我的问题是:对于在C#buffer中加速类似imenu的索引,您有什么建议吗

我正在考虑:

  • 避免
    回头看
    。我不知道如何做到这一点,因为当<代码>重新搜索前进>代码>发现,例如关键字<代码>类< /代码>时,光标已经在类声明的中间。代码>回顾似乎至关重要

  • 不要使用opencurly作为标记,而是使用诸如enum、interface、namespace和class之类的关键字

  • 避免
    缩小到区域

有什么建议吗?进一步的建议

一些我已经尝试过但并不热衷于重新访问的东西:为C#构建一个基于wisent的解析器,并依靠语义来进行索引。我发现语义很难使用,很难发现,而且有问题。我让语义工作了一段时间,但后来升级到v23.2,它坏了,我再也不能让它工作了。简单的事情——比如索引namespace关键字——需要很长时间才能解决。我很不满意,不想再试一次

我真的不懂C#语法,如果不看你的elisp,很难给出答案,但还是来了

回首往事
可能非常缓慢。这是我要做的第一件事。一件非常有用的事情是使用
limit
arg,例如,将搜索限制在当前行的开头。另一种方法是,当你点击打开的卷发do
backward char
然后
backward sexp
(或其他)到达前一个单词的前面,然后使用
查看

使用关键字搜索而不是打开卷发可能是我应该做的。可能类似于
(向前搜索“\\(枚举\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

我不知道窄到区域的成本有多高,但如果您找到一个开放的卷发,则可以避免此问题,方法是保存偏移,向前搜索sexp,并保留
点作为当前迭代(我假设是递归)搜索的限制