module System.Console.Haskeline.RunCommand (runCommandLoop) where
import System.Console.Haskeline.Command
import System.Console.Haskeline.Term
import System.Console.Haskeline.LineState
import System.Console.Haskeline.Monads
import System.Console.Haskeline.Prefs
import System.Console.Haskeline.Key
import Control.Exception (SomeException)
import Control.Monad
import Control.Monad.Catch (handle, throwM)
runCommandLoop :: (CommandMonad m, MonadState Layout m, LineState s)
=> TermOps -> Prefix -> KeyCommand m s a -> s -> m a
runCommandLoop :: forall (m :: * -> *) s a.
(CommandMonad m, MonadState Layout m, LineState s) =>
TermOps -> Prefix -> KeyCommand m s a -> s -> m a
runCommandLoop tops :: TermOps
tops@TermOps{evalTerm :: TermOps -> forall (m :: * -> *). CommandMonad m => EvalTerm m
evalTerm = forall (m :: * -> *). CommandMonad m => EvalTerm m
e} Prefix
prefix KeyCommand m s a
cmds s
initState
= case EvalTerm m
forall (m :: * -> *). CommandMonad m => EvalTerm m
e of
EvalTerm forall a. n a -> m a
eval forall a. m a -> n a
liftE
-> n a -> m a
forall a. n a -> m a
eval (n a -> m a) -> n a -> m a
forall a b. (a -> b) -> a -> b
$ TermOps
-> forall (m :: * -> *) a.
CommandMonad m =>
(m Event -> m a) -> m a
withGetEvent TermOps
tops
((n Event -> n a) -> n a) -> (n Event -> n a) -> n a
forall a b. (a -> b) -> a -> b
$ (forall a. m a -> n a)
-> TermOps -> Prefix -> s -> KeyCommand m s a -> n Event -> n a
forall (m :: * -> *) (n :: * -> *) s a.
(Term n, CommandMonad n, MonadState Layout m, LineState s) =>
(forall b. m b -> n b)
-> TermOps -> Prefix -> s -> KeyCommand m s a -> n Event -> n a
runCommandLoop' m b -> n b
forall a. m a -> n a
liftE TermOps
tops Prefix
prefix s
initState
KeyCommand m s a
cmds
runCommandLoop' :: forall m n s a . (Term n, CommandMonad n,
MonadState Layout m, LineState s)
=> (forall b . m b -> n b) -> TermOps -> Prefix -> s -> KeyCommand m s a -> n Event
-> n a
runCommandLoop' :: forall (m :: * -> *) (n :: * -> *) s a.
(Term n, CommandMonad n, MonadState Layout m, LineState s) =>
(forall b. m b -> n b)
-> TermOps -> Prefix -> s -> KeyCommand m s a -> n Event -> n a
runCommandLoop' forall b. m b -> n b
liftE TermOps
tops Prefix
prefix s
initState KeyCommand m s a
cmds n Event
getEvent = do
let s :: LineChars
s = Prefix -> s -> LineChars
forall s. LineState s => Prefix -> s -> LineChars
lineChars Prefix
prefix s
initState
LineChars -> n ()
forall (m :: * -> *). Term m => LineChars -> m ()
drawLine LineChars
s
LineChars -> KeyMap (CmdM m (a, [Key])) -> n a
readMoreKeys LineChars
s (((s -> CmdM m a) -> CmdM m (a, [Key]))
-> KeyCommand m s a -> KeyMap (CmdM m (a, [Key]))
forall a b. (a -> b) -> KeyMap a -> KeyMap b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> (a, [Key])) -> CmdM m a -> CmdM m (a, [Key])
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (\a
x -> (a
x,[])) (CmdM m a -> CmdM m (a, [Key]))
-> ((s -> CmdM m a) -> CmdM m a)
-> (s -> CmdM m a)
-> CmdM m (a, [Key])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((s -> CmdM m a) -> s -> CmdM m a
forall a b. (a -> b) -> a -> b
$ s
initState)) KeyCommand m s a
cmds)
where
readMoreKeys :: LineChars -> KeyMap (CmdM m (a,[Key])) -> n a
readMoreKeys :: LineChars -> KeyMap (CmdM m (a, [Key])) -> n a
readMoreKeys LineChars
s KeyMap (CmdM m (a, [Key]))
next = do
event <- (SomeException -> n Event) -> n Event -> n Event
forall (m :: * -> *) e a.
(HasCallStack, MonadCatch m, Exception e) =>
(e -> m a) -> m a -> m a
handle (\(SomeException
e::SomeException) -> LineChars -> n ()
forall (m :: * -> *). Term m => LineChars -> m ()
moveToNextLine LineChars
s n () -> n Event -> n Event
forall a b. n a -> n b -> n b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> SomeException -> n Event
forall e a. (HasCallStack, Exception e) => e -> n a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM SomeException
e)
n Event
getEvent
case event of
ErrorEvent SomeException
e -> LineChars -> n ()
forall (m :: * -> *). Term m => LineChars -> m ()
moveToNextLine LineChars
s n () -> n a -> n a
forall a b. n a -> n b -> n b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> SomeException -> n a
forall e a. (HasCallStack, Exception e) => e -> n a
forall (m :: * -> *) e a.
(MonadThrow m, HasCallStack, Exception e) =>
e -> m a
throwM SomeException
e
Event
WindowResize -> do
(forall b. m b -> n b) -> TermOps -> LineChars -> n ()
forall (n :: * -> *) (m :: * -> *).
(Term n, MonadState Layout m) =>
(forall a. m a -> n a) -> TermOps -> LineChars -> n ()
drawReposition m a -> n a
forall b. m b -> n b
liftE TermOps
tops LineChars
s
LineChars -> KeyMap (CmdM m (a, [Key])) -> n a
readMoreKeys LineChars
s KeyMap (CmdM m (a, [Key]))
next
KeyInput [Key]
ks -> do
bound_ks <- (Key -> n [Key]) -> [Key] -> n [[Key]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM ((Prefs -> [Key]) -> n [Key]
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks ((Prefs -> [Key]) -> n [Key])
-> (Key -> Prefs -> [Key]) -> Key -> n [Key]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> Prefs -> [Key]
lookupKeyBinding) [Key]
ks
loopCmd s $ applyKeysToMap (concat bound_ks) next
ExternalPrint String
str -> do
LineChars -> String -> n ()
forall (m :: * -> *). Term m => LineChars -> String -> m ()
printPreservingLineChars LineChars
s String
str
LineChars -> KeyMap (CmdM m (a, [Key])) -> n a
readMoreKeys LineChars
s KeyMap (CmdM m (a, [Key]))
next
loopCmd :: LineChars -> CmdM m (a,[Key]) -> n a
loopCmd :: LineChars -> CmdM m (a, [Key]) -> n a
loopCmd LineChars
s (GetKey KeyMap (CmdM m (a, [Key]))
next) = LineChars -> KeyMap (CmdM m (a, [Key])) -> n a
readMoreKeys LineChars
s KeyMap (CmdM m (a, [Key]))
next
loopCmd LineChars
s (DoEffect (LineChange Prefix -> LineChars
_)
e :: CmdM m (a, [Key])
e@(DoEffect (LineChange Prefix -> LineChars
_) CmdM m (a, [Key])
_)) = LineChars -> CmdM m (a, [Key]) -> n a
loopCmd LineChars
s CmdM m (a, [Key])
e
loopCmd LineChars
s (DoEffect Effect
e CmdM m (a, [Key])
next) = do
t <- Prefix -> LineChars -> Effect -> n LineChars
forall (m :: * -> *).
(Term m, MonadReader Prefs m) =>
Prefix -> LineChars -> Effect -> m LineChars
drawEffect Prefix
prefix LineChars
s Effect
e
loopCmd t next
loopCmd LineChars
s (CmdM m (CmdM m (a, [Key]))
next) = m (CmdM m (a, [Key])) -> n (CmdM m (a, [Key]))
forall b. m b -> n b
liftE m (CmdM m (a, [Key]))
next n (CmdM m (a, [Key])) -> (CmdM m (a, [Key]) -> n a) -> n a
forall a b. n a -> (a -> n b) -> n b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= LineChars -> CmdM m (a, [Key]) -> n a
loopCmd LineChars
s
loopCmd LineChars
s (Result (a
x,[Key]
ks)) = do
IO () -> n ()
forall a. IO a -> n a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (TermOps -> [Key] -> IO ()
saveUnusedKeys TermOps
tops [Key]
ks)
LineChars -> n ()
forall (m :: * -> *). Term m => LineChars -> m ()
moveToNextLine LineChars
s
a -> n a
forall a. a -> n a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
printPreservingLineChars :: Term m => LineChars -> String -> m ()
printPreservingLineChars :: forall (m :: * -> *). Term m => LineChars -> String -> m ()
printPreservingLineChars LineChars
s String
str = do
LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> m ()
clearLine LineChars
s
[String] -> m ()
forall (m :: * -> *). Term m => [String] -> m ()
printLines ([String] -> m ()) -> (String -> [String]) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
lines (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
str
LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> m ()
drawLine LineChars
s
drawReposition :: (Term n, MonadState Layout m)
=> (forall a . m a -> n a) -> TermOps -> LineChars -> n ()
drawReposition :: forall (n :: * -> *) (m :: * -> *).
(Term n, MonadState Layout m) =>
(forall a. m a -> n a) -> TermOps -> LineChars -> n ()
drawReposition forall a. m a -> n a
liftE TermOps
tops LineChars
s = do
oldLayout <- m Layout -> n Layout
forall a. m a -> n a
liftE m Layout
forall s (m :: * -> *). MonadState s m => m s
get
newLayout <- liftIO (getLayout tops)
liftE (put newLayout)
when (oldLayout /= newLayout) $ reposition oldLayout s
drawEffect :: (Term m, MonadReader Prefs m)
=> Prefix -> LineChars -> Effect -> m LineChars
drawEffect :: forall (m :: * -> *).
(Term m, MonadReader Prefs m) =>
Prefix -> LineChars -> Effect -> m LineChars
drawEffect Prefix
prefix LineChars
s (LineChange Prefix -> LineChars
ch) = do
let t :: LineChars
t = Prefix -> LineChars
ch Prefix
prefix
LineChars -> LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> LineChars -> m ()
drawLineDiff LineChars
s LineChars
t
LineChars -> m LineChars
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return LineChars
t
drawEffect Prefix
_ LineChars
s Effect
ClearScreen = do
m ()
forall (m :: * -> *). Term m => m ()
clearLayout
LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> m ()
drawLine LineChars
s
LineChars -> m LineChars
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return LineChars
s
drawEffect Prefix
_ LineChars
s (PrintLines [String]
ls) = do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (LineChars
s LineChars -> LineChars -> Bool
forall a. Eq a => a -> a -> Bool
/= ([],[])) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> m ()
moveToNextLine LineChars
s
[String] -> m ()
forall (m :: * -> *). Term m => [String] -> m ()
printLines [String]
ls
LineChars -> m ()
forall (m :: * -> *). Term m => LineChars -> m ()
drawLine LineChars
s
LineChars -> m LineChars
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return LineChars
s
drawEffect Prefix
_ LineChars
s Effect
RingBell = m ()
forall (m :: * -> *). (Term m, MonadReader Prefs m) => m ()
actBell m () -> m LineChars -> m LineChars
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> LineChars -> m LineChars
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return LineChars
s
actBell :: (Term m, MonadReader Prefs m) => m ()
actBell :: forall (m :: * -> *). (Term m, MonadReader Prefs m) => m ()
actBell = do
style <- (Prefs -> BellStyle) -> m BellStyle
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Prefs -> BellStyle
bellStyle
case style of
BellStyle
NoBell -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
BellStyle
VisualBell -> Bool -> m ()
forall (m :: * -> *). Term m => Bool -> m ()
ringBell Bool
False
BellStyle
AudibleBell -> Bool -> m ()
forall (m :: * -> *). Term m => Bool -> m ()
ringBell Bool
True
applyKeysToMap :: Monad m => [Key] -> KeyMap (CmdM m (a,[Key]))
-> CmdM m (a,[Key])
applyKeysToMap :: forall (m :: * -> *) a.
Monad m =>
[Key] -> KeyMap (CmdM m (a, [Key])) -> CmdM m (a, [Key])
applyKeysToMap [] KeyMap (CmdM m (a, [Key]))
next = KeyMap (CmdM m (a, [Key])) -> CmdM m (a, [Key])
forall (m :: * -> *) a. KeyMap (CmdM m a) -> CmdM m a
GetKey KeyMap (CmdM m (a, [Key]))
next
applyKeysToMap (Key
k:[Key]
ks) KeyMap (CmdM m (a, [Key]))
next = case KeyMap (CmdM m (a, [Key]))
-> Key -> Maybe (KeyConsumed (CmdM m (a, [Key])))
forall a. KeyMap a -> Key -> Maybe (KeyConsumed a)
lookupKM KeyMap (CmdM m (a, [Key]))
next Key
k of
Maybe (KeyConsumed (CmdM m (a, [Key])))
Nothing -> Effect -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a. Effect -> CmdM m a -> CmdM m a
DoEffect Effect
RingBell (CmdM m (a, [Key]) -> CmdM m (a, [Key]))
-> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall a b. (a -> b) -> a -> b
$ KeyMap (CmdM m (a, [Key])) -> CmdM m (a, [Key])
forall (m :: * -> *) a. KeyMap (CmdM m a) -> CmdM m a
GetKey KeyMap (CmdM m (a, [Key]))
next
Just (Consumed CmdM m (a, [Key])
cmd) -> [Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a.
Monad m =>
[Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
applyKeysToCmd [Key]
ks CmdM m (a, [Key])
cmd
Just (NotConsumed CmdM m (a, [Key])
cmd) -> [Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a.
Monad m =>
[Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
applyKeysToCmd (Key
kKey -> [Key] -> [Key]
forall a. a -> [a] -> [a]
:[Key]
ks) CmdM m (a, [Key])
cmd
applyKeysToCmd :: Monad m => [Key] -> CmdM m (a,[Key])
-> CmdM m (a,[Key])
applyKeysToCmd :: forall (m :: * -> *) a.
Monad m =>
[Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
applyKeysToCmd [Key]
ks (GetKey KeyMap (CmdM m (a, [Key]))
next) = [Key] -> KeyMap (CmdM m (a, [Key])) -> CmdM m (a, [Key])
forall (m :: * -> *) a.
Monad m =>
[Key] -> KeyMap (CmdM m (a, [Key])) -> CmdM m (a, [Key])
applyKeysToMap [Key]
ks KeyMap (CmdM m (a, [Key]))
next
applyKeysToCmd [Key]
ks (DoEffect Effect
e CmdM m (a, [Key])
next) = Effect -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a. Effect -> CmdM m a -> CmdM m a
DoEffect Effect
e ([Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a.
Monad m =>
[Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
applyKeysToCmd [Key]
ks CmdM m (a, [Key])
next)
applyKeysToCmd [Key]
ks (CmdM m (CmdM m (a, [Key]))
next) = m (CmdM m (a, [Key])) -> CmdM m (a, [Key])
forall (m :: * -> *) a. m (CmdM m a) -> CmdM m a
CmdM (m (CmdM m (a, [Key])) -> CmdM m (a, [Key]))
-> m (CmdM m (a, [Key])) -> CmdM m (a, [Key])
forall a b. (a -> b) -> a -> b
$ (CmdM m (a, [Key]) -> CmdM m (a, [Key]))
-> m (CmdM m (a, [Key])) -> m (CmdM m (a, [Key]))
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ([Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a.
Monad m =>
[Key] -> CmdM m (a, [Key]) -> CmdM m (a, [Key])
applyKeysToCmd [Key]
ks) m (CmdM m (a, [Key]))
next
applyKeysToCmd [Key]
ks (Result (a
x,[Key]
ys)) = (a, [Key]) -> CmdM m (a, [Key])
forall (m :: * -> *) a. a -> CmdM m a
Result (a
x,[Key]
ys[Key] -> [Key] -> [Key]
forall a. [a] -> [a] -> [a]
++[Key]
ks)