Como detectar se o ponto está dentro de uma área de comentários?

15

Como detectar se o ponto está dentro de uma área de comentários?

Nome
fonte

Respostas:

19

Verifique o quarto valor * na lista retornada por syntax-ppss:

(nth 4 (syntax-ppss))

É nilse point estiver fora de qualquer comentário, tse estiver dentro de um comentário não aninhado ou um número inteiro (a profundidade do aninhamento) se estiver dentro de um comentário aninhado. Veja a documentação parse-partial-sexppara mais detalhes.

* Baseado em zero.

Observe que isso não funciona no modo Org, você deve usar isto:

(defun in-comment-p ()
  "Testy if cursor/point in a commented line?"
  (save-excursion
        (if (derived-mode-p 'org-mode)
                (save-match-data (beginning-of-line) (looking-at "^[ \t]*#"))
          (nth 4 (syntax-ppss)))))
legoscia
fonte
Perfeito, existe uma documentação para todas as outras informações que syntax-ppssfornecem?
Name
2
Sim, está na documentação para parse-partial-sexp.
27615 legoscia
2
@Name: a documentação para syntax-ppsso apontará parse-partial-sexp, o último dos quais fornecerá uma descrição de todas as coisas retornadas por essas funções. Espero que ajude para começar.
Dan
11
Consulte também a seção 34.6 "Analisando expressões" no Manual do Emacs Lisp.
Julio Nymme
7

use a fonte-face, este é o truque que aprendi com o flyspell.

Eu tentei syntax-ppsshá dois anos, ele não funciona por dois motivos:

  • não funciona na borda do comentário (limite de comentários), por exemplo, para comentários como // this is commentno modo c ++ -, se você colocar o cursor sobre o /caractere, o resultado (nth 4 (syntax-ppss))é nulo.

  • não funciona no modo principal como no modo web

Aqui está o código que eu copiei do flyspell:

(defun evilnc--in-comment-p (&optional pos)
  "Test if character at POS is comment.  If POS is nil, character at `(point)' is tested"
  (interactive)
  (unless pos (setq pos (point)))
  (let* ((fontfaces (get-text-property pos 'face)))
    (when (not (listp fontfaces))
      (setf fontfaces (list fontfaces)))
    (delq nil
          (mapcar #'(lambda (f)
                      ;; learn this trick from flyspell
                      (or (eq f 'font-lock-comment-face)
                          (eq f 'font-lock-comment-delimiter-face)))
                  fontfaces))))

Observe que o código pode ser estendido para oferecer suporte aos novos modos principais, exibindo a fonte correspondente ao fuzz.

Eu usei esse truque por cerca de três anos sem falhas. Além disso, considerando que o flyspell é amplamente utilizado por tanto tempo, eu poderia afirmar que esse método é confiável.

Consulte Qual atalho de teclado usar para navegar fora de uma sequência de caracteres para obter uma pergunta semelhante.

Chen Bin
fonte
11
Uma edição propôs outra versão que não aceita POSargumentos e usa point. Melhor do que ter duas dessas versões é tornar o arg POSopcional e configurá-lo para (point)quando nil.
Tirou