jcsalomon / smarttabs

Emacs smart tabs - indent with tabs, align with spaces!
http://www.emacswiki.org/emacs/SmartTabs
114 stars 20 forks source link

Ruby: indentation is inserting tabs inappropriately. #32

Open rye opened 10 years ago

rye commented 10 years ago

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

jcsalomon commented 10 years ago

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.

rye commented 10 years ago

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.

jcsalomon commented 9 years ago

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

rye commented 9 years ago

Well, I know that ruby-indent-line works correctly, and smie-indent-line does not.

rye commented 9 years ago

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.

rye commented 9 years ago

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.

rye commented 9 years ago

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.

rye commented 9 years ago

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?

jcsalomon commented 9 years ago

I would prefer a patch that included this within the Ruby set-up; either on its own or within the Ruby mode hook.

scast commented 8 years ago

Thanks @rye for the fix. This should be indeed documented.