Skip to content

Ideas for a better GHCi editing experience

I have a two annoyances when writing Haskell code in GHCi which I will enumerate here. While minor, I think if these were fixed there would be a marked improvement of the GHCi editing experience.

  1. Syntax/Keyword Highlighting.

Haskell has some very common keywords. Simply writing if, then, else, where, do, etc. in some color other than the default when not inside a string literal would be a huge improvement in my opinion, and might not be very difficult.

  1. Multiline editing

Writing multiline expressions in Haskell is somewhat difficult for four reasons. Firstly, to even start a multiline expression you must enter :{ end end it with :}. Secondly, GHCi does not attempt to automatically indent your code, which is usually (always?) required when writing a multiline expression. Thirdly, you cannot navigate the curor to previous lines to edit them. Lastly, pressing the up arrow on the keyboard shows the last line of the multiline expression which is useless because it's almost always :}.

My proposal is as follows.

  1. The issue of how to enter multiline mode without needing to enter :{ and exit it without needing :}.

Instead of entering multiline mode only when the user enters :{, we add the following additional criteria. When I discuss haskell keywords in here, assume I mean "while not in a string literal".

a) When the input code contains an odd number of unescaped quotation marks and ends in a backslash.

b) When the input code ends with where, let, in, if, then, else, do, of, case, or -> preceeded by and in the same level of parenthetical nesting of case.

c) When the input code contains a let that is not eventually followed by in, an if not followed by then, or a then not followed by else.

d) When the input code contains a case followed by of, not enclosed by parentheses.

e) When the input code contains a [ that is not followed by a ], or an ( that is not followed by a ).

f) When the input starts with two or more consecutive space-seperated tokens that do not contain haskell keywords (other than the backtick) followed by =.

g)

i) When the input contains a single token that is not a haskell keyword, followed by ::, ending in => or ->.

ii) When the input contains a single token that is not a haskell keyword, followed by ::, not ending in => or ->.

e) When the user hits shift-return instead of simply return, or hits return when there are non-whitespace characters after the cursor.

This should cover the majority of cases where it can be safely assumed one would want to enter multiline mode. Criterion f is intended to enter multiline mode when defining any function, to make it simple to define functions that use pattern matching. Criterion g is to make it simple to place a function signature right above a function definition.

In situations where multiline mode was not entered with :{, you should be able to exit it and submit your code to GHCi for execution by pressing return twice, or meta-return.

  1. The issue of GHCi not attempting to indent your code.

How to indent depends on the reason GHCi entered multiline mode. If GHCi entered multiline mode because the user entered :{, no indentation should take place. If the user is in multiline mode but their code does not match criteria a-f, the default indentation should be the same as the indentation on the previous line. If the line is just whitespace and the user presses enter, indentation should be the same as the previous line. For criteria a-f, here is how to respond (I've ordered these from greatest to least precedence I think they should take, but I could be entirely wrong here).

a) Indent to the same column as the last unescaped quotation mark. For bonus points add a backslash too.

b) Indent to two columns as the token that caused the activation of multiline mode.

c) Indent to the same column as the token that caused the activation of multiline mode.

d) Indent to the character after the final of not contained in parentheses

e) Indent to the column of the next non-whitespace character after ( or [, if one exists. Otherwise, indent one column farther than the (/[.

f) No indentation.

g)

i) Indent to the column of the first non-whitespace character after the ::

ii) No indentation.

e) No indentation

If the user is not editing the last line, use the code up to the point of their cursor for advice on how to indent.

  1. The issue of not being able to navigate the curor to previous lines in order to edit them when in multiline editing mode.

I think this would require a complete rewrite of the user interface for multiline editing, and I anticipate it would be the hardest part of this whole endevor. I don't have the knowledge to suggest how one might go about implementing it, though. If possible, pressing ctrl-c should cancel the current code and make a new Prelude> prompt.

  1. The issue of pressing up only displaying one line at a time.

See above.

I would be happy to try to implement some of these, but I have never contributed to GHC or GHCi before and would need some pointers on where to start (Either in here or in the #ghc irc channel).

Trac metadata
Trac field Value
Version 8.6.2
Type FeatureRequest
TypeOfFailure OtherFailure
Priority high
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Edited by Anchpop
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information