19

How to detect if the point is within a comment area?

2 Answers 2

20

Check the fourth* value in the list returned by syntax-ppss:

(nth 4 (syntax-ppss))

It's nil if point is outside any comment, t if inside a non-nestable comment, or an integer (the nesting depth) if inside a nestable comment. See the docstring for parse-partial-sexp for more details.

* Zero-based.

Note that this doesn't work with Org-mode, you should use this:

(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)))))
4
  • Perfect, is there a documentation for all other information thatsyntax-ppss provides?
    – Name
    Commented Jul 27, 2015 at 12:55
  • 2
    Yes, it's in the docstring for parse-partial-sexp.
    – legoscia
    Commented Jul 27, 2015 at 12:59
  • 2
    @Name: the docstring for syntax-ppss will point you to parse-partial-sexp, the latter of which will give you a description of all of the stuff returned by these functions. Hopefully that helps for a start.
    – Dan
    Commented Jul 27, 2015 at 13:01
  • 1
    See also section 34.6 "Parsing Expressions" in the Emacs Lisp Manual. Commented Jul 27, 2015 at 13:43
9

use the font-face, this is the trick I learned from flyspell.

I tried syntax-ppss two years ago, it does not work for two reason:

  • not work on edge of comment (comment limit), for example, for comment like // this is comment in c++-mode, if you place the cursor over the / character, the result of (nth 4 (syntax-ppss)) is nil.

  • not work at all in major-mode like web-mode

Here is code I copied from 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)))
    (or (member 'font-lock-comment-face fontfaces)
        (member 'font-lock-comment-delimiter-face fontfaces))))

Please note the code could be extended to support new major modes by fuzz matching font face.

I've used this trick for about three years without failure. Besides, considering flyspell is widely used for so long, I could claim this method is reliable.

See Which keyboard shortcut to use for navigating out of a string for similar question.

1
  • 1
    An edit proposed another version that takes no POS arg and uses point. Better than having two such versions is to make arg POS optional and set it to (point) when nil.
    – Drew
    Commented Mar 11, 2019 at 3:39

Not the answer you're looking for? Browse other questions tagged or ask your own question.