module System.Console.Haskeline.IO(
InputState(),
initializeInput,
closeInput,
cancelInput,
queryInput
) where
import System.Console.Haskeline hiding (completeFilename)
import Control.Concurrent
import Control.Exception (finally)
import Control.Monad.IO.Class
data Request = forall a . Request (InputT IO a) (MVar a)
data InputState = HD {InputState -> ThreadId
forkedThread :: ThreadId,
InputState -> MVar (Maybe Request)
requestVar :: MVar (Maybe Request),
InputState -> MVar ()
subthreadFinished :: MVar ()
}
initializeInput :: Settings IO -> IO InputState
initializeInput :: Settings IO -> IO InputState
initializeInput Settings IO
settings = do
MVar (Maybe Request)
reqV <- IO (MVar (Maybe Request))
forall a. IO (MVar a)
newEmptyMVar
MVar ()
finished <- IO (MVar ())
forall a. IO (MVar a)
newEmptyMVar
ThreadId
tid <- IO () -> IO ThreadId
forkIO (Settings IO -> MVar (Maybe Request) -> MVar () -> IO ()
runHaskeline Settings IO
settings MVar (Maybe Request)
reqV MVar ()
finished)
InputState -> IO InputState
forall (m :: * -> *) a. Monad m => a -> m a
return HD :: ThreadId -> MVar (Maybe Request) -> MVar () -> InputState
HD {requestVar :: MVar (Maybe Request)
requestVar = MVar (Maybe Request)
reqV, forkedThread :: ThreadId
forkedThread = ThreadId
tid,
subthreadFinished :: MVar ()
subthreadFinished = MVar ()
finished}
runHaskeline :: Settings IO -> MVar (Maybe Request) -> MVar () -> IO ()
runHaskeline :: Settings IO -> MVar (Maybe Request) -> MVar () -> IO ()
runHaskeline Settings IO
settings MVar (Maybe Request)
reqV MVar ()
finished = Settings IO -> InputT IO () -> IO ()
forall (m :: * -> *) a.
(MonadIO m, MonadMask m) =>
Settings m -> InputT m a -> m a
runInputT Settings IO
settings InputT IO ()
loop
IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO a
`finally` MVar () -> () -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar ()
finished ()
where
loop :: InputT IO ()
loop = do
Maybe Request
mf <- IO (Maybe Request) -> InputT IO (Maybe Request)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe Request) -> InputT IO (Maybe Request))
-> IO (Maybe Request) -> InputT IO (Maybe Request)
forall a b. (a -> b) -> a -> b
$ MVar (Maybe Request) -> IO (Maybe Request)
forall a. MVar a -> IO a
takeMVar MVar (Maybe Request)
reqV
case Maybe Request
mf of
Maybe Request
Nothing -> () -> InputT IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just (Request InputT IO a
f MVar a
var) -> InputT IO a
f InputT IO a -> (a -> InputT IO ()) -> InputT IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO () -> InputT IO ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> InputT IO ()) -> (a -> IO ()) -> a -> InputT IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MVar a -> a -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar a
var InputT IO () -> InputT IO () -> InputT IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> InputT IO ()
loop
closeInput :: InputState -> IO ()
closeInput :: InputState -> IO ()
closeInput InputState
hd = MVar (Maybe Request) -> Maybe Request -> IO ()
forall a. MVar a -> a -> IO ()
putMVar (InputState -> MVar (Maybe Request)
requestVar InputState
hd) Maybe Request
forall a. Maybe a
Nothing IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MVar () -> IO ()
forall a. MVar a -> IO a
takeMVar (InputState -> MVar ()
subthreadFinished InputState
hd)
cancelInput :: InputState -> IO ()
cancelInput :: InputState -> IO ()
cancelInput InputState
hd = ThreadId -> IO ()
killThread (InputState -> ThreadId
forkedThread InputState
hd) IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> MVar () -> IO ()
forall a. MVar a -> IO a
takeMVar (InputState -> MVar ()
subthreadFinished InputState
hd)
queryInput :: InputState -> InputT IO a -> IO a
queryInput :: forall a. InputState -> InputT IO a -> IO a
queryInput InputState
hd InputT IO a
f = do
MVar a
var <- IO (MVar a)
forall a. IO (MVar a)
newEmptyMVar
MVar (Maybe Request) -> Maybe Request -> IO ()
forall a. MVar a -> a -> IO ()
putMVar (InputState -> MVar (Maybe Request)
requestVar InputState
hd) (Request -> Maybe Request
forall a. a -> Maybe a
Just (InputT IO a -> MVar a -> Request
forall a. InputT IO a -> MVar a -> Request
Request InputT IO a
f MVar a
var))
MVar a -> IO a
forall a. MVar a -> IO a
takeMVar MVar a
var