Function: ruby-ts--indent-rules
ruby-ts--indent-rules is a byte-compiled function defined in
ruby-ts-mode.el.gz.
Signature
(ruby-ts--indent-rules)
Documentation
Indent rules supported by ruby-ts-mode.
Source Code
;; Defined in /usr/src/emacs/lisp/progmodes/ruby-ts-mode.el.gz
;;
;; end of functions that can be used for queries
;;
(defun ruby-ts--indent-rules ()
"Indent rules supported by `ruby-ts-mode'."
(let ((common
`(
;; Slam all top level nodes to the left margin
((parent-is "program") column-0 0)
;; Do not indent here docs or the end. Not sure why it
;; takes the grand-parent but ok fine.
((n-p-gp nil nil "heredoc_body") no-indent 0)
((parent-is "heredoc_body") no-indent 0)
((node-is "heredoc_body") no-indent 0)
;; Do not indent multiline regexp
((n-p-gp nil nil "regex") no-indent 0)
((parent-is "regex") no-indent 0)
;; Incomplete buffer state, better not reindent (bug#61017).
((and (parent-is "ERROR")
(or (node-is ,ruby-ts--class-or-module-regex)
(node-is "\\`\\(?:def\\|identifier\\)\\'")))
no-indent 0)
;; if then else elseif notes:
;;
;; 1. The "then" starts at the end of the line that ends
;; the if condition which can be on a different line
;; from the "if".
;;
;; 2. If there is an "elsif", it is a sibling to the then
;; BUT the "else" that follows is now a child of the
;; "elsif".
;;
;; 3. The statements within each of these are direct
;; children. There is no intermediate construct such
;; as a block_statement.
;;
;; I'm using very restrictive patterns hoping to reduce rules
;; triggering unintentionally.
((match "else" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "elsif" "if")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "end" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((n-p-gp nil "then\\|else\\|elsif" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
;; case expression: when, in_clause, and else are all
;; children of case. when and in_clause have pattern and
;; body as fields. body has "then" and then the statements.
;; i.e. the statements are not children of when but then.
;; But for the statements are children of else.
((match "when" "case")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "in_clause" "case")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "else" "case")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "end" "case")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((n-p-gp nil "then" "when") grand-parent ruby-indent-level)
((n-p-gp nil "then" "in_clause") grand-parent ruby-indent-level)
((n-p-gp nil "else" "case") parent ruby-indent-level)
;; The beauty of inconsistency :-)
;; while / until have only "do" as a child. The "end" is a
;; child of "do".
((n-p-gp "end" "do" "while\\|until")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) 0)
((n-p-gp nil "do" "while\\|until")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
;; begin can have rescue, ensure, else, and end.
;; statements are a child of begin. rescue, ensure, else,
;; and end are also children of begin. rescue has a then
;; as a child thus statements will be grand children of
;; rescue.
((n-p-gp nil "then" "rescue")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
((n-p-gp nil "ensure\\|else" "begin")
(ruby-ts--align-keywords ruby-ts--parent-node) ruby-indent-level)
((match "rescue\\|ensure\\|else\\|end" "begin")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((parent-is "begin") ;last
(ruby-ts--align-keywords ruby-ts--parent-node) ruby-indent-level)
;; for ... I don't think I have ever used a for loop in
;; Ruby. The "in" (not an in_clause) and "do" are
;; children. The statements are children of the "do".
;; And, of course, the "end" is a child of the "do".
((n-p-gp "end" "do" "for")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) 0)
((n-p-gp nil "do" "for")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
;; method has a "body_statement" and the "end" as children.
;; The body_statement can have rescue, ensure, and else as
;; well as statements. Note that the first statement of a
;; body_statement hits the node as "body_statement" and not
;; as the assignment, etc.
((match "end" ,ruby-ts--method-regex)
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((n-p-gp "\\`\\(rescue\\|ensure\\|else\\)\\'" "body_statement" ,ruby-ts--method-regex)
(ruby-ts--align-keywords ruby-ts--grand-parent-node) 0)
((n-p-gp nil "rescue\\|ensure\\|else" "body_statement") parent ruby-indent-level)
((match "body_statement" ,ruby-ts--method-regex) ;first statement
(ruby-ts--align-keywords ruby-ts--parent-node) ruby-indent-level)
((n-p-gp nil "body_statement" ,ruby-ts--method-regex) ;other statements
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
;; Quirk of the ruby parser: these "alignable" nodes don't
;; have the "container" child node when there are no
;; statements inside. Thus we have to have a separate rule
;; for the "empty if/unless/case/def" situation.
((match "\\`\\'" "\\`\\(?:if\\|unless\\|case\\|method\\)\\'")
(ruby-ts--align-keywords ruby-ts--parent-node) ruby-indent-level)
;; Chained calls:
;; if `ruby-align-chained-calls' is true, the first query
;; matches and the node is aligned under the first dot (.);
;; else the second query aligns
;; `ruby-indent-level' spaces in from the parent.
((and ruby-ts--align-chain-p (match "\\." "call")) ruby-ts--align-chain 0)
;; Obery ruby-method-call-indent, whether the dot is on
;; this line or the previous line.
((and (not ruby-ts--method-call-indent-p)
(or
(match "\\." "call")
(query "(call \".\" (identifier) @indent)")))
(ruby-ts--bol ruby-ts--statement-ancestor) ruby-indent-level)
((match "\\." "call") parent ruby-indent-level)
;; method parameters -- four styles:
;; 1) With paren, first arg on same line:
((and (query "(method_parameters \"(\" _ @indent)")
ruby-ts--same-line-params-p
(node-is ")"))
first-sibling 0)
((and (query "(method_parameters \"(\" _ @indent)")
ruby-ts--same-line-params-p)
first-sibling 1)
;; ;; 2) With paren, first arg on next line, ruby-method-params-indent eq t
;; ;; 3) With paren, first arg on next line, ruby-method-params-indent neq t
((and (query "(method_parameters \"(\" _ @indent)") (node-is ")")) ruby-ts--param-indent 0)
((query "(method_parameters \"(\" _ @indent)") ruby-ts--param-indent ruby-indent-level)
;; 4) No paren:
((parent-is "method_parameters") first-sibling 0)
;; Argument lists:
;; 1) With paren, 1st arg on same line
((and (query "(argument_list \"(\" _ @indent)")
ruby-ts--same-line-args-p
(node-is ")"))
first-sibling 0)
((and (query "(argument_list \"(\" _ @indent)")
ruby-ts--same-line-args-p)
first-sibling 1)
;; 2) With paren, 1st arg on next line
((and (query "(argument_list \"(\" _ @indent)")
(node-is ")"))
ruby-ts--parent-call-or-bol 0)
((or (query "(argument_list \"(\" _ @indent)")
;; No arguments yet; NODE is nil in that case.
(match "\\`\\'" "argument_list"))
ruby-ts--parent-call-or-bol ruby-indent-level)
;; 3) No paren, ruby-parenless-call-arguments-indent is t
((and ruby-ts--parenless-call-arguments-indent-p (parent-is "argument_list"))
first-sibling 0)
;; 4) No paren, ruby-parenless-call-arguments-indent is nil
((parent-is "argument_list")
(ruby-ts--bol ruby-ts--statement-ancestor) ruby-indent-level)
;; Old... probably too simple
((parent-is "block_parameters") first-sibling 1)
((and (not ruby-ts--after-op-indent-p)
(parent-is "binary\\|conditional"))
(ruby-ts--bol ruby-ts--statement-ancestor) ruby-indent-level)
((parent-is "binary")
ruby-ts--binary-indent-anchor 0)
((parent-is "conditional") parent ruby-indent-level)
;; ruby-mode does not touch these...
((match "bare_string" "string_array") no-indent 0)
;; hash and array. Note that the first sibling is the "{"
;; or "[". There is a special case where the hash is an
;; argument to a method. These need to be processed first.
((and ruby-ts--same-line-hash-array-p (match "}" "hash"))
first-sibling 0)
((and ruby-ts--same-line-hash-array-p (parent-is "hash"))
(nth-sibling 0 ruby-ts--true) 0)
((and ruby-ts--same-line-hash-array-p (match "]" "array"))
first-sibling 0)
((and ruby-ts--same-line-hash-array-p (parent-is "array"))
(nth-sibling 0 ruby-ts--true) 0)
((match "}" "hash") ruby-ts--parent-call-or-bol 0)
((parent-is "hash") ruby-ts--parent-call-or-bol ruby-indent-level)
((match "]" "^array") ruby-ts--parent-call-or-bol 0)
((parent-is "^array") ruby-ts--parent-call-or-bol ruby-indent-level)
((match ")" "string_array") ruby-ts--parent-call-or-bol 0)
((parent-is "pair") ruby-ts--parent-call-or-bol 0)
((match ")" "parenthesized_statements") parent-bol 0)
((parent-is "parenthesized_statements") parent-bol ruby-indent-level)
;; If the previous method isn't finished yet, this will get
;; the next method indented properly.
((n-p-gp ,ruby-ts--method-regex "body_statement" ,ruby-ts--class-or-module-regex)
(ruby-ts--bol ruby-ts--grand-parent-node) ruby-indent-level)
;; Match the end of a class / module
((match "end" ,ruby-ts--class-or-module-regex) parent 0)
;; A "do_block" has a "body_statement" child which has the
;; statements as children within it. The problem is that
;; the first statement starts at the same point as the
;; body_statement and so treesit-simple-indent is called
;; with node set to body_statement on the first statement
;; but with node set to the statement and parent set to
;; body_statement for all others. ... Fine. Be that way.
;; Ditto for "block" and "block_body"
((node-is "body_statement")
(ruby-ts--block-indent-anchor ruby-ts--parent-node)
ruby-indent-level)
((parent-is "body_statement")
(ruby-ts--block-indent-anchor ruby-ts--grand-parent-node)
ruby-indent-level)
((match "end" "do_block") (ruby-ts--block-indent-anchor ruby-ts--parent-node) 0)
((n-p-gp "block_body" "block" nil)
(ruby-ts--block-indent-anchor ruby-ts--parent-node)
ruby-indent-level)
((n-p-gp nil "block_body" "block")
(ruby-ts--block-indent-anchor ruby-ts--grand-parent-node)
ruby-indent-level)
((match "}" "block") (ruby-ts--block-indent-anchor ruby-ts--parent-node) 0)
;; Chained strings
((match "string" "chained_string") first-sibling 0)
;; Try and indent two spaces when all else fails.
(catch-all parent-bol ruby-indent-level))))
`((ruby . ,common))))