15

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

19

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)))))
  • Perfect, is there a documentation for all other information thatsyntax-ppss provides? – Name Jul 27 '15 at 12:55
  • 2
    Yes, it's in the docstring for parse-partial-sexp. – legoscia Jul 27 '15 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 Jul 27 '15 at 13:01
  • 1
    See also section 34.6 "Parsing Expressions" in the Emacs Lisp Manual. – Sue D. Nymme Jul 27 '15 at 13:43
8

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

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
    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 Mar 11 at 3:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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