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