Skip to content

Indentation issues #1178

Open
Open
@geraldus

Description

@geraldus

We have a lot of issues related to indentation and a lot of efforts to fix this. However, having done so much job we still struggling with this. Maybe we are doing something wrong and should re-think this question a bit deeper?

I think this is because Haskell itself quite complex and flexible in question of indentation. It allows programmers many valid ways to indent the code, and trying to predict what is the best indentation choice for every single haskeller seems to be very complicated task.

Here are some examples.

Data type decalrations

-- some people prefer this style
data ABC = A
    | B
    | C
-- other may prefer this one
data ABC 
    = A
    | B
    | C
-- another example
data ABC = A
         | B
         | C

do keyword

action = do
    foo
    bar

action =
    do bar
       baz

Function arguments

foobar baz
    quux
    norf

foobar
  baz quux norf

foobar
  baz
  quux
  norf

foobar baz quux
       norf

There is no reliable way to predict correct indentation position user expects for all cases. Sticking indentation to single style and omitting other looks like compliment some people and discriminate others. Indentation should not be based on style, but on code validity from Haskell perspective.

So, maybe we should dramatically simplify indentation? Here some of my thoughts:

  • if several previous lines are identically aligned at some column pick this columns as default indentation for new line
main = do
  foo
  bar
  _
main =
  do foo
     bar
     _

data A = A { a :: ()
           , b :: ()
           _
data A = A { a :: (),
             b :: (),
             _
data A = A
  { a :: (),
  , b :: ()
  _
  • indent newlines one step further based on tab width in cases of inner blocks
main = do
    _
main =
    _
data A =
    _
data A = A { a :: ()
    _
functionA = functionB (
    _
data A = A
_
  • avoid any "smart" tries to predict preferred indentation position when cycling, rather combine positions based on tab width with columns where words starts on previous line
-- _ is tab width based step (in this example 4)
-- . is word beginning step
function = foobar baz quux
_   _   _. ._   _ . _ . _

Not sure what default should be picked in these cases

main = someFunc
?   ?
main = somFunc foo
?   ?          ?

What else is needed?

We can also support possibility to write "smart" indentation backends for different styles for those who really interested in, it is possible to provide a special haskell-indentation-hook which supposes to be a list of functions taking current buffer and maybe a line number and return a list of indentation positions. Then we can define default indentation step provider and allow to override it.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions