Como adicionar realce de sintaxe complexo em um modo menor?

10

Eu gostaria de destacar o código com várias faces em um modo menor.

Aqui está uma captura de tela próxima ao que eu quero:

python-sintaxe-destaque

Uma coisa que estou perdendo é ter os comentários #em destaque font-lock-comment-face. A idéia é ter comentários que "pertençam" a um esboço destacado como texto simples, para facilitar a leitura. Enquanto faz comentários regulares com o rosto menos proeminente de sempre.

Aqui está o código que eu usei:

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

O problema é que não tenho idéia da interface na qual font-lock-syntactic-face-functionopera, exceto por receber uma estrutura de dados complexa state, ter um estado de ponto diferente e retornar uma face.

Alguém poderia explicar essa interface? Existe um melhor talvez?

abo-abo
fonte

Respostas:

6

font-lock-syntactic-face-functioné uma variável regular do Font Lock, mais especificamente da fase Syntactic Font Lock (ênfase minha):

Se essa variável for nula, deve ser uma função determinar qual face usar para um determinado elemento sintático (uma sequência ou comentário). O valor é normalmente definido por meio de um elemento other-vars em font-lock-defaults.

A função é chamada com um argumento, o estado de análise no ponto retornado por parse-partial-sexpe deve retornar uma face . O valor padrão retorna font-lock-comment-face para comentários e font-lock-comment-face para strings (consulte Faces para bloqueio de fonte).

parse-partial-sexppor sua vez, retorna uma lista que descreve o estado sintático atual do Emacs, que é essencialmente o resultado da aplicação da tabela de sintaxe ao buffer atual. A lista é bastante complexa, portanto, eu a pouparei aqui; você pode ver a referência completa na documentação de parse-partial-sexp. O objetivo desta função é alterar a face aplicada a um elemento sintático sob certas regras. O início da sua função demonstra o seguinte: Se a string atual for uma docstring, use uma face diferente para ela.

No entanto, a face sempre se aplica a todo o elemento sintático, ou seja, a toda a cadeia ou comentário. Você não pode destacar partes individuais com esta função e deve apenas observar o que é fornecido statepara esse fim - como (python-info-docstring-p state)no seu código. Você não usar o ponto neste lugar; Eu nem tenho certeza se o valor de pointestá definido corretamente nesse estágio de bloqueio de fonte.


Ao juntar as peças, você está usando a função errada para o seu propósito, e é por isso que não pode fazê-la funcionar.

Não tentei implementar o realce desejado, mas acho que você cavou demais, profundo demais para o seu propósito. Se eu entender as coisas corretamente, você gostaria de destacar os contornos em um comentário.

Se eu estiver certo, então você só precisa font-lock-keywordsde uma maneira especial, a saber:

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

onde outline-faceé o rosto que você deseja aplicar ao título, tsignifica substituir qualquer bloqueio de fonte anterior neste local e my/find-outline-in-commenté uma função de correspondência (consulte a documentação de font-lock-defaults) que assume uma posição e procura o primeiro esboço em um comentário entre (point)e nessa posição, retornando as extensões do contorno a serem destacadas nos dados da correspondência.

Para encontrar o esboço, você deve procurar comentários (usando font-lock-comment-faceou o estado sintático) e depois usa looking-atpara verificar se o comentário tem um esboço.

lunaryorn
fonte
1

Considere definir font-lock-syntactic-face-functionassim:

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

Isso foi testado com python-mode.el, deixando uma seção começando com "# *" sem a cara do comentário:

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

Enquanto é administrado com o modo:

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

Em vez de nil, qualquer rosto válido deve funcionar.

Andreas Röhler
fonte