¿Cómo detectar si el punto está dentro de un área de comentarios?

15

¿Cómo detectar si el punto está dentro de un área de comentarios?

Nombre
fuente

Respuestas:

19

Verifique el cuarto * valor en la lista devuelta por syntax-ppss:

(nth 4 (syntax-ppss))

Es nilsi el punto está fuera de cualquier comentario, tsi está dentro de un comentario no anidable, o un número entero (la profundidad de anidación) si está dentro de un comentario anidable. Vea la cadena de documentación parse-partial-sexppara más detalles.

* Basado en cero.

Tenga en cuenta que esto no funciona con el modo Org, debe usar esto:

(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
fuente
Perfecto, ¿hay alguna documentación para toda la otra información que syntax-ppssproporciona?
Nombre
2
Sí, está en la cadena de documentación para parse-partial-sexp.
legoscia
2
@Name: el docstring para lo syntax-ppssseñalará parse-partial-sexp, el último de los cuales le dará una descripción de todas las cosas devueltas por estas funciones. Esperemos que eso ayude para empezar.
Dan
1
Consulte también la sección 34.6 "Análisis de expresiones" en el Manual Emacs Lisp.
Sue D. Nymme
7

usa la fuente, este es el truco que aprendí de flyspell.

Lo intenté hace syntax-ppssdos años, no funciona por dos razones:

  • no funciona en el borde del comentario (límite de comentario), por ejemplo, para comentarios como // this is commenten el modo c ++, si coloca el cursor sobre el /carácter, el resultado de (nth 4 (syntax-ppss))es nulo.

  • no funciona en absoluto en modo mayor como el modo web

Aquí está el código que copié de 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))))

Tenga en cuenta que el código podría ampliarse para admitir nuevos modos principales mediante la coincidencia fuzz de la fuente.

He usado este truco durante unos tres años sin fallar. Además, teniendo en cuenta que el flyspell se usa ampliamente durante tanto tiempo, podría afirmar que este método es confiable.

Consulte Qué método abreviado de teclado usar para navegar fuera de una cadena para una pregunta similar.

Chen Bin
fuente
1
Una edición propuso otra versión que no requiere POSargumentos ni usos point. Mejor que tener dos de esas versiones es hacer que arg sea POSopcional y configurarlo (point)cuando nil.
Dibujó el