[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 1e44c63fcad 03/11: Allow treesit-simple-indent's rule to be a sin
From: |
Yuan Fu |
Subject: |
master 1e44c63fcad 03/11: Allow treesit-simple-indent's rule to be a single function |
Date: |
Sun, 1 Dec 2024 21:10:22 -0500 (EST) |
branch: master
commit 1e44c63fcadeb89a9a9c9208f221970e6fcc774c
Author: Yuan Fu <casouri@gmail.com>
Commit: Yuan Fu <casouri@gmail.com>
Allow treesit-simple-indent's rule to be a single function
* lisp/treesit.el (treesit-simple-indent-rules): Allow the rule
to be a single function. Also replace cl-loop with dolist plus
catch-throw.
(treesit--indent-rules-optimize): Handle the case when a rule is
a function.
* doc/lispref/modes.texi (Parser-based Indentation): Update
manuel.
---
doc/lispref/modes.texi | 21 ++++++++++---
lisp/treesit.el | 85 +++++++++++++++++++++++++++++---------------------
2 files changed, 65 insertions(+), 41 deletions(-)
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index 87c6347eaa7..f32d5a89bca 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -5243,11 +5243,13 @@ more complex indentation engines.
@cindex indentation rules, for parser-based indentation
@defvar treesit-simple-indent-rules
-This local variable stores indentation rules for every language. It
-is an alist with elements of the form @w{@code{(@var{language}
-. @var{rules})}}, where @var{language} is a language symbol, and
-@var{rules} is a list with elements of the form
-@w{@code{(@var{matcher} @var{anchor} @var{offset})}}.
+This local variable stores indentation rules for every language. It is
+an list of elements of the form @w{@code{(@var{language}
+@var{rule}...)}}, where @var{language} is a language symbol, and each
+@var{rule} is either a list with elements of the form
+@w{@code{(@var{matcher} @var{anchor} @var{offset})}}, or a function. Let
+'s focus on the list variant first, we'll come back to the function
+variant later.
First, Emacs passes the smallest tree-sitter node at the beginning of
the current line to @var{matcher}; if it returns non-@code{nil}, this
@@ -5277,6 +5279,15 @@ and @var{anchor} should return a buffer position.
or a function that returns an integer. If it is a function, it is
passed @var{node}, @var{parent}, and @var{bol}, like matchers and
anchors.
+
+Remember that @var{rule} can also be a function. This is for the
+complex cases where a rule needs to consider the matching rule and
+anchor together. If @var{rule} is a function, it's passed the same
+argument as @var{matcher}: @var{node}, @var{parent}, and @var{bol}. If
+it matches, @var{rule} should return a cons @w{@code{(@var{anchor-pos}
+. @var{offset})}}, where @var{anchor-pos} is a buffer position, and
+@var{offset} is the indent offset. If @var{rule} does't match, it
+should return @code{nil}.
@end defvar
@defvar treesit-simple-indent-presets
diff --git a/lisp/treesit.el b/lisp/treesit.el
index 5d57b9e8e3e..64b08857f4a 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1559,13 +1559,13 @@ START and END mark the current to-be-propertized
region."
(defvar-local treesit-simple-indent-rules nil
"A list of indent rule settings.
-Each indent rule setting should be (LANGUAGE . RULES),
-where LANGUAGE is a language symbol, and RULES is a list of
+Each indent rule setting should be (LANGUAGE RULE...), where LANGUAGE is
+a language symbol, and each RULE is of the form
- (MATCHER ANCHOR OFFSET).
+ (MATCHER ANCHOR OFFSET)
-MATCHER determines whether this rule applies, ANCHOR and OFFSET
-together determines which column to indent to.
+MATCHER determines whether this rule applies, ANCHOR and
+OFFSET together determines which column to indent to.
A MATCHER is a function that takes three arguments (NODE PARENT
BOL). BOL is the point where we are indenting: the beginning of
@@ -1582,7 +1582,12 @@ ANCHOR and adds OFFSET to it, and indents to that
column. OFFSET
can be an integer or a variable whose value is an integer.
For MATCHER and ANCHOR, Emacs provides some convenient presets.
-See `treesit-simple-indent-presets'.")
+See `treesit-simple-indent-presets'.
+
+For complex cases, a RULE can also be a single function. This function
+should take the same argument as MATCHER or ANCHOR. If it matches,
+return a cons (ANCHOR-POS . OFFSET), where ANCHOR-POS is a position and
+OFFSET is the indent offset; if it doesn't match, return nil.")
(defvar treesit-simple-indent-presets
(list (cons 'match
@@ -2121,31 +2126,37 @@ OFFSET."
(let* ((language (treesit-node-language parent))
(rules (alist-get language
treesit-simple-indent-rules)))
- (cl-loop for rule in rules
- for pred = (nth 0 rule)
- for anchor = (nth 1 rule)
- for offset = (nth 2 rule)
- if (treesit--simple-indent-eval
- (list pred node parent bol))
- do (when treesit--indent-verbose
+ (catch 'match
+ (dolist (rule rules)
+ (if (functionp rule)
+ (let ((result (funcall rule node parent bol)))
+ (when result
+ (when treesit--indent-verbose
(message "Matched rule: %S" rule))
- and
- return
- (let ((anchor-pos
- (treesit--simple-indent-eval
- (list anchor node parent bol)))
- (offset-val
- (cond ((numberp offset) offset)
- ((and (symbolp offset)
- (boundp offset))
- (symbol-value offset))
- (t (treesit--simple-indent-eval
- (list offset node parent bol))))))
- (cons anchor-pos offset-val))
- finally return
- (progn (when treesit--indent-verbose
- (message "No matched rule"))
- (cons nil nil))))))
+ (throw 'match result)))
+ (let ((pred (nth 0 rule))
+ (anchor (nth 1 rule))
+ (offset (nth 2 rule)))
+ ;; Found a match.
+ (when (treesit--simple-indent-eval
+ (list pred node parent bol))
+ (when treesit--indent-verbose
+ (message "Matched rule: %S" rule))
+ (let ((anchor-pos
+ (treesit--simple-indent-eval
+ (list anchor node parent bol)))
+ (offset-val
+ (cond ((numberp offset) offset)
+ ((and (symbolp offset)
+ (boundp offset))
+ (symbol-value offset))
+ (t (treesit--simple-indent-eval
+ (list offset node parent bol))))))
+ (throw 'match (cons anchor-pos offset-val)))))))
+ ;; Didn't find any match.
+ (when treesit--indent-verbose
+ (message "No matched rule"))
+ (cons nil nil)))))
(defun treesit--read-major-mode ()
"Read a major mode using completion.
@@ -2201,12 +2212,14 @@ RULES."
(_ func)))
;; Optimize a rule (MATCHER ANCHOR OFFSET).
(optimize-rule (rule)
- (let ((matcher (nth 0 rule))
- (anchor (nth 1 rule))
- (offset (nth 2 rule)))
- (list (optimize-func matcher)
- (optimize-func anchor)
- offset))))
+ (if (functionp rule)
+ rule
+ (let ((matcher (nth 0 rule))
+ (anchor (nth 1 rule))
+ (offset (nth 2 rule)))
+ (list (optimize-func matcher)
+ (optimize-func anchor)
+ offset)))))
(cons lang (mapcar #'optimize-rule indent-rules)))))
;;; Search
- master updated (4afd1eca366 -> de98b5a24f2), Yuan Fu, 2024/12/01
- master c65c5d02224 01/11: Improve c-ts-mode compound indents (bug#74507), Yuan Fu, 2024/12/01
- master d0b918d8f3c 04/11: Add treesit-explore command, Yuan Fu, 2024/12/01
- master 4afdb7e80fe 05/11: ; Minor simplification for tree-sitter indent preset column-0, Yuan Fu, 2024/12/01
- master 63d69bd1549 07/11: Use new baseline indent rule in c-ts-mode, Yuan Fu, 2024/12/01
- master 9acf6eff01a 10/11: Standardize and promote c-ts-mode's custom matcher and anchor, Yuan Fu, 2024/12/01
- master de98b5a24f2 11/11: ; Indent by 8 in BSD indent tests for c-ts-mode, Yuan Fu, 2024/12/01
- master 1e44c63fcad 03/11: Allow treesit-simple-indent's rule to be a single function,
Yuan Fu <=
- master 1d425125694 02/11: Refactor treesit--indent-1, Yuan Fu, 2024/12/01
- master e37cd4fa597 06/11: Add baseline tree-sitter indent rule for C-like languages, Yuan Fu, 2024/12/01
- master 44fcd37a486 08/11: Add more c-ts-mode indent tests, Yuan Fu, 2024/12/01
- master 994258f5567 09/11: Remove unused functions in c-ts-mode, Yuan Fu, 2024/12/01