一千萬個為什麽

搜索

編譯模式難題 - 匹配和突出顯示

在使用編譯模式進行運行測試並使用HIGHLIGHT面向失敗的期望時,我遇到了一些難題。

Question: why does my compilation-errors-regexp-alist fail to match when the matching group/s are preceded by more than a certain number of characters. And how best to mitigate this given my matching requirements.

讓我試試吧。

我正在使用2017-01-14的 GNU Emacs 25.1.1(x86_64-pc-linux-gnu,GTK +版本3.18.9)

這是一些重現問題的最小代碼:

(defface face-frame
  '((t :foreground "white" :background "black" :weight bold)) "frames out for a failing test")

(defface face-wrong
  '((t :foreground "white" :background "darkred" :weight bold)) "highlight incorrect output in red")

(defface face-expected
  '((t :foreground "white" :background "darkgreen" :weight bold)) "show expected output in green")

(defconst error-regexp-alist
  '(("^Received\n\\(\\(.\\|\n\\)+?\\)\nExpected\n\\(\\(.\\|\n\\)+?\\)\n\\(.*\\):\\([[:digit:]]+\\)\n--$"
     5 6 nil nil nil (0 'face-frame) (1 'face-wrong) (3 'face-expected))))

(define-derived-mode weird-compilation-mode compilation-mode "Fixture Compilation"
  (set (make-local-variable 'compilation-error-regexp-alist)
       error-regexp-alist))

(defun demonstrate-weirdness ()
  (interactive)
  (with-current-buffer (get-buffer-create "*weird-regexp-matching-issue*")
    (compilation-start "./fixture.sh" 'weird-compilation-mode (lambda (m) (buffer-name)))
    ))

重現:

compilation-mode 緩沖區應該與 fixture.sh 的輸出一起出現,它產生要匹配的測試輸出。

all-good

對我來說很好看,這就是我想要的;輸出收到錯誤突出顯示為紅色,預期輸出突出顯示為綠色,兩種錯誤情況

BUT, add a single addition 1 (or any other character) to the start of fixture.sh (after the cat << HERE of course) then switch back to the *weird-regexp-matching-issue* buffer and hit g to (recompile)

boo-hoo

我設計了regexp來將 ReceivedExpected 之間的所有內容分組,包括新行,以及類似 Expectedfile:line </代碼>信息:

^Received\n\\(\\(.\\|\n\\)+?\\)\nExpected\n\\(\\(.\\|\n\\)+?\\)\n\\(.*\\):\\([[:digit:]]+\\)\n--$

Note: it's a shame Emacs doesn't support lookbehind and lookahead facilities as it would have made things easier...

它似乎在 compilation-mode 的上下文之外工作正常。我已經使用各種輸入字符串通過 regex-toolhelm-regex ,並使用(s-match ...)來測試它檢查我自己的理智。

正則表達式可以這樣結束......

Why is the matching and highlighting failing when the "preamble" output is extended beyond a certain length?

也許有更多使用Emacs正則表達式或編譯模式內部經驗的人可以幫助我。希望代碼+示例能夠幫助將來使用 compilation-mode 找到類似船只的其他人。

最佳答案

我認為這是正在發生的事情:

shell命令產生輸出,同時compile.el希望使用regexp列表將字體鎖屬性放在其上。但是,它應該如何知道,是否已生成足夠的文本以滿足所有正則表達式的要求?例如,可能有一個匹配緩沖區的起始結尾,如果完整輸出將立即匹配,則只能成功。但這不是compile.el的運作方式:它使用font-lock,它在到達時批量解析輸出。

這同樣適用於您的測試用例,盡管方式不太嚴格。如果我們使用 trace-function-background 跟蹤函數 compilation - ensure-parse ,我們可以看到發生了什麽。當應用於錯誤情況時(添加1),這是部分結果。

======================================================================
1 -> (compilation--ensure-parse 184)
1 <- compilation--ensure-parse: nil
======================================================================
1 -> (compilation--ensure-parse 684)
1 <- compilation--ensure-parse: nil
======================================================================

檢查編譯緩沖區中的位置684,我們看到它對應於該子字符串的開頭。

/path/to/test:1234
--

很明顯,為什麽這不起作用:你的正則表達式要求文本以雙連字符結​​尾,但字體鎖定只停止了第一次出現此字符串的兩行,所以輸出的第一部分不匹配。

您可以做的是確保在生成所有命令輸出後緩沖區得到重新解析,例如,如下面的代碼所示。

(defun compilation-reparse-buffer (&rest _ignored)
  (interactive)
  (compilation--flush-parse (point-min) (point-max))
  (compilation--ensure-parse (point-max)))

(add-hook 'weird-compilation-mode-hook
          (lambda nil
            (add-hook 'compilation-finish-functions #'compilation-reparse-buffer nil t)))

轉載註明原文: 編譯模式難題 - 匹配和突出顯示