23

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?!
6
  • 1
    The case case is correct behavior. Commented Nov 13, 2010 at 3:15
  • 1
    If you press tab twice, it inserts a '|' in correct indentation. Commented Nov 13, 2010 at 8:11
  • if there is no | yet, it doesn't. So I have to type something in the line before pressing tab Commented Nov 13, 2010 at 15:04
  • @jrockwaym, even the first one can be considered correct by someone Commented Nov 13, 2010 at 15:05
  • 3
    Probably, what is needed is to implement some different indentation algorithm for different people. We need some emacs guru, here. Commented Nov 18, 2010 at 5:08

3 Answers 3

9
+75

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.

Sign up to request clarification or add additional context in comments.

Comments

4

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.

Comments

3

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.