2012-08-16 103 views
1

我試圖強調一堆詞 - 所以我寫了一個pygments擴展。基本上它有效,但仍然不令我滿意。突出顯示一堆單詞?

下面是一個應該起作用的簡單概念:適當地突出顯示單詞,以及所有其他與這些單詞不匹配的文本 - 在文本中。但是,這hungs起來:

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))" 

是exlusing正則表達式我一直在尋找。

現在,我試圖讓#評論焦 - 這樣經過它的一切(行內) - 是一個註釋:我已經試過:

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

的complite工作Pygments來做擴展蟒包是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

是否有正則表達式匹配至少一個字符?也許問題是最後一個正則表達式匹配一個空字符串,所以沒有字符被「消耗」,並且它永遠不會前進。 – MRAB 2012-08-16 15:24:18

+0

也許你rihgt。其實我認爲 - 最後一個正則表達式必須匹配(|)指定的單詞。我會檢查它是否匹配空字符串。 – Adobe 2012-08-16 16:19:43

+0

真的,我的意思是,因爲「(?!...)」是一個負向預測,它永遠不會消耗任何字符。 – MRAB 2012-08-16 16:23:36

回答

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 

和它的作品我爲我測試的情況下,文本的正則表達式看起來不錯,在你的代碼:)

+0

哇..'R「(!(+?):??$ | \ B(=(Alt鍵| SHFT | SPC | CTRL |懲戒| BkSpc |標籤| CpsLk | NmLk鍵| ScrlLk | PgUp鍵| PgDwn |首頁| End | Del | Ins | Win | F [12]?[1-9])\ b))「'有效。我知道你擅長於pygments(我可以閱讀文檔,但是可以很好地理解'state'的含義,但是我明白,在文章中必須包含所有文字)。 – Adobe 2012-08-17 10:33:05

+0

'state'基本上只是爲了跟蹤a)剩餘的解析和b)我們接下來尋找哪種類型的令牌 - 這個例子應該總是在匹配一個'text'令牌和一個'kwd'令牌之間交替。 – spiralx 2012-08-21 13:29:17

+0

您認爲有評論空間嗎?(#。* $ | \ b(?=(Alt | Shft | Spc | Ctrl | Ret)我試圖做'#'註釋char:我試過:'r「 | BkSpc | Tab | CpsLk | NmLk | ScrlLk | PgUp | PgDwn | Home | End | Del | Ins | Win | F [12]?[1-9])\ b))「'和'r」 ?^#] +)(?:?$ | \ b(=(Alt鍵| SHFT | SPC | CTRL |懲戒| BkSpc |標籤| CpsLk | NmLk鍵| ScrlLk | PgUp鍵| PgDwn |首頁|尾頁|德爾|宏| Win | F [12]?[1-9])\ b))「'後面跟着'(r'#。* $',Comment),',我也嘗試添加第二個狀態:''comment ':[ (r'#。* $',評論), ], - 但沒有任何作用。 – Adobe 2012-10-15 09:56:24

4

1)您誤會了(?!的工作原理:它與文本不匹配。您的最後一個RE(在原始代碼塊中)與的位置相匹配,但沒有列出您列出的任何單詞。但它匹配文字的零個字符,所以沒有顏色,而且你也不能前進。

你的意思是這樣的:\b(?!(?:Alt|Shft|etc)\b)\w+\b。基於Pygments來做文檔,你的表達(r'#.*$', Comment)應該工作:(匹配任何字S \w+\b之間,但如果第一\b之後的任何關鍵字)

2)關於匹配的評論。或者,在示例中使用的風格:

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

3)你只需要一個狀態,所以添加註釋規則到根狀態。當您在不同地方使用不同的語法時,可以使用多種狀態。如果你混合了html和PHP,或者你想突出顯示python字符串中的SQL。

4)你的規則需要匹配一切在你的輸入。規則試圖爲了直到一個作品,所以不是想寫不匹配關鍵字的規則,你可以把這個通配符作爲您的最後規則:

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

它將在前進一個字符直到你找到你的其他規則可以匹配的東西。重複:刪除您的長規則匹配非關鍵字,並使用上述代替。

+0

你的權利'('不匹配文本'\ B((?:Alt鍵| SHFT |等)\ B)\ w + \ B'是一個很好的手藝 - 但它留下空格和標點符號無與倫比。改變'\ w'爲'.'會破壞事情。我讀過的任何方式你回答了幾次,已經讀過關於不捕獲的內容(:??',並且我感謝你的回答。 – Adobe 2012-08-17 10:29:51

+0

當然它忽略了空格和標點符號,因爲你所有的代碼是基於標記的。既然你已經得到了你在對方的回答喜歡的節目,我不會問你想搭配什麼。 – alexis 2012-08-19 19:26:29

+0

(但見編輯答案) – alexis 2012-10-22 21:41:25