8

I would like to use 2-space indents all the time like:

sidekiq_options({
  retry: true
})

I've tried setting .emacs.d/init.el to:

(setq-default indent-tabs-mode nil)
(setq-default tab-width 2)
(setq indent-line-function 'insert-tab)

(setq ruby-deep-indent-paren nil)
(setq ruby-deep-indent-paren-style nil)

But I still get stuff looking like:

sidekiq_options({
                  retry: true
                })
zlotnika
  • 81
  • 4
  • Due to how Ruby parses code, you should be able to omit the braces for the last hash argument. Solves the question in a neat way :> – wasamasa Dec 16 '17 at 10:56

3 Answers3

1

I'm not a ruby user but you can try the following:

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)   ;; change this to 2 if that is the width
(setq indent-line-function 'insert-tab)
eflanigan00
  • 785
  • 4
  • 11
  • Yeah, I actually had those in there already (they just didn't seem to affect `ruby-mode`). – zlotnika Mar 02 '17 at 01:02
  • Inspect tab-width while you are in ruby-mode. Maybe some hook changed it. Likewise this code should be within your ruby-mode hook code. – jtgd Mar 03 '17 at 00:40
  • Also, it looks like maybe it's an issue with tab stops, since the tabbing looks much wider than 8. It also looks like it is trying to indent to line up with the {'s. It may not be strictly a tab WIDTH problem. – jtgd Mar 03 '17 at 00:45
0

All you should have to do is to set ruby-indent-level. For example (setq-local ruby-indent-level 2).

EDIT:

You can use enh-ruby-mode, installable from melpa, and (setq enh-ruby-deep-indent-paren nil).

This resulted in the following indenting:

sidekiq_options({
  retry: true
})
theldoria
  • 1,825
  • 1
  • 13
  • 25
  • I tried that - it doesn't help. It's not the indentation level that's the problem. It's the deep indentation. – zlotnika Jul 19 '17 at 03:50
  • You can mitigate it a bit by setting `(setq ruby-deep-indent-paren nil)`, but it will indent by 4 spaces, because of the `({`. – theldoria Jul 19 '17 at 04:49
0

Looking at the code of ruby-mode, it seems there's no way to configure it. A workaround is overriding function. Try the code below and see if it works:

(defun ruby-smie-rules (kind token)
  (pcase (cons kind token)
    (`(:elem . basic) ruby-indent-level)
    ;; "foo" "bar" is the concatenation of the two strings, so the second
    ;; should be aligned with the first.
    (`(:elem . args) (if (looking-at "\\s\"") 0))
    ;; (`(:after . ",") (smie-rule-separator kind))
    (`(:before . ";")
     (cond
      ((smie-rule-parent-p "def" "begin" "do" "class" "module" "for"
                           "while" "until" "unless"
                           "if" "then" "elsif" "else" "when"
                           "rescue" "ensure" "{")
       (smie-rule-parent ruby-indent-level))
      ;; For (invalid) code between switch and case.
      ;; (if (smie-parent-p "switch") 4)
      ))
    (`(:before . ,(or `"(" `"[" `"{"))
     (cond
      ((and (equal token "{")
            (not (smie-rule-prev-p "(" "{" "[" "," "=>" "=" "return" ";"))
            (save-excursion
              (forward-comment -1)
              (not (eq (preceding-char) ?:))))
       ;; Curly block opener.
       (ruby-smie--indent-to-stmt))
      ((smie-rule-hanging-p)
       ;; Treat purely syntactic block-constructs as being part of their parent,
       ;; when the opening token is hanging and the parent is not an
       ;; open-paren.
       (cond
        ((eq (car (smie-indent--parent)) t) nil)
        ;; When after `.', let's always de-indent,
        ;; because when `.' is inside the line, the
        ;; additional indentation from it looks out of place.
        ((smie-rule-parent-p ".")
         ;; Traverse up the call chain until the parent is not `.',
         ;; or `.' at indentation, or at eol.
         (while (and (not (ruby-smie--bosp))
                     (equal (nth 2 (smie-backward-sexp ".")) ".")
                     (not (ruby-smie--bosp)))
           (forward-char -1))
         (smie-indent-virtual))
        (t (smie-rule-parent))))))
    (`(:after . ,(or `"(" "[" "{"))
     ;; FIXME: Shouldn't this be the default behavior of
     ;; `smie-indent-after-keyword'?
     (save-excursion
       (smie-rule-parent)))
    (`(:before . " @ ")
     (save-excursion
       (skip-chars-forward " \t")
       (cons 'column (current-column))))
    (`(:before . "do") (ruby-smie--indent-to-stmt))
    (`(:before . ".")
     (if (smie-rule-sibling-p)
         (and ruby-align-chained-calls 0)
       (smie-backward-sexp ".")
       (cons 'column (+ (current-column)
                        ruby-indent-level))))
    (`(:before . ,(or `"else" `"then" `"elsif" `"rescue" `"ensure"))
     (smie-rule-parent))
    (`(:before . "when")
     ;; Align to the previous `when', but look up the virtual
     ;; indentation of `case'.
     (if (smie-rule-sibling-p) 0 (smie-rule-parent)))
    (`(:after . ,(or "=" "+" "-" "*" "/" "&&" "||" "%" "**" "^" "&"
                     "<=>" ">" "<" ">=" "<=" "==" "===" "!=" "<<" ">>"
                     "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" "|"
                     "<<=" ">>=" "&&=" "||=" "and" "or"))
     (and (smie-rule-parent-p ";" nil)
          (smie-indent--hanging-p)
          ruby-indent-level))
    (`(:after . ,(or "?" ":")) ruby-indent-level)
    (`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords)))
     (when (not (ruby--at-indentation-p))
       (if (ruby-smie--indent-to-stmt-p token)
           (ruby-smie--indent-to-stmt)
         (cons 'column (current-column)))))
    (`(:before . "iuwu-mod")
     (smie-rule-parent ruby-indent-level))
    ))

The part I edited is just below the FIXME, changing it to (smie-rule-parent), and it seemed to work for me.

Jesse
  • 1,984
  • 11
  • 19