Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
p-kraszewski opened this issue Feb 25, 2016 · 5 comments
Assignees

Comments

@p-kraszewski
Copy link

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
Copy link

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
Copy link
Contributor

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
Copy link

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
Copy link
Contributor

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
Copy link
Contributor

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:

  • Lines in a case or cond block that include the patten foo -> (but not fn ->) should be de-indented in order to make everything line up correctly.
  • By default new lines after a do are indented. This means that our above logic needs to exclude the first case in each case block. Otherwise you'll end up with this:
case foo do
[] -> bar
end
  • We can still have edge cases with this manual indenting and de-indenting. For instance what happens when someone just hits backspace to add their next case statement? Our de-indenting logic has no way of knowing how many tabs deep the line should be and it will still de-indent the line. We've made the general user experience worse by trying to optimize for something that people just don't do nearly as often.

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.

@keathley keathley self-assigned this May 19, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants