repl: support multi-line input

```
Welcome to hnix 0.9.0. For help type :help

hnix> :paste
-- Entering multi-line mode. Press <Ctrl-D> to finish.
| { just
| =
| ''
| testing
| '';
| }
|
{ just = "<CYCLE>"; }
hnix>
Goodbye.
```

Closes #665.
This commit is contained in:
Richard Marko 2020-06-28 11:25:42 +02:00
parent 710bc84309
commit 59e65d094a
1 changed files with 27 additions and 15 deletions

View File

@ -7,6 +7,7 @@
directory for more details. directory for more details.
-} -}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiWayIf #-} {-# LANGUAGE MultiWayIf #-}
@ -51,30 +52,40 @@ import Control.Monad.Identity
import Control.Monad.Reader import Control.Monad.Reader
import Control.Monad.State.Strict import Control.Monad.State.Strict
import System.Console.Repline hiding ( options, prefix ) import System.Console.Repline ( CompletionFunc
import System.Environment , CompleterStyle (Prefix)
import System.Exit , ExitDecision(Exit)
, HaskelineT
, WordCompleter
)
import qualified System.Console.Repline
import qualified System.Exit
main :: (MonadNix e t f m, MonadIO m, MonadMask m) => m () main :: (MonadNix e t f m, MonadIO m, MonadMask m) => m ()
main = flip evalStateT initState main = flip evalStateT initState
$ evalRepl $ System.Console.Repline.evalRepl
(const $ return prefix) banner
cmd cmd
options options
(Just ':') (Just ':')
Nothing (Just "paste")
completer completer
welcomeText greeter
(return Exit) finalizer
where where
prefix = "hnix> " banner = pure . \case
welcomeText = System.Console.Repline.SingleLine -> "hnix> "
System.Console.Repline.MultiLine -> "| "
greeter =
liftIO liftIO
$ putStrLn $ putStrLn
$ "Welcome to hnix " $ "Welcome to hnix "
<> showVersion version <> showVersion version
<> ". For help type :help\n" <> ". For help type :help\n"
finalizer = do
liftIO $ putStrLn "Goodbye."
return Exit
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Types -- Types
@ -92,7 +103,7 @@ hoistErr :: (MonadIO m, MonadThrow m) => Result a -> Repl e t f m a
hoistErr (Success val) = return val hoistErr (Success val) = return val
hoistErr (Failure err) = do hoistErr (Failure err) = do
liftIO $ print err liftIO $ print err
abort System.Console.Repline.abort
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Execution -- Execution
@ -121,7 +132,7 @@ exec update source = do
case mVal of case mVal of
Left (NixException frames) -> do Left (NixException frames) -> do
lift $ lift $ liftIO . print =<< renderFrames @(NValue t f m) @t frames lift $ lift $ liftIO . print =<< renderFrames @(NValue t f m) @t frames
abort System.Console.Repline.abort
Right val -> do Right val -> do
-- Update the interpreter state -- Update the interpreter state
when update $ do when update $ do
@ -178,7 +189,7 @@ typeof args = do
-- :quit command -- :quit command
quit :: (MonadNix e t f m, MonadIO m) => a -> Repl e t f m () quit :: (MonadNix e t f m, MonadIO m) => a -> Repl e t f m ()
quit _ = liftIO exitSuccess quit _ = liftIO System.Exit.exitSuccess
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- Interactive Shell -- Interactive Shell
@ -187,7 +198,7 @@ quit _ = liftIO exitSuccess
-- Prefix tab completer -- Prefix tab completer
defaultMatcher :: MonadIO m => [(String, CompletionFunc m)] defaultMatcher :: MonadIO m => [(String, CompletionFunc m)]
defaultMatcher = defaultMatcher =
[(":load", fileCompleter) [(":load", System.Console.Repline.fileCompleter)
--, (":type" , values) --, (":type" , values)
] ]
@ -219,8 +230,9 @@ help
help _ = liftIO $ do help _ = liftIO $ do
putStrLn "Available commands:\n" putStrLn "Available commands:\n"
mapM_ putStrLn $ map (\o -> ":" ++ (fst o)) (options @e @t @f @m) mapM_ putStrLn $ map (\o -> ":" ++ (fst o)) (options @e @t @f @m)
putStrLn ":paste - enter multi-line mode"
completer completer
:: (MonadNix e t f m, MonadIO m) :: (MonadNix e t f m, MonadIO m)
=> CompleterStyle (StateT (IState t f m) m) => CompleterStyle (StateT (IState t f m) m)
completer = Prefix (wordCompleter comp) defaultMatcher completer = Prefix (System.Console.Repline.wordCompleter comp) defaultMatcher