Comment détecter si le point se trouve dans une zone de commentaire?

15

Comment détecter si le point se trouve dans une zone de commentaire?

Nom
la source

Réponses:

19

Vérifiez la quatrième valeur * dans la liste renvoyée par syntax-ppss:

(nth 4 (syntax-ppss))

C'est nilsi le point est en dehors de tout commentaire, ts'il est à l'intérieur d'un commentaire non imbriqué, ou un entier (la profondeur d'imbrication) s'il est à l'intérieur d'un commentaire emboîtable. Voir la docstring parse-partial-sexppour plus de détails.

* Basé sur zéro.

Notez que cela ne fonctionne pas avec le mode Org, vous devez utiliser ceci:

(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
la source
Parfait, existe-t-il une documentation pour toutes les autres informations syntax-ppssfournies?
Nom du
2
Oui, c'est dans la docstring pour parse-partial-sexp.
legoscia
2
@Name: la docstring pour syntax-ppssvous indiquera parse-partial-sexp, ce dernier vous donnera une description de toutes les choses retournées par ces fonctions. J'espère que cela vous aidera pour commencer.
Dan
1
Voir aussi la section 34.6 «Analyser les expressions» dans le manuel Emacs Lisp.
Sue D. Nymme
7

utiliser la police, c'est l'astuce que j'ai apprise de flyspell.

J'ai essayé syntax-ppssil y a deux ans, ça ne marche pas pour deux raisons:

  • ne fonctionne pas sur le bord du commentaire (limite de commentaire), par exemple, pour un commentaire comme // this is commenten mode c ++ -, si vous placez le curseur sur le /caractère, le résultat de (nth 4 (syntax-ppss))est nul.

  • ne fonctionne pas du tout en mode majeur comme le mode web

Voici le code que j'ai 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))))

Veuillez noter que le code pourrait être étendu pour prendre en charge de nouveaux modes principaux en faisant correspondre la face de la police.

J'utilise cette astuce depuis environ trois ans sans échec. De plus, étant donné que flyspell est largement utilisé depuis si longtemps, je pourrais affirmer que cette méthode est fiable.

Voir Quel raccourci clavier utiliser pour naviguer hors d'une chaîne pour une question similaire.

chen bin
la source
1
Une modification a proposé une autre version qui ne prend aucun POSargument et utilise point. Mieux que d'avoir deux de ces versions est de rendre arg POSoptionnel et de le mettre à (point)quand nil.
Drew