Allow returning remaining-non-childcommand input

more specifically, the part of the input that is not part of any
successfully parsed subcommand invocation. "remaining" is not
completely accurate because this works even when all input
is processed.
pull/5/head
Lennart Spitzner 2016-12-30 22:02:32 +01:00
parent 04cb0bdea5
commit a3ff58c682
1 changed files with 41 additions and 10 deletions

View File

@ -29,7 +29,9 @@ module UI.Butcher.Monadic.Core
, reorderStop , reorderStop
, cmdCheckParser , cmdCheckParser
, cmdRunParser , cmdRunParser
, cmdRunParserExt
, cmdRunParserA , cmdRunParserA
, cmdRunParserAExt
) )
where where
@ -319,6 +321,9 @@ cmdCheckParser mTopLevel cmdParser
monadMisuseError = error "CmdParser definition error - used Monad powers where only Applicative/Arrow is allowed" monadMisuseError = error "CmdParser definition error - used Monad powers where only Applicative/Arrow is allowed"
newtype PastCommandInput = PastCommandInput Input
cmdRunParser cmdRunParser
:: Maybe String :: Maybe String
-> Input -> Input
@ -328,6 +333,14 @@ cmdRunParser mTopLevel inputInitial cmdParser
= runIdentity = runIdentity
$ cmdRunParserA mTopLevel inputInitial cmdParser $ cmdRunParserA mTopLevel inputInitial cmdParser
cmdRunParserExt
:: Maybe String
-> Input
-> CmdParser Identity out ()
-> (CommandDesc (), Input, Either ParsingError (CommandDesc out))
cmdRunParserExt mTopLevel inputInitial cmdParser
= runIdentity
$ cmdRunParserAExt mTopLevel inputInitial cmdParser
cmdRunParserA :: forall f out cmdRunParserA :: forall f out
. Applicative f . Applicative f
@ -337,7 +350,16 @@ cmdRunParserA :: forall f out
-> f ( CommandDesc () -> f ( CommandDesc ()
, Either ParsingError (CommandDesc out) , Either ParsingError (CommandDesc out)
) )
cmdRunParserA mTopLevel inputInitial cmdParser cmdRunParserA mTopLevel inputInitial cmdParser =
(\(x, _, z) -> (x, z)) <$> cmdRunParserAExt mTopLevel inputInitial cmdParser
cmdRunParserAExt
:: forall f out . Applicative f
=> Maybe String
-> Input
-> CmdParser f out ()
-> f (CommandDesc (), Input, Either ParsingError (CommandDesc out))
cmdRunParserAExt mTopLevel inputInitial cmdParser
= runIdentity = runIdentity
$ MultiRWSS.runMultiRWSTNil $ MultiRWSS.runMultiRWSTNil
$ (<&> captureFinal) $ (<&> captureFinal)
@ -345,15 +367,17 @@ cmdRunParserA mTopLevel inputInitial cmdParser
$ MultiRWSS.withMultiStateA cmdParser $ MultiRWSS.withMultiStateA cmdParser
$ MultiRWSS.withMultiStateSA (StackBottom []) $ MultiRWSS.withMultiStateSA (StackBottom [])
$ MultiRWSS.withMultiStateSA inputInitial $ MultiRWSS.withMultiStateSA inputInitial
$ MultiRWSS.withMultiStateSA (PastCommandInput inputInitial)
$ MultiRWSS.withMultiStateSA initialCommandDesc $ MultiRWSS.withMultiStateSA initialCommandDesc
$ processMain cmdParser $ processMain cmdParser
where where
initialCommandDesc = emptyCommandDesc initialCommandDesc = emptyCommandDesc
{ _cmd_mParent = mTopLevel <&> \n -> (n, emptyCommandDesc) } { _cmd_mParent = mTopLevel <&> \n -> (n, emptyCommandDesc) }
captureFinal :: ([String], (CmdDescStack, (Input, (CommandDesc out, f())))) captureFinal
-> f (CommandDesc (), Either ParsingError (CommandDesc out)) :: ([String], (CmdDescStack, (Input, (PastCommandInput, (CommandDesc out, f())))))
captureFinal (errs, (descStack, (inputRest, (cmd, act)))) = -> f (CommandDesc (), Input, Either ParsingError (CommandDesc out))
act $> (() <$ cmd', res) captureFinal (errs, (descStack, (inputRest, (PastCommandInput pastCmdInput, (cmd, act))))) =
act $> (() <$ cmd', pastCmdInput, res)
where where
errs' = errs ++ inputErrs ++ stackErrs errs' = errs ++ inputErrs ++ stackErrs
inputErrs = case inputRest of inputErrs = case inputRest of
@ -372,7 +396,7 @@ cmdRunParserA mTopLevel inputInitial cmdParser
-> MultiRWSS.MultiRWS -> MultiRWSS.MultiRWS
'[] '[]
'[[String]] '[[String]]
'[CommandDesc out, Input, CmdDescStack, CmdParser f out ()] '[CommandDesc out, PastCommandInput, Input, CmdDescStack, CmdParser f out ()]
(f ()) (f ())
processMain = \case processMain = \case
Pure () -> return $ pure $ () Pure () -> return $ pure $ ()
@ -492,10 +516,16 @@ cmdRunParserA mTopLevel inputInitial cmdParser
case mRest of case mRest of
Nothing -> do Nothing -> do
cmd :: CommandDesc out <- mGet cmd :: CommandDesc out <- mGet
subCmd <- MultiRWSS.withMultiStateS (emptyCommandDesc :: CommandDesc out) let (subCmd, subStack)
$ MultiRWSS.withMultiStateA (StackBottom []) = runIdentity
$ iterM processCmdShallow sub $ MultiRWSS.runMultiRWSTNil
mSet $ cmd { _cmd_children = (cmdStr, subCmd) : _cmd_children cmd } $ MultiRWSS.withMultiStateSA (emptyCommandDesc :: CommandDesc out)
$ MultiRWSS.withMultiStateS (StackBottom [])
$ iterM processCmdShallow sub
mSet $ cmd
{ _cmd_children = (cmdStr, postProcessCmd subStack subCmd)
: _cmd_children cmd
}
processMain next processMain next
Just rest -> do Just rest -> do
iterM processCmdShallow f iterM processCmdShallow f
@ -504,6 +534,7 @@ cmdRunParserA mTopLevel inputInitial cmdParser
prevStack :: CmdDescStack <- mGet prevStack :: CmdDescStack <- mGet
return $ postProcessCmd prevStack c return $ postProcessCmd prevStack c
mSet $ rest mSet $ rest
mSet $ PastCommandInput rest
mSet $ (emptyCommandDesc :: CommandDesc out) mSet $ (emptyCommandDesc :: CommandDesc out)
{ _cmd_mParent = Just (cmdStr, cmd) { _cmd_mParent = Just (cmdStr, cmd)
} }