Reputation: 10095
Please help me set up proper indentation in Emacs haskell-mode
When I'm trying to type down something like ADT or a record, I'm getting on the wrong column after pressing <ENTER>
, and pressing <TAB>
won't switch to the right one until I enter either |
or ';'!
data MyADT = Oh
| Hi
| Hello
| <- the cursor is here again!
Trying to solve the problem I set
(define-key global-map (kbd "RET") 'reindent-then-newline-and-indent)
in my .emacs
file, but it won't indent the current line on pressing <enter>
too!
Another strange behaviour: indentation of case
oneChar c = case lookup c simpleEscapes of
| <- what? here?!
Upvotes: 23
Views: 4309
Reputation: 74430
Caveat: I'm not a Haskell user, so take this with a grain of salt.
When you press RET after the Hello
, Emacs doesn't know you're going to add a |
(quick search shows you can have other symbols). The Haskell folks have deemed the proper indentation to be lined up directly below the H
in Hello
. If the indentation were to automatically line up with the |
on the line above, then all the cases where you don't type a |
will result in improper indentation. Damned if you do, damned if you don't...
Other programming modes (C/C++, Lisp, Tcl, ...) have the same problem - they cannot know ahead of time what you're going to put on the next line, so the indentation my not be what you'd hoped for.
One solution is to use "electric" keys, which is to say that they insert characters and also force re-indentation. You could easily define | to be electric with the following code:
(defun haskell-electric-| ()
"it's electric! (insert | and indent as long as the | follows whitespace)"
(interactive)
(insert "|")
(if (string-match-p "^\\s-*|" (buffer-substring (line-beginning-position)
(point)))
(haskell-indentation-indent-line)))
(define-key haskell-mode-map "|" 'haskell-electric-|)
I added a check to ensure that the |
inserted is preceded by only whitespace, you can customize that however you want or remove the check altogether.
I presume there might also be other symbols in Haskell that would be worth making electric.
Upvotes: 4
Reputation: 5254
It sounds like you type <Enter>
and then "|
" and then <Tab>
. If I do that, I get the same results. But if I type <Enter>
and then <Tab>
and then <Tab>
again it automatically inserts the "|
" and lines it up correctly, like so:
data MyADT = Oh
| Hi
|<Cursor>
When I check my haskell-mode version using M-x eval-expression haskell-version <Enter>
I get "v2_4".
Emacs haskell-mode doesn't fully analyze the source code, so the "automatic" features are approximate, I think. Typing <Tab>
several times on a new line cycles through several possible indentations, and also sometimes inserts text like the "|
" for algebraic data types.
Upvotes: 9
Reputation: 10095
I commented the line
;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
And now I'm getting a good "tab" behavior: at least, it allows me to choose a column and does not tie down me to the one it likes. But no auto-indent at all annoys me a little bit, so I'm hoping it is a temporary solution
Upvotes: 3