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))))