I'm writing a REPL in Haskell. The basic idea looks like this:
repl :: IO ()
repl = do putStr ">> "
hFlush stdout
input <- getLine
...
repl
I'd like to mimic some GHCi behaviour that when CTRL-C is pressed, the REPL discards the current line and starts a new empty line for user input. It has come to my mind that SIGINT raises UserInterrupt of AsyncException, which can be handled by catch. Therefore some modifications on the input line:
repl :: IO ()
repl = do putStr ">> "
hFlush stdout
input <- getLine `catch` handleCC
repl
handleCC :: AsyncException -> IO String
handleCC _ = do putStr "\n>> "
hFlush stdout
getLine `catch` handleCC
Within handleCC, AsyncException will be handled once more by recursion, so surely I can interrupt the REPL infinite times, right...?
Of course I can't; a second CTRL-C still terminates the REPL. But why?
>> something^C
>> another^C
[Process exited 130]