Неизвестное количество совпадений в регулярных выражениях и font-lock - PullRequest
1 голос
/ 25 мая 2011

Я пытаюсь использовать font-lock и регулярное выражение elisp, чтобы выделить что-то вроде этого:

class Foo implements A, B, C, D { }

Проблема заключается в неизвестной длине списка через запятую после implements.Я уже сделал регулярное выражение, которое выделяет все слова в списке (используя re-buider, выделены A, B, C и D):

"implements\\s-+\\(?:\\(\\sw+\\)\\s-*,\\s-*\\)*\\(\\sw+\\)"

, но я не могу объединить это с font-lock,

Очевидно,

'("implements\\s-+\\(?:\\(\\sw+\\)\\s-*,\\s-*\\)*\\(\\sw+\\)"
  (1 font-lock-type-face) (2 font-lock-type-face))

не работает, потому что он подсвечивается только последним вхождениям (C и D), игнорируя звезду (*) после первой обратной ссылки.

Есть ли способ получить список всех подходящих слов или, может быть, совершенно другой способ решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 30 мая 2011

Если вы не хотите, чтобы запятые тоже выделялись, ваш подход не сработает. Когда вы используете subexp-highlighter вида

(subexp facespec)

subexp относится к подгруппе вашего регулярного выражения и выделяется с данным facespec. Теперь подгруппа соответствия регулярному выражению представляет собой непрерывный промежуток текста с началом и концом. Фактически, всякий раз, когда вы выполняете поиск по регулярному выражению, вы можете запрашивать эти значения с помощью функций (match-beginning subexp) и (match-end subexp).

Но это означает, что вы не можете сопоставить переменное число имен классов, исключая запятые, с одним подвыражением, потому что это подвыражение должно быть непрерывным диапазоном. И непрерывный промежуток, который охватывает переменное число имен классов, всегда должен содержать запятые, и нет никакого способа обойти это.

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

Рассмотрим следующую строку кода:

class Foo implements A, /*B, C,*/ D { }

В этом случае вы бы хотели, чтобы символы в диапазоне /*B, C,*/ были выделены с помощью font-lock-comment-face, а окружающие классы - в font-lock-type-face. Вы все еще можете добиться этого эффекта, если выделите комментарии только после того, как все остальное уже выделено, и разрешите комментариям переопределять другие совпадения блокировки шрифтов. Но это приведет к довольно неэффективному сопоставлению, потому что каждый комментарий будет сначала выделен, как если бы он был кодом, а затем выделен как комментарий во втором проходе.

Решением обеих проблем, вероятно, было бы разделение соответствия ключевых слов («инструментов») и классов на два разных правила соответствия, возможно, вы могли бы использовать в качестве отправной точки что-то вроде:

'(("\\bimplements\\b" . font-lock-keyword-face)
  ("\\b[A-Z]\\w*\\b" . font-lock-type-face))
1 голос
/ 26 мая 2011

Кажется, что-то вроде этого работает здесь:

'("\\(implements\\)\\s-+\\(\\(\\sw+\\s-*,\\s-*\\)*\\sw+\\)"
   (1 font-lock-warning-face)
   (2 font-lock-keyword-face))

(и, очевидно, вы, вероятно, хотите разные лица ...)

...