haskell / haskell/haskell-mode

Indentation issues

Open
#1,178 26 comments 1 reaction 0 assignees View on GitHub
discussion indentation
Dominant language
Emacs Lisp
Stars
1.4k
Forks
354
Avg merge
5d 10h
Merged PRs (30d)
2

Description

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

``` hs
-- 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

``` hs
action = do
foo
bar

action =
do bar
baz
```

Function arguments

``` hs
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

``` hs
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

``` hs
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

``` hs
-- _ 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

``` hs
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.

Contributor guide

Open the contributing guide

Research direction

No file, test, or entry point is named. Start by locating the existing Haskell indentation implementation and reading the 26-comment discussion to determine whether there is agreement on the proposed behavior. Done requires a concrete, accepted scope for indentation rules or configurable backends, plus defined tests for the examples in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
emacs, emacs-lisp, haskell
Domain
developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.