sdiehl / repline

Haskeline wrapper for GHCi-like REPL interfaces
MIT License
107 stars 28 forks source link

0.4: Add support for multi-line commands #29

Closed basile-henry closed 4 years ago

basile-henry commented 4 years ago

While commands already work with multi-line inputs, the commands cannot distinguish between a space and newline character since the arguments the function receives are already split by word.

This commit changes this and provides the raw argument string to the command function.

basile-henry commented 4 years ago

To give a more concrete use case where we might want multi-line commands:

The Dhall REPL uses the :let command to add bindings to the environment. Dhall also has mutli-line strings, so in order to bind a multi-line string to a variable we can write the following:

> :let multiline = ''
|   Hello
|   World
|   ''

Before this PR, this unfortunately did not work (and didn't actually parse) because all the newlines got replaced by spaces.

sdiehl commented 4 years ago

Not sure how I feel about this. This forces all the command functions which previously pattern matched on [String] to now pattern match of String and rehydrate the words back into a list if needed. While it might be convenient in this example quite a lot of my existing users do something like this which would all have to be refactored after this patch.

symbols :: [[Char]] -> Repl ()
symbols [] = do
   ... -- no arguments
symbols [x] = do
  ... -- one arguments
symbols xs = do
  ... -- n arguments
symbols :: [Char] -> Repl ()
symbols arg = do
   case words arg of
      [] -> ...
      [x] -> ...
      xs -> ...
basile-henry commented 4 years ago

I understand your concern about changing this part of the API. My view of how the library is being used is very much biased by its use in the Dhall REPL, where basically every command ended up doing unwords on the arguments.

I had a quick look at repline's (public) reverse dependencies to see how the arguments were usually handled: https://packdeps.haskellers.com/reverse/repline

If we do want to keep the arguments split by words, here are a few possible API we could provide:

I am very much open to changing this PR if you like any of my suggestions or if you have other suggestions about what the API should look like. I think a good stable API is very valuable! :smile:

Note: If you are interested in just how much 0.4 + this PR requires to be changed here is the current draft PR for Dhall that implements this change https://github.com/dhall-lang/dhall-haskell/pull/1867

sdiehl commented 4 years ago

Ok, will just have to document migration from 0.3 to 0.4 well enough and it should be fine. I suppose some refactoring using words and unwords isn't that much overhead.