在以下c ++文本上运行pygments默认词法分析器:class foo{};
,结果是:
(Token.Keyword, 'class')
(Token.Text, ' ')
(Token.Name.Class, 'foo')
(Token.Punctuation, '{')
(Token.Punctuation, '}')
(Token.Punctuation, ';')
请注意,代币foo
的类型为Token.Name.Class
。
如果我将类名称更改为foobar
,我希望能够仅在触摸的令牌上运行默认词法分析器,在这种情况下,原始令牌foo
和{ {1}}。
问:如何保存词法分析器状态,以便标记化{
会产生类型为foobar{
的标记?
具有此功能将优化大型中间文件的语法突出显示,例如,该大型中间文件在文件中间恰好发生了更改(用户正在输入文本)。似乎没有记录的方式来执行此操作,也没有有关如何使用默认pygments lexers来执行此操作的信息。
是否有其他语法高亮系统支持此行为?
编辑:
以下是有关性能的示例:http://tpcg.io/ESYjiF
答案 0 :(得分:6)
根据我对源代码的理解,您想要的东西是不可能的。
我不会挖掘并尝试解释每一行相关的代码,但是基本上,这是发生了什么:
pygments.lexers.c_cpp.CLexer
,它是从pygments.lexer.RegexLexer
继承的。pygments.lex(lexer, code)
函数无非是在get_tokens
上调用lexer
方法并处理错误。lexer.get_tokens
基本上以unicode字符串解析源代码并调用self.get_tokens_unprocessed
get_tokens_unprocessed
是由每个Lexer定义的,相关方法是pygments.lexers.c_cpp.CFamilyLexer.get_tokens_unprocessed
。CFamilyLexer.get_tokens_unprocessed
基本上是从RegexLexer.get_tokens_unprocessed
获取令牌并重新处理其中的一些令牌。最后,RegexLexer.get_tokens_unprocessed
在定义的令牌类型(类似于(("function", ('pattern-to-find-c-function',)), ("class", ('function-to-find-c-class',)))
)上循环,并为每种类型(function
,class
,comment
...)循环在源文本中找到所有匹配项,然后处理下一个类型。
这种行为使您想要的事情变得不可能,因为它在令牌类型而不是文本上循环。
为了使我的观点更加清楚,我在lib file: pygments/lexer.py
, line: 628
for rexmatch, action, new_state in statetokens:
print('looking for {}'.format(action))
m = rexmatch(text, pos)
print('found: {}'.format(m))
并使用以下代码运行它:
import pygments
import pygments.lexers
lexer = pygments.lexers.get_lexer_for_filename("foo.h")
sample="""
class foo{};
"""
print(list(lexer.get_tokens(sample)))
输出:
[...]
looking for Token.Keyword.Reserved
found: None
looking for Token.Name.Builtin
found: None
looking for <function bygroups.<locals>.callback at 0x7fb1f29b52f0>
found: None
looking for Token.Name
found: <_sre.SRE_Match object; span=(6, 9), match='foo'>
[...]
如您所见,令牌类型是代码迭代的对象。
考虑到这一点,并且(如Tarun Lalwani在评论中所说的那样),即一个新字符可以破坏整个源代码结构这一事实,您做不到比在每次更新时重新整理整个文本更好的方法。