elixir-editors / language-elixir

Elixir language support for the Atom editor.
Other
181 stars 40 forks source link

Lines -> Auto Indent (editor:auto-indent) misinterprets case branches #44

Open p-kraszewski opened 8 years ago

p-kraszewski commented 8 years ago

atom: ver 1.6.0-beta6-8bd4c99 language-elixir: ver 0.11.1

It seems auto-indent does not properly unindent branches of case.

Instead of

defmodule Demo do
  def demo(value) do
    case value do
      :one ->
        do_one
      :two ->
        do_two
      :three ->
        do_three
    end
  end
end

you get

defmodule Demo do
  def demo(value) do
    case value do
      :one ->
        do_one
        :two ->
          do_two
          :three ->
            do_three
          end
        end
      end
ramsay-t commented 8 years ago

I have the same problem. The most frustrating part is that it then throws off all the following statements' indentation because the 'end's are out, so after a few case statements my def statements are 40 characters in!

keathley commented 8 years ago

How should we distinguish between a new case and just a plain old new line?

For instance you might want to do something like this:

case value do
  :one ->
    do_one
    do_one_again
  :two ->
    do_two
end

The only distinguishing factor is the -> however we can't just de-indent lines that contain -> because it would break anonymous functions in case statements. We'll have to ignore anonymous functions for de-indenting purposes.

Any thoughts?

ramsay-t commented 8 years ago

I'm not sure, its an interesting question. How much parse/grammar information do you get from Atom?

Its lines that start "[pattern] ->" that need de-indenting. Even if they are part of an anonymous function they will want to be aligned back a bit, so:

case list do
         [] ->
            []
         [_|_] ->
            Enum.map(list
                  fn({:a,b}) ->
                        b+1
                     ({x,b}) ->
                        b-1
                  end)
end

(I haven't got the hang of this markdown system... )

It works in Emacs, so I would say: what do they do? But I can't read Lisp, so I'm not going to :)

Ramsay

keathley commented 8 years ago

The Emacs implementation has the ability to run real code so it isn't very analogous here. Atom works by creating regex rules for indenting and de-indenting. I'll keep looking for solutions here but unless someone has some better insight the solution is going to be non-trivial. We'll also need to make sure that this solution works for cond as well.

keathley commented 8 years ago

I've spent some time looking into how other languages implement this in atom. The majority of packages do 1 of 2 things:

1) They've implemented it the same way that we have (and have the same problems). The Elm package behaves in this same way for instance.

2) They don't indent new lines after case statements. This avoids the problem with re-indenting altogether but means that the user has to hit tab after they've added the new line.

Neither of these scenarios correctly accounts for re-indenting although the second tends to look slightly nicer.

I would like to completely solve this problem however its going to be hard. To give you an idea here are just a few of the rules:

case foo do
[] -> bar
end

Unfortunately I don't see a good way to solve this problem with the tools that Atom gives us. For the moment I'd rather optimize for the majority use case. If someone else wants to figure out how to make this work in Atom I'd be happy to take a look at it.

Let me know what you think. I'm open to other suggestions.