Выделите кучу слов?
Я пытаюсь выделить кучу слов - поэтому я написал расширение 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|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"([^#]+?)(?:$|\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),
],
- но ничего не работает.
Редактировать 2
Полный пакет Python для расширения рабочих фрагментов находится здесь. Вы можете получить и
python setup.py build
python setup.py install --user
это зарегистрировать это в фрагментах. Затем вы можете проверить это с:
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).
2 ответа
Да, последнее регулярное выражение не соответствует ни одному из символов. Я попробовал этот код:
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
И это работает я для случаев, которые я тестировал, регулярное выражение текста выглядит хорошо в вашем коде:)
1) Вы неправильно понимаете, как (?!
работает: не соответствует тексту. Ваш последний RE (в исходном блоке кода) соответствует позиции, за которой не следует ни одно из перечисленных вами слов. Но он соответствует нулю символов текста, так что нечего раскрашивать, и вы не двигаетесь вперед.
То, что вы действительно имели в виду, это: \b(?!(?:Alt|Shft|etc)\b)\w+\b
, (Подберите любое слово \w+
между \b
с, но не если первый \b
сопровождается любым из ключевых слов)
2) О соответствующих комментариях: на основе документации по фрагментам, ваше выражение (r'#.*$', Comment)
должен работать. Или в стиле, использованном в примерах:
(r'#.*\n', Comment),
3) Вам нужно только одно состояние, поэтому добавьте правило комментария в корневое состояние. Несколько состояний предназначены для случаев, когда у вас разный синтаксис в разных местах, например, если вы смешали html и PHP, или если вы хотите выделить SQL внутри строки Python.
4) Ваши правила должны соответствовать всему, что вы вводите. Правила пробуются по порядку до тех пор, пока одно из них не работает, поэтому вместо того, чтобы пытаться написать правило, которое не соответствует ключевым словам, вы можете поместить этот шаблон в качестве последнего правила:
(r'(?s).', Text),
Он будет продвигаться по одному персонажу за раз, пока вы не достигнете того, что могут соответствовать ваши другие правила. Повторим: удалите длинное правило, которое соответствует не-ключевым словам, и используйте вместо этого выше.