Регулярное выражение режима компиляции Emacs для нескольких строк - PullRequest
2 голосов
/ 28 июня 2011

Итак, у меня есть инструмент, который помечает изменения Python, которые я сделал, и выдает ошибки и предупреждения.Я хотел бы, чтобы это можно было использовать в режиме компиляции с Emacs, но у меня есть проблема.Имя файла выводится только один раз в начале, а затем появляются только номера строк с ошибками и предупреждениями.Вот пример:

Linting file.py
E0602: 37: Undefined variable 'foo'
C6003: 42: Unnecessary parens after 'print' keyword
2 new errors, 2 total errors in file.py.

Это очень похоже на pylint, но нет опции output-format = parseable.Я проверил документацию на compilation-error-regexp-alist и обнаружил что-то многообещающее:

Если FILE, LINE или COLUMN равны нулю или этот индекс не совпадает, то
информация неприсутствует на согласованной линии.В этом случае предполагается, что имя файла
совпадает с предыдущим в буфере
, номер строки по умолчанию равен 1, а столбец по умолчанию равен
начало отступа строки.

Итак, я попытался написать регулярное выражение, которое могло бы соответствовать строке файла и вытащить его в группу, а затем остальные соответствовали бы другим строкам.Я предполагал, что сначала он будет соответствовать

Linting file.py
E0602: 37: Undefined variable 'foo'

и будет в порядке.Тогда это продолжится и будет соответствовать

C6003: 42: Unnecessary parens after 'print' keyword

без файла.Поскольку файла не было, он должен использовать имя файла из предыдущего совпадения, верно?Вот регулярное выражение, которое я использую:

(add-to-list 'compilation-error-regexp-alist 'special-lint)
(add-to-list 'compilation-error-regexp-alist-alist
         '(special-lint
           "\\(Linting \\(.*\\)\\n\\)?\\([[:upper:]][[:digit:]]+:\\s-+\\([[:digit:]]\\)+\\).*"
           2 4 nil nil 3))

Я проверил его с помощью пересборки и вручную в чистом буфере.Он ведет себя как ожидалось.2-я группа - это имя файла, 4-я - номер строки, а 3-я - это то, что я хочу выделить.Всякий раз, когда я пытаюсь это сделать, я получаю сообщение об ошибке:

signal(error ("No match 2 in highlight (2 compilation-error-face)"))

У меня есть обходной путь для этого, который включает преобразование вывода до того, как модуль компиляции смотрит на него, но я бы предпочел избавиться от этого и иметь«чистое» решение.Буду признателен за любой совет или за указание на любые глупые ошибки, которые я мог совершить.

РЕДАКТИРОВАТЬ

Псевдокод Томаса, приведенный ниже, работал довольно хорошо.Он упомянул, что обратный поиск может испортить данные о совпадении, и это произошло.Но это было решено добавлением специальной формы save-match-data перед save-excursion.

Ответы [ 2 ]

3 голосов
/ 28 июня 2011

ФАЙЛ также может иметь форму (ФАЙЛ ФОРМАТ ...), где ФОРМАТЫ (например, "% s.c") будет применен по очереди к распознанное имя файла, пока файл это имя найдено. Или ФАЙЛ может также быть функцией, которая возвращает (FILENAME) или (RELATIVE-FILENAME. DIRNAME). В В первом случае FILENAME может быть относительный или абсолютный.

Вы можете попытаться написать регулярное выражение, которое вообще не соответствует имени файла, только столбец. Затем для файла напишите функцию, которая ищет файл в обратном направлении. Возможно, это не так эффективно, но у него должно быть то преимущество, что вы можете перемещаться вверх по сообщениям об ошибках, и оно все равно будет определять правильный файл, когда вы пересекаете границы файла.

У меня не установлено необходимых вещей, чтобы попробовать это, но я беру в качестве вдохновения следующий псевдокод:

(add-to-list 'compilation-error-regexp-alist-alist
         '(special-lint
           "^\\S-+\\s-+\\([0-9]+\\):.*" ;; is .* necessary?
           'special-lint-backward-search-filename 1))

(defun special-lint-backward-search-filename ()
  (save-excursion
    (when (re-search-backward "^Linting \\(.*\\)$" (point-min) t) 
      (list (match-string 1)))))

(Возможно, использование функции поиска внутри special-lint-backward-search-filename приведет к нарушению соответствия подгруппы compilation-error-regexp, что может быть отстой.)

0 голосов
/ 28 июня 2011

Я не думаю, что вы можете заставить компиляцию делать то, что вам нужно, потому что она не будет предполагать, что последующая ошибка относится к ранее увиденному имени файла.Но вот альтернатива;написать flymake плагин.Flymake всегда работает с текущим файлом, поэтому вам нужно только указать ему, как найти номера строк (и, необязательно, столбцов).

Попробуйте взломать что-то вроде этого , и выскорее всего, будет приятно удивлен.

...