1

我试图突出显示一堆单词 - 所以我写了一个 pygments 扩展。基本上它有效,但仍然不令我满意。

这是一个应该可行的简单想法:适当地突出显示单词,以及与这些单词不匹配的所有其他文本 - 在文本中。但这挂断了:

from pygments.lexer import RegexLexer
from pygments.token import *

class HotKeyPoetry(RegexLexer):
    name = 'HotKeyPoetry'
    aliases = ['HotKeyPoetry']
    filenames = ['*.hkp']

    tokens = {
        'root': [

            (r'\bAlt\b', Generic.Traceback),
            (r'\bShft\b', Name.Variable),
            (r'\bSpc\b', Operator),
            (r'\bCtrl\b', Keyword.Type),
            (r'\bRet\b', Name.Label),
            (r'\bBkSpc\b', Generic.Inserted),
            (r'\bTab\b', Keyword.Type),
            (r'\bCpsLk\b', String.Char),
            (r'\bNmLk\b', Generic.Output),
            (r'\bScrlLk\b', String.Double),
            (r'\bPgUp\b', Name.Attribute),
            (r'\bPgDwn\b', Name.Builtin),
            (r'\bHome\b', Number.Oct),
            (r'\bEnd\b', Name.Constant),
            (r'\bDel\b', Name.Decorator),
            (r'\bIns\b', Number.Integer.Long),
            (r'\bWin\b', Name.Builtin.Pseudo),
            (r'\bF1?[1-9]\b', Name.Function),

            (r'(?!\b(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F5)\b)', Text),

        ]
    }

也许我应该更好地使用另一个词法分析器来完成这项工作?

编辑 1

所以

r"(.+?)(?:$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|P‌​gDwn|‌​Home|End|Del|Ins|Win|F[12]?[1-9])\b))"

是我一直在寻找的排除正则表达式。

现在我正在尝试创建#一个评论字符——以便它之后的所有内容(在一行内)——都是评论:我试过了:

r"(.+?)(?:$|#.*$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|P‌​gDwn|‌​Home|End|Del|Ins|Win|F[12]?[1-9])\b))"

r"([^#]+?)(?:$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgD‌​wn|‌​Home|End|Del|Ins|Win|F[12]?[1-9])\b))"

其次是

 (r'#.*$', Comment),

我还尝试添加第二个状态:

'comment': [ 
      (r'#.*$', Comment),
],

- 但没有任何效果。

编辑 2

完整的工作 pygments 扩展 python 包在这里。你可以得到和

python setup.py build
python setup.py install --user

它在 pygments 中注册它。然后,您可以使用以下方法对其进行测试:

pygmentize -f html -O full -o test.html test.hkp

或指定一种语言:

pygmentize -f html -O full -l HotKeyPoetry -o test.html test.hkp

这是一个示例test.hkp

Ctrl-Alt-{Home/End} ⇒ {beginning/end}-of-visual-line
Ctrl-Alt-{b/↓/↑} ⇒ {set/goto next/goto previous} bookmark # I have it in okular and emacs
Alt-{o/O} ⇒ switch-to-buffer{/-other-window}
Ctrl-{o/O} ⇒ find-file{/-other-window}
Ctrl-x o ⇒ ergo-undo-close-buffer # it uses ergoemacs' recently-closed-buffers
Ctrl-Alt-O ⇒ find-alternate-file

(评论对于热键并没有真正有用——但我需要它们用于PyMOL)。

4

2 回答 2

4

1)您误解了(?!工作原理:它与文本不匹配。您的最后一个 RE(在原始代码块中)匹配的位置后面没有您列出的任何单词。但它匹配文本的零个字符,所以没有什么可以着色的,你不会继续前进。

你真正的意思是这样的:\b(?!(?:Alt|Shft|etc)\b)\w+\b。(匹配s\w+之间的任何单词\b,但如果第一个\b后面跟着任何关键字,则不匹配)

2)关于匹配注释:根据 pygments 文档,您的表达式(r'#.*$', Comment)应该可以工作。或者,在示例中使用的样式中:

(r'#.*\n', Comment),

3)你只需要一个状态,所以将评论规则添加到根状态。当你在不同的地方有不同的语法时,多个状态是适用的,例如,如果你混合了 html 和 PHP,或者如果你想突出显示 python 字符串中的 SQL。

4)您的规则需要匹配输入中的所有内容。规则会按顺序尝试,直到一个有效,所以不要尝试编写与关键字不匹配的规则,您可以将此通配符作为最后一条规则:

(r'(?s).', Text),

它会一次推进一个角色,直到你得到其他规则可以匹配的东西。重复:删除与非关键字匹配的长规则,并改用上述规则。

于 2012-08-16T21:05:28.760 回答
3

是的,最终的正则表达式实际上并不匹配任何字符。我试过这段代码:

import re

regexes = {
  "text": re.compile(r"(.+?)(?:$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F1?[1-9])\b))"),
  "kwd": re.compile(r"(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F1?[1-9])\b")
}

def tokenise(state):
  while state["src"]:
    state["tok"] = "text" if state["tok"] == "kwd" else "kwd"
    #print "mode: {0:20} {1!r}".format(state["tok"].capitalize(), state["src"])

    m = regexes[state["tok"]].match(state["src"])
    if m:
      match = m.group(0)
      state["src"] = state["src"][m.end():]
      #print "  TOKEN({0}, {1!r})".format(state["tok"], match)
      yield "TOKEN({0}, {1!r})".format(state["tok"], match)


state = {
  "src": "A thing that, Tab, is AltCps or 'Win'. F8 is good, as is: F13.",
  "tok": "text"
}
print repr(state["src"])
print "\n".join(list(tokenise(state)))
print

state = {
  "src": "Alt thing that, Tab, is AltCps or 'Win'. F8 is good, as is: F13.",
  "tok": "text"
}
print repr(state["src"])
print "\n".join(list(tokenise(state)))
print

state = {
  "src": "Alt thing that, Tab, is AltCps or 'Win'. F8 is good, as is: F11",
  "tok": "text"
}
print repr(state["src"])
print "\n".join(list(tokenise(state)))
print

它适用于我测试的案例,文本正则表达式在您的代码中看起来不错:)

于 2012-08-16T21:54:53.337 回答