* lisp/treesit.el (treesit-forward-sexp): Don't use
'treesit-sexp-type-regexp' reserved for list commands
to override their default 'list' thing.
(treesit-down-list, treesit-up-list): Use
'treesit-sexp-type-regexp' instead of 'list'
when it's non-nil.
(treesit-toggle-sexp-mode): New command.
* lisp/progmodes/c-ts-mode.el (c-ts-mode--thing-settings):
Improve 'sexp' thing settings to exclude the top-level
"translation_unit" that just moves to EOF and also "comment".
* lisp/progmodes/elixir-ts-mode.el (elixir-ts--sexp-regexp): Remove.
(elixir-ts--forward-sexp): Remove to use the default 'sexp' navigation.
(elixir-ts--with-parens-0-p, elixir-ts--with-parens-1-p):
New internal functions.
(elixir-ts-mode): Add 'treesit-thing-settings'
instead of 'forward-sexp-function' (bug#76788).
* lisp/progmodes/heex-ts-mode.el (heex-ts--sexp-regexp): Remove.
(heex-ts--forward-sexp): Remove to use the default 'sexp' navigation.
(heex-ts--thing-settings): New variable.
(heex-ts-mode): Use 'heex-ts--thing-settings'
instead of 'forward-sexp-function'.
* lisp/progmodes/java-ts-mode.el (java-ts-mode):
Improve 'sexp' thing to use settings like in c-ts-mode.
* lisp/progmodes/php-ts-mode.el (php-ts-mode):
Improve 'sexp' thing settings to exclude the top-level
"program" that just moves to EOF and also "comment".
* lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode):
Improve 'sexp' thing to use settings like in c-ts-mode.
* lisp/textmodes/css-mode.el (css--treesit-thing-settings):
Add 'sexp' thing. Add "string_value" to 'text' thing.
* lisp/textmodes/html-ts-mode.el (html-ts-mode--treesit-things-settings):
Improve 'sexp' thing to use settings like in c-ts-mode.
Add "doctype" to the 'list' thing.
(cherry picked from commit
99a2cb05a41c66565d417e11e60f4324aaa5c5b5)
(defvar c-ts-mode--thing-settings
`(;; It's more useful to include semicolons as sexp so
;; that users can move to the end of a statement.
- (sexp (not ,(rx (or "{" "}" "[" "]" "(" ")" ","))))
+ (sexp (not (or (and named
+ ,(rx bos (or "translation_unit" "comment") eos))
+ (and anonymous
+ ,(rx (or "{" "}" "[" "]"
+ "(" ")" ","))))))
(list
,(regexp-opt '("preproc_params"
"preproc_if"
"Face used for attributes in Elixir files."
:group 'elixir-ts)
-(defconst elixir-ts--sexp-regexp
- (rx bol
- (or "call" "stab_clause" "binary_operator" "list" "tuple" "map" "pair"
- "sigil" "string" "atom" "alias" "arguments" "identifier"
- "boolean" "quoted_content" "bitstring")
- eol))
-
(defconst elixir-ts--test-definition-keywords
'("describe" "test"))
(:match "^[HF]$" @_name)
(quoted_content) @heex)))))
-(defvar heex-ts--sexp-regexp)
+(defvar heex-ts--thing-settings)
(defvar heex-ts--indent-rules)
(defvar heex-ts--font-lock-settings)
-(defun elixir-ts--forward-sexp (&optional arg)
- "Move forward across one balanced expression (sexp).
-With ARG, do it many times. Negative ARG means move backward."
- (or arg (setq arg 1))
- (funcall
- (if (> arg 0) #'treesit-end-of-thing #'treesit-beginning-of-thing)
- (if (eq (treesit-language-at (point)) 'heex)
- heex-ts--sexp-regexp
- elixir-ts--sexp-regexp)
- (abs arg)))
-
(defun elixir-ts--treesit-anchor-grand-parent-bol (_n parent &rest _)
"Return the beginning of non-space characters for the parent node of PARENT."
(save-excursion
(_ nil))))
(_ nil)))
+(defun elixir-ts--with-parens-0-p (node)
+ (equal (treesit-node-type (treesit-node-child node 0))
+ "("))
+
+(defun elixir-ts--with-parens-1-p (node)
+ (equal (treesit-node-type (treesit-node-child node 1))
+ "("))
+
(defvar elixir-ts--syntax-propertize-query
(when (treesit-available-p)
(treesit-query-compile
(setq-local treesit-simple-indent-rules elixir-ts--indent-rules)
;; Navigation.
- (setq-local forward-sexp-function #'elixir-ts--forward-sexp)
+ (setq-local treesit-thing-settings
+ `((elixir
+ (sexp (not (or (and named
+ ,(rx bos (or "source" "comment") eos))
+ (and anonymous
+ ,(rx (or "{" "}" "[" "]" "(" ")"
+ "do" "end"))))))
+ (list
+ (or (and "\\`arguments\\'" ,#'elixir-ts--with-parens-0-p)
+ (and "\\`unary_operator\\'" ,#'elixir-ts--with-parens-1-p)
+ ,(rx bos (or "block"
+ "quoted_atom"
+ "string"
+ "interpolation"
+ "sigil"
+ "quoted_keyword"
+ "list"
+ "tuple"
+ "bitstring"
+ "map"
+ "do_block"
+ "anonymous_function")
+ eos)))
+ (sentence
+ ,(rx bos (or "call") eos))
+ (text
+ ,(rx bos (or "string" "sigil" "comment") eos)))
+ (heex ,@heex-ts--thing-settings)))
(setq-local treesit-defun-type-regexp
'("call" . elixir-ts--defun-p))
:safe 'integerp
:group 'heex-ts)
-(defconst heex-ts--sexp-regexp
- (rx bol
- (or "directive" "tag" "component" "slot"
- "attribute" "attribute_value" "quoted_attribute_value" "expression")
- eol))
-
;; There seems to be no parent directive block for tree-sitter-heex,
;; so we ignore them for now until we learn how to query them.
;; https://github.com/phoenixframework/tree-sitter-heex/issues/28
(treesit-node-child (treesit-node-child node 0) 1) nil)))
(_ nil)))
-(defun heex-ts--forward-sexp (&optional arg)
- "Move forward across one balanced expression (sexp).
-With ARG, do it many times. Negative ARG means move backward."
- (or arg (setq arg 1))
- (funcall
- (if (> arg 0) #'treesit-end-of-thing #'treesit-beginning-of-thing)
- heex-ts--sexp-regexp
- (abs arg)))
+(defvar heex-ts--thing-settings
+ `((sexp
+ (not (or (and named
+ ,(rx bos (or "fragment" "comment") eos))
+ (and anonymous
+ ,(rx (or "<!" "<" ">" "{" "}"))))))
+ (list
+ ,(rx bos (or "doctype"
+ "tag"
+ "component"
+ "slot"
+ "expression"
+ "directive"
+ "comment")
+ eos))
+ (sentence
+ ,(rx bos (or "tag_name"
+ "component_name"
+ "attribute")
+ eos))
+ (text
+ ,(rx bos (or "comment" "text") eos)))
+ "`treesit-thing-settings' for HEEx.")
;;;###autoload
(define-derived-mode heex-ts-mode html-mode "HEEx"
;; Comments
(setq-local treesit-thing-settings
- `((heex
- (text ,(regexp-opt '("comment" "text"))))))
-
- (setq-local forward-sexp-function #'heex-ts--forward-sexp)
+ `((heex ,@heex-ts--thing-settings)))
;; Navigation.
(setq-local treesit-defun-type-regexp
(setq-local treesit-thing-settings
`((java
- (sexp ,(rx (or "annotation"
- "parenthesized_expression"
- "argument_list"
- "identifier"
- "modifiers"
- "block"
- "body"
- "literal"
- "access"
- "reference"
- "_type"
- "true"
- "false")))
+ (sexp (not (or (and named
+ ,(rx bos (or "program"
+ "line_comment"
+ "block_comment")
+ eos))
+ (and anonymous
+ ,(rx (or "{" "}" "[" "]"
+ "(" ")" "<" ">"
+ ","))))))
(list ,(rx bos (or "inferred_parameters"
"parenthesized_expression"
"argument_list"
(setq-local treesit-thing-settings
`((php
(defun ,treesit-defun-type-regexp)
- (sexp (not ,(rx (or "{" "}" "[" "]" "(" ")" ","))))
+ (sexp (not (or (and named
+ ,(rx bos (or "program"
+ "comment")
+ eos))
+ (and anonymous
+ ,(rx bos (or "{" "}" "[" "]"
+ "(" ")" ",")
+ eos)))))
(list
,(rx bos (or "namespace_use_group"
"enum_declaration_list"
(setq-local treesit-thing-settings
`((ruby
- (sexp ,(cons (rx
- bos
- (or
- "class"
- "singleton_class"
- "module"
- "method"
- "singleton_method"
- "array"
- "hash"
- "parenthesized_statements"
- "method_parameters"
- "array_pattern"
- "hash_pattern"
- "if"
- "else"
- "then"
- "unless"
- "case"
- "case_match"
- "when"
- "while"
- "until"
- "for"
- "block"
- "do_block"
- "begin"
- "integer"
- "identifier"
- "self"
- "super"
- "constant"
- "simple_symbol"
- "hash_key_symbol"
- "symbol_array"
- "string"
- "string_array"
- "heredoc_body"
- "regex"
- "argument_list"
- "interpolation"
- "instance_variable"
- "global_variable"
- )
- eos)
- #'ruby-ts--sexp-p))
+ (sexp (not (or (and named
+ ,(rx bos (or "program"
+ "body_statement"
+ "comment"
+ "then")
+ eos))
+ (and anonymous
+ ,(rx (or "do" "begin"
+ "if" "unless"
+ "def" "end"
+ "(" ")" "[" "]"
+ "{" "}" "|" "," ";"))))))
(list ,(cons (rx
bos
(or
res)))))))
(defvar css--treesit-thing-settings
- `((css (list
+ `((css (sexp
+ (not (or (and named
+ ,(rx bos (or "stylesheet" "comment") eos))
+ (and anonymous
+ ,(rx (or "{" "}" "[" "]"
+ "(" ")" ","))))))
+ (list
,(rx bos (or "keyframe_block_list"
"block"
"pseudo_class_arguments"
"declaration")
eos))
(text
- ,(rx bos "comment" eos))))
+ ,(rx bos (or "comment" "string_value") eos))))
"Settings for `treesit-thing-settings'.")
(defvar css--treesit-font-lock-feature-list
(defvar html-ts-mode--treesit-things-settings
`((html
- (sexp ,(regexp-opt '("element"
- "text"
- "attribute"
- "value")))
- (list ,(rx (or
- ;; Also match script_element and style_element
- "element"
- ;; HTML comments have the element syntax
- "comment")))
+ (sexp (not (or (and named
+ ,(rx bos (or "document" "tag_name") eos))
+ (and anonymous
+ ,(rx (or "<!" "<" ">" "</"))))))
+ (list ,(rx (or "doctype"
+ ;; Also match script_element and style_element
+ "element"
+ ;; HTML comments have the element syntax
+ "comment")))
(sentence ,(rx (and bos (or "tag_name" "attribute") eos)))
(text ,(regexp-opt '("comment" "text")))))
"Settings for `treesit-thing-settings'.")
(let ((arg (or arg 1))
(pred (or treesit-sexp-type-regexp 'sexp))
(node-at-point
- (when (null treesit-sexp-type-regexp)
- (treesit-node-at (point) (treesit-language-at (point))))))
+ (treesit-node-at (point) (treesit-language-at (point)))))
(or (when (and node-at-point
;; Make sure point is strictly inside node.
(< (treesit-node-start node-at-point)
ARG is described in the docstring of `down-list'."
(interactive "^p")
- (let* ((pred 'list)
+ (let* ((pred (or treesit-sexp-type-regexp 'list))
(arg (or arg 1))
(cnt arg)
(inc (if (> arg 0) 1 -1)))
(treesit-thing-prev (point) pred)))
(child (when sibling
(treesit-node-child sibling (if (> arg 0) 0 -1)))))
- (or (when (and default-pos
+ (or (when (and (null treesit-sexp-type-regexp)
+ default-pos
(or (null child)
(if (> arg 0)
(<= default-pos (treesit-node-start child))
ARG is described in the docstring of `up-list'."
(interactive "^p")
- (let* ((pred 'list)
+ (let* ((pred (or treesit-sexp-type-regexp 'list))
(arg (or arg 1))
(cnt arg)
(inc (if (> arg 0) 1 -1)))
(treesit-node-at (point) (car parsers)) pred)
parsers (cdr parsers)))))
- (or (when (and default-pos
+ (or (when (and (null treesit-sexp-type-regexp)
+ default-pos
(or (null parent)
(if (> arg 0)
(<= default-pos (treesit-node-end parent))
(user-error "At top level")))
(setq cnt (- cnt inc)))))
+(defun treesit-toggle-sexp-mode ()
+ "Toggle the mode of navigation for sexp and list commands.
+This mode toggle affects such navigation commands as
+`treesit-forward-sexp', `treesit-forward-list', `treesit-down-list',
+`treesit-up-list'.
+
+The list mode uses the `list' thing defined in `treesit-thing-settings'.
+In this mode commands use syntax definition to navigate symbols and
+treesit definition to navigate lists.
+
+The sexp mode uses the `sexp' thing defined in `treesit-thing-settings'.
+In this mode commands use the treesit definition only
+without distinction between symbols and lists."
+ (interactive)
+ (if (not (treesit-thing-defined-p 'list (treesit-language-at (point))))
+ (message "No `list' thing is defined in `treesit-thing-settings'")
+ (setq-local treesit-sexp-type-regexp
+ (unless treesit-sexp-type-regexp
+ (if (treesit-thing-defined-p
+ 'sexp (treesit-language-at (point)))
+ 'sexp
+ #'treesit-node-named))
+ forward-sexp-function
+ (if treesit-sexp-type-regexp
+ #'treesit-forward-sexp
+ #'treesit-forward-sexp-list))
+ (message "Toggle to mode where sexp commands navigate %s"
+ (or (and treesit-sexp-type-regexp
+ "treesit nodes")
+ "syntax symbols and treesit lists"))))
+
(defun treesit-transpose-sexps (&optional arg)
"Tree-sitter `transpose-sexps' function.
ARG is the same as in `transpose-sexps'.