diff options
Diffstat (limited to 'lisp/treesit.el')
-rw-r--r-- | lisp/treesit.el | 100 |
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 |