
module Igor2.UI.REPLoop(REPL(..), readEvalPrintLoop) where

import Control.Monad.Trans
import System.Console.Haskeline

data REPL s = REPL {
    repl_init :: IO (String, s),                -- prompt and initial state
    repl_eval :: s -> String -> IO (Bool, s),   -- quit flag and new state
    repl_exit :: s -> IO ()
    }

readEvalPrintLoop :: REPL s -> IO ()
readEvalPrintLoop p = do
    (prompt, state) <- repl_init p
    let loop s = (do 
        minput <- getInputLine prompt
        case minput of
          Nothing    -> loop s
          Just input -> do 
            (quit, s') <- handleInterrupt 
                            (outputStrLn " Interrupted" >> return (False, s))
                            (withInterrupt $ lift $ repl_eval p s input)
            if quit then lift $ repl_exit p s'
              else do loop s'
        )
    runInputT defaultSettings (loop state)
