Как добавить сложную подсветку синтаксиса в второстепенном режиме?

10

Я хотел бы выделить код с различными лицами в второстепенном режиме.

Вот скриншот, который близок к тому, что я хочу:

питон-синтаксически выделить

Одна вещь , которую я пропускаю это имеющий свой комментарий символов #в font-lock-comment-face. Идея состоит в том, чтобы комментарии, которые «принадлежат» к схеме, выделены в виде простого текста, чтобы их было легче читать. Имея регулярные комментарии со своим обычно менее заметным лицом.

Вот код, который я использовал:

(setq-local font-lock-defaults
            '(python-font-lock-keywords
              nil nil nil nil
              (font-lock-syntactic-face-function
               . lpy-font-lock-syntactic-face-function)))

(defun lpy-font-lock-syntactic-face-function (state)
  "Return syntactic face given STATE.
Returns 'defalt face for comments that belong to an outline."
  (cond ((nth 3 state)
         (if (python-info-docstring-p state)
             font-lock-doc-face
           font-lock-string-face))
        ((save-excursion
           (while (and (> (point) (point-min))
                       (progn (move-beginning-of-line 0)
                              (eq (char-after) ?\#))))
           (forward-line 1)
           (looking-at "#\\*+ "))
         'default)
        (t
         font-lock-comment-face)))

Дело в том, что я понятия не имею об интерфейсе, на котором font-lock-syntactic-face-functionработает, кроме того, что он получает сложную структуру данных state, имеет другое состояние точки и возвращает лицо.

Может ли кто-нибудь объяснить этот интерфейс? Возможно, есть лучший?

Або-або
источник

Ответы:

6

font-lock-syntactic-face-functionобычная переменная из Font Lock, более конкретно из фазы Syntactic Font Lock (выделено мной):

Если эта переменная не ноль, она должна быть функцией, чтобы определить, какое лицо использовать для данного синтаксического элемента (строки или комментария). Значение обычно устанавливается через элемент other-vars в font-lock-defaults.

Функция вызывается с одним аргументом, состоянием анализа в точке, возвращаемой parse-partial-sexp, и должна возвращать грань . Значение по умолчанию возвращает font-lock-comment-face для комментариев и font-lock-string-face для строк (см. Faces для Font Lock).

parse-partial-sexpв свою очередь возвращает список, который описывает текущее синтаксическое состояние Emacs, которое по сути является результатом применения таблицы синтаксиса к текущему буферу. Список довольно сложный, поэтому я пощадлю его здесь; Вы можете увидеть полную ссылку в документации parse-partial-sexp. Цель этой функции - изменить грань, примененную к синтаксическому элементу в соответствии с определенными правилами. Начало вашей функции демонстрирует это: если текущая строка является строкой документации, используйте для нее другое лицо.

Тем не менее, лицо всегда применяется ко всему синтаксическому элементу, то есть всей строке или комментарию. Вы не можете выделить отдельные части с помощью этой функции, и вы должны смотреть только на данные stateдля этой цели - как это (python-info-docstring-p state)делается в вашем коде. Вы не использовать точку в этом месте; Я даже не уверен, правильно ли определено значение pointна этом этапе блокировки шрифтов.


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

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

Если я прав, то вам просто нужно font-lock-keywordsособым образом, а именно:

(my/find-outline-in-comment-p 0 'outline-face t)

где outline-faceлицо, которое вы хотели бы применить к заголовку, tозначает переопределение любой предыдущей блокировки шрифтов в этом месте и my/find-outline-in-commentявляется функцией сопоставления (см. строку документации font-lock-defaults), которая занимает позицию и ищет первый контур в комментарии. между (point)и этой позицией, возвращая экстенты контура, который будет выделен в данных соответствия.

Чтобы найти схему, вам нужно отсканировать комментарии (используя font-lock-comment-faceили синтаксическое состояние), а затем использовать, looking-atчтобы проверить, есть ли у комментария схема.

lunaryorn
источник
1

Рассмотрим определение font-lock-syntactic-face-functionтак:

(setq font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state))
            MY-COMMENT-FACE
          (t  font-lock-comment-face))))

Это было проверено с python-mode.el, оставив раздел, начинающийся с "# *" без комментария:

(setq py--font-lock-syntactic-face-function
      (lambda (state)
    (cond ((nth 3 state)
           font-lock-string-face)
          ((and (nth 4 state)(nth 8 state)
            (progn (save-excursion
                 (goto-char (nth 8 state))
                 (looking-at (concat comment-start (regexp-quote "*"))))))
           nil)
          (t font-lock-comment-face))))

Пока он администрируется в режиме:

(font-lock-syntactic-face-function
                    . py--font-lock-syntactic-face-function)

Вместо этого nil, любое действительное лицо должно работать.

Андреас Рёлер
источник