Better handling of interrupts in REPL
This commit is contained in:
parent
c6a7835a6f
commit
09eedfb609
@ -15,7 +15,7 @@ evalSingle env term
|
||||
Just existingValue
|
||||
| existingValue == evalAST env body -> env
|
||||
| otherwise -> errorWithoutStackTrace $
|
||||
"Unable to rebind immutable identifier: '" ++ name
|
||||
"Unable to rebind immutable identifier: " ++ name
|
||||
Nothing ->
|
||||
let res = evalAST env body
|
||||
in Map.insert "!result" res (Map.insert name res env)
|
||||
|
@ -59,7 +59,7 @@ main = do
|
||||
case args of
|
||||
Repl -> do
|
||||
putStrLn "Welcome to the tricu REPL"
|
||||
putStrLn "You can exit with `CTRL+D` or the `:_exit` command.`"
|
||||
putStrLn "You can exit with `CTRL+D` or the `!exit` command.`"
|
||||
repl Map.empty
|
||||
Evaluate { file = filePaths, form = form } -> do
|
||||
result <- case filePaths of
|
||||
|
47
src/REPL.hs
47
src/REPL.hs
@ -8,6 +8,7 @@ import Research
|
||||
|
||||
import Control.Exception (SomeException, catch)
|
||||
import Control.Monad.IO.Class (liftIO)
|
||||
import Control.Monad.Catch (handle, MonadCatch)
|
||||
import Data.Char (isSpace)
|
||||
import Data.List (dropWhile, dropWhileEnd, intercalate)
|
||||
import System.Console.Haskeline
|
||||
@ -15,33 +16,37 @@ import System.Console.Haskeline
|
||||
import qualified Data.Map as Map
|
||||
|
||||
repl :: Env -> IO ()
|
||||
repl env = runInputT defaultSettings (loop env)
|
||||
repl env = runInputT defaultSettings (withInterrupt (loop env))
|
||||
where
|
||||
loop :: Env -> InputT IO ()
|
||||
loop env = do
|
||||
loop env = handle (interruptHandler env) $ do
|
||||
minput <- getInputLine "tricu < "
|
||||
if
|
||||
| Nothing <- minput -> outputStrLn "Exiting tricu"
|
||||
| Just s <- minput, strip s == "!exit" -> outputStrLn "Exiting tricu"
|
||||
| Just s <- minput, strip s == "" -> do
|
||||
outputStrLn ""
|
||||
loop env
|
||||
| Just s <- minput, strip s == "!import" -> do
|
||||
path <- getInputLine "File path to load < "
|
||||
if
|
||||
| Nothing <- path -> do
|
||||
outputStrLn "No input received; stopping import."
|
||||
loop env
|
||||
| Just p <- path -> do
|
||||
loadedEnv <- liftIO $ evaluateFileWithContext env (strip p) `catch` \e -> errorHandler env e
|
||||
loop $ Map.delete "!result" (Map.union loadedEnv env)
|
||||
| Just s <- minput -> do
|
||||
if
|
||||
| take 2 s == "--" -> loop env
|
||||
| otherwise -> do
|
||||
case minput of
|
||||
Nothing -> outputStrLn "Exiting tricu"
|
||||
Just s
|
||||
| strip s == "!exit" -> outputStrLn "Exiting tricu"
|
||||
| strip s == "" -> loop env
|
||||
| strip s == "!import" -> do
|
||||
path <- getInputLine "File path to load < "
|
||||
case path of
|
||||
Nothing -> do
|
||||
outputStrLn "No input received; stopping import."
|
||||
loop env
|
||||
Just p -> do
|
||||
loadedEnv <- liftIO $ evaluateFileWithContext env
|
||||
(strip p) `catch` \e -> errorHandler env e
|
||||
loop $ Map.delete "!result" (Map.union loadedEnv env)
|
||||
| take 2 s == "--" -> loop env
|
||||
| otherwise -> do
|
||||
newEnv <- liftIO $ processInput env s `catch` errorHandler env
|
||||
loop newEnv
|
||||
|
||||
interruptHandler :: Env -> Interrupt -> InputT IO ()
|
||||
interruptHandler env _ = do
|
||||
outputStrLn "Interrupted with CTRL+C\n\
|
||||
\You can use the !exit command or CTRL+D to exit"
|
||||
loop env
|
||||
|
||||
processInput :: Env -> String -> IO Env
|
||||
processInput env input = do
|
||||
let asts = parseTricu input
|
||||
|
@ -26,6 +26,7 @@ executable tricu
|
||||
base >=4.7
|
||||
, cmdargs
|
||||
, containers
|
||||
, exceptions
|
||||
, haskeline
|
||||
, megaparsec
|
||||
, mtl
|
||||
@ -52,6 +53,7 @@ test-suite tricu-tests
|
||||
base
|
||||
, cmdargs
|
||||
, containers
|
||||
, exceptions
|
||||
, haskeline
|
||||
, megaparsec
|
||||
, mtl
|
||||
|
Loading…
x
Reference in New Issue
Block a user