summaryrefslogtreecommitdiff
path: root/lisp/progmodes/c-ts-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/c-ts-mode.el')
-rw-r--r--lisp/progmodes/c-ts-mode.el74
1 files changed, 56 insertions, 18 deletions
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index fc35d9aedda..a8189a0f3da 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -29,7 +29,7 @@
;;; Code:
(require 'treesit)
-(require 'rx)
+(eval-when-compile (require 'rx))
(declare-function treesit-parser-create "treesit.c")
(declare-function treesit-induce-sparse-tree "treesit.c")
@@ -168,7 +168,7 @@ MODE is either `c' or `cpp'."
(let ((c-keywords
'("break" "case" "const" "continue"
"default" "do" "else" "enum"
- "extern" "for" "goto" "if"
+ "extern" "for" "goto" "if" "inline"
"long" "register" "return" "short"
"signed" "sizeof" "static" "struct"
"switch" "typedef" "union" "unsigned"
@@ -179,7 +179,7 @@ MODE is either `c' or `cpp'."
"catch" "class" "co_await" "co_return"
"co_yield" "compl" "concept" "consteval"
"constexpr" "constinit" "decltype" "delete"
- "explicit" "final" "friend" "friend"
+ "explicit" "final" "friend"
"mutable" "namespace" "new" "noexcept"
"not" "not_eq" "operator" "or"
"or_eq" "override" "private" "protected"
@@ -505,15 +505,35 @@ the subtrees."
(when var-index `(("Variable" . ,var-index)))
(when func-index `(("Function" . ,func-index))))))
+(defun c-ts-mode--end-of-defun ()
+ "`end-of-defun-function' of `c-ts-mode'."
+ ;; A struct/enum/union_specifier node doesn't include the ; at the
+ ;; end, so we manually skip it.
+ (treesit-end-of-defun)
+ (when (looking-at (rx (* " ") ";"))
+ (goto-char (match-end 0))
+ ;; This part is copied from `end-of-defun'.
+ (unless (bolp)
+ (skip-chars-forward " \t")
+ (if (looking-at "\\s<\\|\n")
+ (forward-line 1)))))
+
;;;###autoload
-(define-derived-mode c-ts-mode--base-mode prog-mode "C"
+(define-derived-mode c-ts-base-mode prog-mode "C"
"Major mode for editing C, powered by tree-sitter."
:syntax-table c-ts-mode--syntax-table
;; Navigation.
(setq-local treesit-defun-type-regexp
- (rx (or "specifier"
- "definition")))
+ (regexp-opt '("function_definition"
+ "type_definition"
+ "struct_specifier"
+ "enum_specifier"
+ "union_specifier")))
+
+ ;; Nodes like struct/enum/union_specifier can appear in
+ ;; function_definitions, so we need to find the top-level node.
+ (setq-local treesit-defun-prefer-top-level t)
;; Indent.
(when (eq c-ts-mode-indent-style 'linux)
@@ -528,13 +548,13 @@ the subtrees."
(setq-local which-func-functions nil)
(setq-local treesit-font-lock-feature-list
- '(( comment constant keyword literal preprocessor string)
- ( assignment definition label property type)
- ( delimiter error escape-sequence function
- operator variable bracket))))
+ '(( comment definition)
+ ( keyword preprocessor string type)
+ ( assignment constant escape-sequence label literal property )
+ ( bracket delimiter error function operator variable))))
;;;###autoload
-(define-derived-mode c-ts-mode c-ts-mode--base-mode "C"
+(define-derived-mode c-ts-mode c-ts-base-mode "C"
"Major mode for editing C, powered by tree-sitter."
:group 'c
@@ -545,10 +565,14 @@ the subtrees."
;; Comments.
(setq-local comment-start "/* ")
- (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
(setq-local comment-end " */")
- (setq-local treesit-comment-start (rx "/" (or (+ "/") (+ "*"))))
- (setq-local treesit-comment-end (rx (+ (or "*")) "/"))
+ (setq-local comment-start-skip (rx (or (seq "/" (+ "/"))
+ (seq "/" (+ "*")))
+ (* (syntax whitespace))))
+ (setq-local comment-end-skip
+ (rx (* (syntax whitespace))
+ (group (or (syntax comment-end)
+ (seq (+ "*") "/")))))
(setq-local treesit-simple-indent-rules
(c-ts-mode--set-indent-style 'c))
@@ -556,10 +580,14 @@ the subtrees."
;; Font-lock.
(setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
- (treesit-major-mode-setup))
+ (treesit-major-mode-setup)
+
+ ;; Override default value of end-of-defun-function set by
+ ;; `treesit-major-mode-setup'.
+ (setq-local end-of-defun-function #'c-ts-mode--end-of-defun))
;;;###autoload
-(define-derived-mode c++-ts-mode c-ts-mode--base-mode "C++"
+(define-derived-mode c++-ts-mode c-ts-base-mode "C++"
"Major mode for editing C++, powered by tree-sitter."
:group 'c++
@@ -568,8 +596,14 @@ the subtrees."
;; Comments.
(setq-local comment-start "// ")
- (setq-local comment-start-skip "\\(?://+\\|/\\*+\\)\\s *")
(setq-local comment-end "")
+ (setq-local comment-start-skip (rx (or (seq "/" (+ "/"))
+ (seq "/" (+ "*")))
+ (* (syntax whitespace))))
+ (setq-local comment-end-skip
+ (rx (* (syntax whitespace))
+ (group (or (syntax comment-end)
+ (seq (+ "*") "/")))))
(treesit-parser-create 'cpp)
@@ -579,7 +613,11 @@ the subtrees."
;; Font-lock.
(setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp))
- (treesit-major-mode-setup))
+ (treesit-major-mode-setup)
+
+ ;; Override default value of end-of-defun-function set by
+ ;; `treesit-major-mode-setup'.
+ (setq-local end-of-defun-function #'c-ts-mode--end-of-defun))
(provide 'c-ts-mode)