我正在尝试突出一堆词 - 所以我写了一个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),
]
}
可能我应该更好地使用另一个词法分析器来完成这项工作?
所以
r"(.+?)(?:$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F[12]?[1-9])\b))"
是我一直在寻找的exlusing正则表达式。
现在我正在努力使#
成为一个评论字符 - 所以它之后的所有内容(在一行内)都是评论:我试过了:
r"(.+?)(?:$|#.*$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F[12]?[1-9])\b))"
和
r"([^#]+?)(?:$|\b(?=(Alt|Shft|Spc|Ctrl|Ret|BkSpc|Tab|CpsLk|NmLk|ScrlLk|PgUp|PgDwn|Home|End|Del|Ins|Win|F[12]?[1-9])\b))"
接着是
(r'#.*$', Comment),
我也试过添加第二个状态:
'comment': [
(r'#.*$', Comment),
],
- 但没有任何作用。
complite working pygments扩展python包是here。你可以得到
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}。
答案 0 :(得分:4)
1)你误解了(?!
的工作原理:它与文本不匹配。您的最后一个RE(在原始代码块中)匹配位置,后面没有您列出的任何单词。但是它匹配文本的零个字符,所以没有什么可以着色,你也不会前进。
你真正的意思是:\b(?!(?:Alt|Shft|etc)\b)\w+\b
。 (在\w+
之间匹配任何单词\b
,但如果第一个\b
后跟任何关键字,则不会匹配
2)关于匹配评论:根据pygments文档,您的表达式(r'#.*$', Comment)
应该有效。或者,以示例中使用的样式:
(r'#.*\n', Comment),
3)您只需要一个州,因此将评论规则添加到根状态。多个状态适用于在不同位置使用不同语法的情况,例如:如果你有混合的html和PHP,或者你想在python字符串中突出显示SQL。
4)您的规则需要匹配输入中的所有。规则是按顺序尝试的,直到一个工作,因此您可以将此通配符作为最后规则,而不是尝试编写与关键字不匹配的规则:
(r'(?s).', Text),
它会一次前进一个角色,直到你得到其他规则可以匹配的内容。要重复:删除与非关键字匹配的长规则,并改为使用上述规则。
答案 1 :(得分: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
它适用于我测试的案例,文本正则表达式在您的代码中看起来很好:)