summaryrefslogtreecommitdiff
path: root/lisp/progmodes/ruby-ts-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/ruby-ts-mode.el')
-rw-r--r--lisp/progmodes/ruby-ts-mode.el109
1 files changed, 69 insertions, 40 deletions
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index d077c43ba52..7a00977f14a 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -469,7 +469,7 @@ non-nil."
(let* (first-call )
(while (and parent
(setq first-call (treesit-node-parent parent))
- (string-match-p "call" (treesit-node-type first-call)))
+ (equal "call" (treesit-node-type first-call)))
(setq parent first-call))
(treesit-node-start (treesit-search-subtree parent "\\." nil t))))
@@ -883,32 +883,24 @@ a statement container is a node that matches
"Return the fully qualified name of NODE."
(let* ((name (ruby-ts--get-name node))
(delimiter "#"))
+ (when (equal (treesit-node-type node) "singleton_method")
+ (setq delimiter "."
+ name (treesit-node-text (treesit-node-child-by-field-name node "name"))))
(while (setq node (treesit-parent-until node #'ruby-ts--class-or-module-p))
- (setq name (concat (ruby-ts--get-name node) delimiter name))
+ (if name
+ (setq name (concat (ruby-ts--get-name node) delimiter name))
+ (setq name (ruby-ts--get-name node)))
(setq delimiter "::"))
name))
-(defun ruby-ts--imenu-helper (node)
- "Convert a treesit sparse tree NODE in an imenu list.
-Helper for `ruby-ts--imenu' which converts a treesit sparse
-NODE into a list of imenu ( name . pos ) nodes"
- (let* ((ts-node (car node))
- (subtrees (mapcan #'ruby-ts--imenu-helper (cdr node)))
- (name (when ts-node
- (ruby-ts--full-name ts-node)))
- (marker (when ts-node
- (set-marker (make-marker)
- (treesit-node-start ts-node)))))
- (cond
- ((or (null ts-node) (null name)) subtrees)
- ;; Don't include the anonymous "class" and "module" nodes
- ((string-match-p "(\"\\(class\\|module\\)\")"
- (treesit-node-string ts-node))
- nil)
- (subtrees
- `((,name ,(cons name marker) ,@subtrees)))
- (t
- `((,name . ,marker))))))
+(defun ruby-ts--imenu-helper (tree)
+ "Convert a treesit sparse tree NODE in a flat imenu list."
+ (if (cdr tree)
+ ;; We only use the "leaf" values in the tree. It does include a
+ ;; leaf node for every class or module body.
+ (cl-mapcan #'ruby-ts--imenu-helper (cdr tree))
+ (list (cons (ruby-ts--full-name (car tree))
+ (treesit-node-start (car tree))))))
;; For now, this is going to work like ruby-mode and return a list of
;; class, modules, def (methods), and alias. It is likely that this
@@ -916,8 +908,14 @@ NODE into a list of imenu ( name . pos ) nodes"
(defun ruby-ts--imenu ()
"Return Imenu alist for the current buffer."
(let* ((root (treesit-buffer-root-node))
- (nodes (treesit-induce-sparse-tree root "^\\(method\\|alias\\|class\\|module\\)$")))
- (ruby-ts--imenu-helper nodes)))
+ (tree (treesit-induce-sparse-tree root
+ (rx bol (or "singleton_method"
+ "method"
+ "alias"
+ "class"
+ "module")
+ eol))))
+ (ruby-ts--imenu-helper tree)))
(defun ruby-ts--arrow-up-start (arg)
"Move to the start ARG levels up or out."
@@ -1088,6 +1086,15 @@ leading double colon is not added."
(put-text-property pos (1+ pos) 'syntax-table
(string-to-syntax "!"))))))))
+(defun ruby-ts--sexp-p (node)
+ ;; Skip parenless calls (implicit parens are both non-obvious to the
+ ;; user, and might take over when we want to just over some physical
+ ;; parens/braces).
+ (or (not (equal (treesit-node-type node)
+ "argument_list"))
+ (equal (treesit-node-type (treesit-node-child node 0))
+ "(")))
+
(defvar-keymap ruby-ts-mode-map
:doc "Keymap used in Ruby mode"
:parent prog-mode-map
@@ -1116,21 +1123,43 @@ leading double colon is not added."
(setq-local treesit-defun-type-regexp ruby-ts--method-regex)
(setq-local treesit-sexp-type-regexp
- (regexp-opt '("class"
- "module"
- "method"
- "argument_list"
- "array"
- "hash"
- "parenthesized_statements"
- "if"
- "case"
- "when"
- "block"
- "do_block"
- "begin"
- "binary"
- "assignment")))
+ (cons (rx
+ bol
+ (or
+ "class"
+ "module"
+ "method"
+ "array"
+ "hash"
+ "parenthesized_statements"
+ "method_parameters"
+ "array_pattern"
+ "hash_pattern"
+ "if"
+ "unless"
+ "case"
+ "case_match"
+ "when"
+ "block"
+ "do_block"
+ "begin"
+ "integer"
+ "identifier"
+ "constant"
+ "simple_symbol"
+ "hash_key_symbol"
+ "symbol_array"
+ "string"
+ "string_array"
+ "heredoc_body"
+ "regex"
+ "argument_list"
+ "interpolation"
+ "instance_variable"
+ "global_variable"
+ )
+ eol)
+ #'ruby-ts--sexp-p))
;; AFAIK, Ruby can not nest methods
(setq-local treesit-defun-prefer-top-level nil)