smarttabs
smarttabs copied to clipboard
Ruby: indentation is inserting tabs inappropriately.
It appears that the Ruby indentation configuration is broken. C indentation is conforming to the Smart Tabs concept, but the following (example) Ruby code gets indented incorrectly. I have tried removing all tab characters and reindenting the buffer, but the same problem persists. I have replaced tab characters with -> |
.
require "banana"
class Test
-> |class Banana
-> |-> |def initialize
-> |-> |-> |if (ENV["banana"] ||
-> |-> |-> |-> |ENV["chicken"] ||
-> |-> |-> |-> |ENV["cow"])
-> |-> |-> |-> |puts "happy"
-> |-> |-> |end
-> |-> |end
-> |end
end
I would expect it to instead do the following:
require "banana"
class Test
-> |class Banana
-> |-> |def initialize
-> |-> |-> |if (ENV["banana"] ||
-> |-> |-> |....ENV["chicken"] ||
-> |-> |-> |....ENV["cow"])
-> |-> |-> |-> |puts "happy"
-> |-> |-> |end
-> |-> |end
-> |end
end
In examining behavior in much larger and more complex reindentation situations, this problem is the same in many situations: it appears that ruby-indent-line
or ruby-indent-region
is interpreting what should be four spaces as a tab character and is converting to tab characters when it should not.
Is there something that I am missing? I am currently using a very recent version of the Git mirror of the Emacs BZR repository (the development version).
Either the smart-tabs-mode
set-up for Ruby is using the wrong variables, or the Ruby mode’s indentation logic is different to other languages’. In the first case, a patch should be relatively straightforward for someone familiar with Emacs’s Ruby mode; in the second, this mode cannot easily be made compatible with Ruby.
Patches are very welcome; analyses showing incompatibility less so, but still welcome.
I recently tested some possible fixes for this. One of them was to simply call the ruby-indent-line function to reindent lines. This works perfectly fine, indenting the aforementioned lines correctly. However, ruby-indent-line
is not the default indent-line-function
; smie-indent-line
is. To fix this, I just always (setq indent-line-function 'ruby-indent-line)
during ruby-mode-hook
.
Will switching ruby-indent-line
for smie-indent-line
present surprises to the user, and can this switch be included in the smart-tabs-create-language-advice ruby
lines? Or should smart-tabs-mode
be cleverer and use the correct indentation function? (I ask out of ignorance of Ruby-mode behavior; whichever you decide on and submit as a patch will be added.)
Well, I know that ruby-indent-line
works correctly, and smie-indent-line
does not.
It appears that the variable ruby-use-smie
in ruby-mode.el
determines if Ruby will use SMIE or not. If indent-line-function
is buffer-locally set to ruby-indent-line
, ruby-indent-line
is therefore (duh) used, and it works perfectly. I tried defining a hook to do this (pegged to ruby-mode-hook
), but it didn't work.
Unfortunately, I do not have much experience with EmacsLISP packaging, and so I'm somewhat at a loss as to what to do.
EDIT: Fixed words.
It appears that smart-tabs-advice
's modifications to the value of indent-line-function
are simply getting obliterated by SMIE, and so any modifications don't carry through to the end of all of the hooks that are called.
I fixed it in my personal configuration this morning, by adding (setq ruby-use-smie nil)
to my configuration. Perhaps this should be documented for others?
I would prefer a patch that included this within the Ruby set-up; either on its own or within the Ruby mode hook.
Thanks @rye for the fix. This should be indeed documented.