New variable comment-start-line-regexp (bug#80837)

* lisp/newcomment.el (comment-start-line-regexp): New variable
(bug#80837).
* lisp/progmodes/c-ts-common.el (c-ts-common-comment-setup):
* lisp/progmodes/cmake-ts-mode.el (cmake-ts-mode):
* lisp/progmodes/dockerfile-ts-mode.el (dockerfile-ts-mode):
* lisp/progmodes/elixir-ts-mode.el (elixir-ts-mode):
* lisp/progmodes/go-ts-mode.el (go-work-ts-mode):
* lisp/progmodes/json-ts-mode.el (json-ts-mode):
* lisp/progmodes/lua-ts-mode.el (lua-ts-mode):
* lisp/progmodes/php-ts-mode.el (php-ts-mode--comment-setup):
* lisp/progmodes/python.el (python-base-mode):
* lisp/progmodes/ruby-mode.el (ruby-base-mode):
* lisp/progmodes/sh-script.el (sh-base-mode):
* lisp/textmodes/mhtml-ts-mode.el
(mhtml-ts-mode--comment-setup):
* lisp/textmodes/toml-ts-mode.el (toml-ts-mode):
* lisp/textmodes/yaml-ts-mode.el (yaml-ts-mode): Set it.
* doc/emacs/programs.texi (Options for Comments):
* etc/NEWS: Document it.
* lisp/progmodes/c-ts-common.el
(c-ts-common-comment-start-line-regexp): New variable.
* lisp/treesit.el (newcomment): Require.
(treesit--likely-line-comment-p): New function.
(treesit-forward-comment): Use it.  Make COUNT parameter
non-optional.
This commit is contained in:
Yuan Fu 2026-07-29 12:20:33 +01:00 committed by Sean Whitton
parent c80349352f
commit 388717429c
18 changed files with 75 additions and 2 deletions

View file

@ -1385,6 +1385,12 @@ comments also. (Note that @samp{\\} is needed in Lisp syntax to
include a @samp{\} in the string, which is needed to deny the first
star its special meaning in regexp syntax. @xref{Regexp Backslash}.)
@vindex comment-start-line-regexp
Modes that support both line and block comments should also set
@code{comment-start-line-regexp} to a regexp that matches only line
comment starters. This lets Emacs distinguish between the two kinds of
comments.
@vindex comment-start
@vindex comment-end
When a comment command makes a new comment, it inserts the value of

View file

@ -305,6 +305,12 @@ buffer as if it were newly created.
+++
** The new function 'markers-in' returns the set of markers in a region.
+++
** New buffer-local variable 'comment-start-line-regexp'.
Modes that support both line and block comments should set this
variable to a regexp that matches only the start of line comments, so
Emacs can distinguish between line and block comments.
---
** New variable 'completion-frontend-properties'.
This variable generalizes the 'completion-lazy-hilit' variable added in

View file

@ -128,6 +128,19 @@ by the close of the first pair.")
;;;###autoload
(put 'comment-start-skip 'safe-local-variable 'stringp)
;;;###autoload
(defvar comment-start-line-regexp nil
"Regexp matching the start of a line comment.
Unlike `comment-start-skip', which matches the start of any comment,
this regexp matches only the start of line comments (as opposed to block
comments), so it can be used to distinguish between the two.
Modes that support both line and block comments should set this
variable.")
;;;###autoload
(put 'comment-start-line-regexp 'safe-local-variable 'stringp)
;;;###autoload
(defvar comment-end-skip nil
"Regexp to match the end of a comment plus everything back to its body.")

View file

@ -60,6 +60,11 @@
(* (syntax whitespace)))
"The `comment-start-skip' used by `c-ts-common-comment-setup'.")
(defvar c-ts-common-comment-start-line-regexp
(rx (seq "/" (+ "/"))
(* (syntax whitespace)))
"The `comment-start-line-regexp' used by `c-ts-common-comment-setup'.")
(defun c-ts-common-looking-at-star (_n _p bol &rest _)
"A tree-sitter simple indent matcher.
Matches if there is a \"*\" after BOL."
@ -287,6 +292,7 @@ Set up:
- `comment-start'
- `comment-end'
- `comment-start-skip'
- `comment-start-line-regexp'
- `comment-end-skip'
- `adaptive-fill-mode'
- `adaptive-fill-first-line-regexp'
@ -298,6 +304,7 @@ Set up:
(setq-local comment-start "// ")
(setq-local comment-end "")
(setq-local comment-start-skip c-ts-common-comment-start-skip)
(setq-local comment-start-line-regexp c-ts-common-comment-start-line-regexp)
(setq-local comment-end-skip
(rx (* (syntax whitespace))
(group (or (syntax comment-end)

View file

@ -229,6 +229,7 @@ Return nil if there is no name or if NODE is not a defun node."
(setq-local comment-start "# ")
(setq-local comment-end "")
(setq-local comment-start-skip (rx "#" (* (syntax whitespace))))
(setq-local comment-start-line-regexp comment-start-skip)
;; Defuns.
(setq-local treesit-defun-type-regexp (rx (or "function" "macro")

View file

@ -176,6 +176,7 @@ Return nil if there is no name or if NODE is not a stage node."
(setq-local comment-start "# ")
(setq-local comment-end "")
(setq-local comment-start-skip (rx "#" (* (syntax whitespace))))
(setq-local comment-start-line-regexp comment-start-skip)
;; Imenu.
(setq-local treesit-simple-imenu-settings

View file

@ -724,6 +724,7 @@ Return nil if NODE is not a defun node or doesn't have a name."
(setq-local comment-start "# ")
(setq-local comment-start-skip
(rx "#" (* (syntax whitespace))))
(setq-local comment-start-line-regexp comment-start-skip)
(setq-local comment-end "")
(setq-local comment-end-skip

View file

@ -725,6 +725,7 @@ what the parent of the node would be if it were a node."
(setq-local comment-start "// ")
(setq-local comment-end "")
(setq-local comment-start-skip (rx "//" (* (syntax whitespace))))
(setq-local comment-start-line-regexp comment-start-skip)
;; Indent.
(setq-local indent-tabs-mode t

View file

@ -198,6 +198,7 @@ PATH is a list of keys (strings) and indices (numbers)."
;; Comments.
(setq-local comment-start "// ")
(setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
(setq-local comment-start-line-regexp "//+\\s *")
(setq-local comment-end "")
;; Electric

View file

@ -683,6 +683,10 @@ Calls REPORT-FN directly."
;; Comments.
(setq-local comment-start "--")
(setq-local comment-start-skip "--\\s-*")
(setq-local comment-start-line-regexp
(rx (seq "--" (or (not (any "["))
(seq "[" (zero-or-more "=")
(not (any "=[")))))))
(setq-local comment-end "")
;; Pairs.

View file

@ -1405,6 +1405,9 @@ If FORCE is t setup comment for PHP. Depends on
(seq "/" (+ "/"))
(seq "/" (+ "*")))
(* (syntax whitespace)))
comment-start-line-regexp
(rx (or (seq "#" (or eol (not (any "["))))
(seq "/" (+ "/"))))
;; reset the state of mhtml-ts-mode--comment-setup
mhtml-ts-mode--comment-current-lang nil))
;; otherwise set comment style for other languages.

View file

@ -7358,6 +7358,7 @@ implementations: `python-mode' and `python-ts-mode'."
(setq-local comment-start "# ")
(setq-local comment-start-skip "#+\\s-*")
(setq-local comment-start-line-regexp comment-start-skip)
(setq-local parse-sexp-lookup-properties t)
(setq-local parse-sexp-ignore-comments t)

View file

@ -2693,6 +2693,7 @@ Currently there are `ruby-mode' and `ruby-ts-mode'."
(setq-local comment-end "")
(setq-local comment-column ruby-comment-column)
(setq-local comment-start-skip "#+ *")
(setq-local comment-start-line-regexp comment-start-skip)
(setq-local parse-sexp-ignore-comments t)
(setq-local parse-sexp-lookup-properties t)

View file

@ -1475,6 +1475,7 @@ implementations. Currently there are two: `sh-mode' and
(setq-local paragraph-separate (concat paragraph-start "\\|#!/"))
(setq-local comment-start "# ")
(setq-local comment-start-skip "#+[\t ]*")
(setq-local comment-start-line-regexp comment-start-skip)
(setq-local local-abbrev-table sh-mode-abbrev-table)
(setq-local comint-dynamic-complete-functions
sh-dynamic-complete-functions)

View file

@ -362,11 +362,13 @@ Return nil if there is no name or if NODE is not a defun node."
('html
(setq-local comment-start "<!-- ")
(setq-local comment-start-skip nil)
(setq-local comment-start-line-regexp nil)
(setq-local comment-end " -->")
(setq-local comment-end-skip nil))
('css
(setq-local comment-start "/*")
(setq-local comment-start-skip "/\\*+[ \t]*")
(setq-local comment-start-line-regexp nil)
(setq-local comment-end "*/")
(setq-local comment-end-skip "[ \t]*\\*+/"))
('javascript

View file

@ -146,6 +146,7 @@ Return nil if there is no name or if NODE is not a defun node."
;; Comments
(setq-local comment-start "# ")
(setq-local comment-end "")
(setq-local comment-start-line-regexp "#+ *")
;; Indent.
(setq-local treesit-simple-indent-rules toml-ts-mode--indent-rules)

View file

@ -271,6 +271,7 @@ Calls REPORT-FN directly."
(setq-local comment-start "# ")
(setq-local comment-end "")
(setq-local comment-start-skip "#+ *")
(setq-local comment-start-line-regexp comment-start-skip)
;; Indentation.
(setq-local indent-tabs-mode nil)

View file

@ -59,6 +59,7 @@
(require 'font-lock)
(require 'seq)
(require 'prog-mode) ; For `prog--text-at-point-or-region-p'.
(require 'newcomment) ; For `comment-start-line-regexp'.
;;; Function declarations
@ -3764,7 +3765,20 @@ by `text' and `sentence' in `treesit-thing-settings'."
(max (point-min) (previous-single-char-property-change
(point) 'treesit-parser)))))))
(defun treesit-forward-comment (&optional count)
(defun treesit--likely-line-comment-p (node)
"Return non-nil if NODE is likely a line comment."
(save-excursion
(goto-char (treesit-node-start node))
(if comment-start-line-regexp
(looking-at-p comment-start-line-regexp)
;; Without `comment-start-line-regexp', it's kind of best-effort.
(and comment-start
;; If `comment-end' is non-empty, `comment-start' must be
;; paired with it.
(string-empty-p (string-trim (or comment-end "")))
(looking-at-p (regexp-quote (string-trim-right comment-start)))))))
(defun treesit-forward-comment (count)
"Tree-sitter `forward-comment-function' implementation.
COUNT is the same as in `forward-comment'."
@ -3774,7 +3788,15 @@ COUNT is the same as in `forward-comment'."
(setq thing (treesit-thing-at (point) 'comment))
(if (and thing (eq (point) (treesit-node-start thing)))
(progn
(goto-char (min (1+ (treesit-node-end thing)) (point-max)))
(goto-char (treesit-node-end thing))
;; For line comments, go to the next line. This is
;; important because a) for navigation convenience, and b)
;; many functions expect `forward-comment' to behave this
;; way (bug#80837).
(when (treesit--likely-line-comment-p thing)
(skip-chars-forward " \t")
(when (looking-at-p "\n")
(forward-char)))
(setq count (1- count)))
(setq count 0 res nil)))
(while (< count 0)