summaryrefslogtreecommitdiff
path: root/lisp/treesit.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/treesit.el')
-rw-r--r--lisp/treesit.el100
1 files changed, 55 insertions, 45 deletions
diff --git a/lisp/treesit.el b/lisp/treesit.el
index b7da38becc1..f3c03daf7e0 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -520,6 +520,25 @@ omitted, default END to BEG."
"Generic tree-sitter font-lock error"
'treesit-error)
+(defvar-local treesit-font-lock-level 3
+ "Decoration level to be used by tree-sitter fontifications.
+
+Major modes categorize their fontification features into levels,
+from 1 which is the absolute minimum, to 4 that yields the maximum
+fontifications.
+
+Level 1 usually contains only comments and definitions.
+Level 2 usually adds keywords, strings, constants, types, etc.
+Level 3 usually represents a full-blown fontification, including
+assignment, constants, numbers, properties, etc.
+Level 4 adds everything else that can be fontified: delimiters,
+operators, brackets, all functions and variables, etc.
+
+In addition to the decoration level, individual features can be
+turned on/off by calling `treesit-font-lock-recompute-features'.
+Changing the decoration level requires calling
+`treesit-font-lock-recompute-features' to have an effect.")
+
(defvar-local treesit--font-lock-query-expand-range (cons 0 0)
"The amount to expand the start and end of the region when fontifying.
This should be a cons cell (START . END). When fontifying a
@@ -537,11 +556,10 @@ temporarily fix.")
"A list of lists of feature symbols.
Use `treesit-font-lock-recompute-features' and
-`font-lock-maximum-decoration' to configure enabled features.
+`treesit-font-lock-level' to configure enabled features.
Each sublist represents a decoration level.
-`font-lock-maximum-decoration' controls which levels are
-activated.
+`treesit-font-lock-level' controls which levels are activated.
Inside each sublist are feature symbols, which correspond to the
:feature value of a query defined in `treesit-font-lock-rules'.
@@ -575,8 +593,8 @@ For SETTING to be activated for font-lock, ENABLE must be t. To
disable this SETTING, set ENABLE to nil.
FEATURE is the \"feature name\" of the query. Users can control
-which features are enabled with `font-lock-maximum-decoration'
-and `treesit-font-lock-feature-list'.
+which features are enabled with `treesit-font-lock-level' and
+`treesit-font-lock-feature-list'.
OVERRIDE is the override flag for this query. Its value can be
t, nil, append, prepend, keep. See more in
@@ -718,22 +736,19 @@ REMOVE-LIST.
If both ADD-LIST and REMOVE-LIST are omitted, recompute each
feature according to `treesit-font-lock-feature-list' and
-`font-lock-maximum-decoration'. Let N be the value of
-`font-lock-maximum-decoration', features in the first Nth sublist
-of `treesit-font-lock-feature-list' are enabled, and the rest
-features are disabled. If `font-lock-maximum-decoration' is t,
-all features in `treesit-font-lock-feature-list' are enabled, and
-the rest are disabled.
-
-ADD-LIST and REMOVE-LIST are each a list of feature symbols. The
+`treesit-font-lock-level'. If the value of `treesit-font-lock-level',
+is N, then the features in the first N sublists of
+`treesit-font-lock-feature-list' are enabled, and the rest of
+the features are disabled.
+
+ADD-LIST and REMOVE-LIST are lists of feature symbols. The
same feature symbol cannot appear in both lists; the function
signals the `treesit-font-lock-error' error if that happens."
(when-let ((intersection (cl-intersection add-list remove-list)))
(signal 'treesit-font-lock-error
(list "ADD-LIST and REMOVE-LIST contain the same feature"
intersection)))
- (let* ((level (font-lock-value-in-major-mode
- font-lock-maximum-decoration))
+ (let* ((level treesit-font-lock-level)
(base-features (cl-loop
for idx = 0 then (1+ idx)
for features in treesit-font-lock-feature-list
@@ -958,16 +973,6 @@ parser notifying of the change."
;;; Indent
-;; `comment-start' and `comment-end' assume there is only one type of
-;; comment, and that the comment spans only one line. So they are not
-;; sufficient for our purpose.
-
-(defvar-local treesit-comment-start nil
- "Regular expression matching an opening comment token.")
-
-(defvar-local treesit-comment-end nil
- "Regular expression matching a closing comment token.")
-
(define-error 'treesit-indent-error
"Generic tree-sitter indentation error"
'treesit-error)
@@ -1056,7 +1061,7 @@ See `treesit-simple-indent-presets'.")
(cons 'comment-end (lambda (_node _parent bol &rest _)
(save-excursion
(goto-char bol)
- (looking-at-p treesit-comment-end))))
+ (looking-at-p comment-end-skip))))
;; TODO: Document.
(cons 'catch-all (lambda (&rest _) t))
@@ -1082,14 +1087,14 @@ See `treesit-simple-indent-presets'.")
(lambda (_n parent &rest _)
(save-excursion
(goto-char (treesit-node-start parent))
- (re-search-forward treesit-comment-start)
+ (re-search-forward comment-start-skip)
+ (skip-syntax-backward "-")
(point))))
(cons 'comment-start-skip
(lambda (_n parent &rest _)
(save-excursion
(goto-char (treesit-node-start parent))
- (re-search-forward treesit-comment-start)
- (skip-syntax-forward "-")
+ (re-search-forward comment-start-skip)
(point))))
;; TODO: Document.
(cons 'grand-parent
@@ -1549,20 +1554,18 @@ For example, \"(function|class)_definition\".
This is used by `treesit-beginning-of-defun' and friends.")
(defvar-local treesit-defun-prefer-top-level nil
- "When non-nil, `treesit-beginning-of-defun' prefers top-level defun.
+ "When non-nil, Emacs prefers top-level defun.
-In some languages, a defun (function, class, struct) could be
-nested in another one. Normally `treesit-beginning-of-defun'
-just finds the first defun it encounter. If this variable's
-value is t, `treesit-beginning-of-defun' tries to find the
-top-level defun, and ignores nested ones.
+In some languages, a defun could be nested in another one.
+Normally Emacs stops at the first defun it encounters. If this
+variable's value is t, Emacs tries to find the top-level defun,
+and ignores nested ones.
-This variable can also be a list of tree-sitter node type
-regexps. Then, when `treesit-beginning-of-defun' finds a defun
-node and that node's type matches one in the list,
-`treesit-beginning-of-defun' finds the top-level node matching
-that particular regexp (as opposed to any node matched by
-`treesit-defun-type-regexp').")
+This variable can also be a list of cons cells of the
+form (FROM . TO), where FROM and TO are tree-sitter node type
+regexps. When Emacs finds a defun node whose type matches any of
+the FROM regexps in the list, it then tries to find a
+higher-level node matching the corresponding TO regexp.")
(defun treesit--defun-maybe-top-level (node)
"Maybe return the top-level equivalent of NODE.
@@ -1574,9 +1577,11 @@ For the detailed semantic see `treesit-defun-prefer-top-level'."
node))
((pred consp)
(cl-loop
- for re in treesit-defun-prefer-top-level
- if (string-match-p re (treesit-node-type node))
- return (or (treesit-node-top-level node re)
+ for con in treesit-defun-prefer-top-level
+ for from = (car con)
+ for to = (cdr con)
+ if (string-match-p from (treesit-node-type node))
+ return (or (treesit-node-top-level node to)
node)
finally return node))))
@@ -1609,7 +1614,12 @@ ARG is the same as in `beginning-of-defun'."
(let* ((node (treesit-search-forward
(treesit-node-at (point)) treesit-defun-type-regexp t t))
(top (treesit--defun-maybe-top-level node)))
- (goto-char (treesit-node-end top))))
+ ;; Technically `end-of-defun' should only call this function when
+ ;; point is at the beginning of a defun, so TOP should always be
+ ;; non-nil, but things happen, and we want to be safe, so check
+ ;; for TOP anyway.
+ (when top
+ (goto-char (treesit-node-end top)))))
;;; Activating tree-sitter