From 28dd60213846a04d3f8c4006bd4ec252bd883ed0 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Mon, 9 Jan 2023 01:44:44 -0800 Subject: [PATCH] Fix c-ts-mode indentation for 2nd line in block comment (bug#60270) If the first line is "/*" or "/* ", indent like this: /* aaa If the first line is "/* some text", indent like this: /* some text aaa * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): (c-ts-mode--looking-at-star): Minor refactor. (c-ts-mode--comment-2nd-line-matcher) (c-ts-mode--comment-2nd-line-anchor): New functions. * lisp/treesit.el (treesit-simple-indent-presets): prev-adaptive-prefix doesn't handle the comment-start-skip case (i.e, 2nd line) anymore. (Handled by the new matcher.) --- lisp/progmodes/c-ts-mode.el | 38 ++++++++++++++++++++++++++++++++----- lisp/treesit.el | 25 +++++++++++------------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 772b259d59e..898b89b9fce 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -122,6 +122,9 @@ MODE is either `c' or `cpp'." ((node-is "else") parent-bol 0) ((node-is "case") parent-bol 0) ((node-is "preproc_arg") no-indent) + (c-ts-mode--comment-2nd-line-matcher + c-ts-mode--comment-2nd-line-anchor + 1) ((and (parent-is "comment") c-ts-mode--looking-at-star) c-ts-mode--comment-start-after-first-star -1) ((parent-is "comment") prev-adaptive-prefix 0) @@ -227,11 +230,8 @@ beginning of grandparent." (defun c-ts-mode--looking-at-star (_n _p bol &rest _) "A tree-sitter simple indent matcher. -Matches if there is a \"*\" after point (ignoring whitespace in -between)." - (save-excursion - (goto-char bol) - (looking-at (rx (* (syntax whitespace)) "*")))) +Matches if there is a \"*\" after BOL." + (eq (char-after bol) ?*)) (defun c-ts-mode--comment-start-after-first-star (_n parent &rest _) "A tree-sitter simple indent anchor. @@ -243,6 +243,34 @@ Assumes PARENT is a comment node." (match-end 0) (point)))) +(defun c-ts-mode--comment-2nd-line-matcher (_n parent &rest _) + "Matches if point is at the second line of a block comment. +PARENT should be a comment node." + (save-excursion + (forward-line -1) + (back-to-indentation) + (eq (point) (treesit-node-start parent)))) + +(defun c-ts-mode--comment-2nd-line-anchor (&rest _) + "Return appropriate anchor for the second line of a comment. + +If the first line is /* alone, return the position right after +the star; if the first line is /* followed by some text, return +the position right before the text minus 1. + +Use an offset of 1 with this anchor." + (save-excursion + (forward-line -1) + (back-to-indentation) + (when (looking-at comment-start-skip) + (goto-char (match-end 0)) + (if (looking-at (rx (* (or " " "\t")) eol)) + ;; Only /* at the first line. + (progn (skip-chars-backward " \t") + (point)) + ;; There is something after /* at the first line. + (1- (point)))))) + ;;; Font-lock (defvar c-ts-mode--preproc-keywords diff --git a/lisp/treesit.el b/lisp/treesit.el index 7a604121c4e..5b306354465 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1143,20 +1143,17 @@ See `treesit-simple-indent-presets'.") (point)))) (cons 'prev-adaptive-prefix (lambda (_n parent &rest _) - (save-excursion - (re-search-backward - (rx (not (or " " "\t" "\n"))) nil t) - (beginning-of-line) - (and (>= (point) (treesit-node-start parent)) - ;; `adaptive-fill-regexp' will not match "/*", - ;; so we need to also try `comment-start-skip'. - (or (and adaptive-fill-regexp - (looking-at adaptive-fill-regexp) - (> (- (match-end 0) (match-beginning 0)) 0) - (match-end 0)) - (and comment-start-skip - (looking-at comment-start-skip) - (match-end 0))))))) + (let ((comment-start-bol + (save-excursion + (goto-char (treesit-node-start parent)) + (line-beginning-position)))) + (save-excursion + (forward-line -1) + (and (>= (point) comment-start-bol) + adaptive-fill-regexp + (looking-at adaptive-fill-regexp) + (> (match-end 0) (match-beginning 0)) + (match-end 0)))))) ;; TODO: Document. (cons 'grand-parent (lambda (_n parent &rest _) -- 2.39.2