简体   繁体   中英

Emacs Haskell indentation

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?!

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 Mx 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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM