[GHC] #15887: It would be very nice to have a better GHCi editing experience

GHC ghc-devs at haskell.org
Sun Nov 11 07:01:48 UTC 2018


#15887: It would be very nice to have a better GHCi editing experience
-------------------------------------+-------------------------------------
           Reporter:  Anchpop        |             Owner:  (none)
               Type:  feature        |            Status:  new
  request                            |
           Priority:  high           |         Milestone:  Research needed
          Component:  Compiler       |           Version:  8.6.2
           Keywords:  QoL            |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 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.

 2) 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`.

         2) 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.

         3) 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.

         4) 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).

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15887>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list