packages feed

butcher 1.3.0.1 → 1.3.1.0

raw patch · 5 files changed

+84/−21 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ UI.Butcher.Monadic.Command: addAlternatives :: Typeable p => [(String, String -> Bool, CmdParser f out p)] -> CmdParser f out p
+ UI.Butcher.Monadic.Command: varPartDesc :: String -> PartDesc
- UI.Butcher.Monadic: cmd_out :: forall out_aiBG. Lens' (CommandDesc out_aiBG) (Maybe out_aiBG)
+ UI.Butcher.Monadic: cmd_out :: forall out_aiBH. Lens' (CommandDesc out_aiBH) (Maybe out_aiBH)
- UI.Butcher.Monadic: mapOut :: (outa -> outb) -> CmdParser f outa () -> CmdParser f outb ()
+ UI.Butcher.Monadic: mapOut :: (outa -> outb) -> CmdParser f outa a -> CmdParser f outb a
- UI.Butcher.Monadic.Types: cmd_out :: forall out_aiBG. Lens' (CommandDesc out_aiBG) (Maybe out_aiBG)
+ UI.Butcher.Monadic.Types: cmd_out :: forall out_aiBH. Lens' (CommandDesc out_aiBH) (Maybe out_aiBH)

Files

ChangeLog.md view
@@ -1,5 +1,9 @@ # Revision history for butcher +## 1.3.1.0  -- April 2018++* Add/Expose two more functions: addAlternatives and varPartDesc+ ## 1.3.0.1  -- April 2018  * Support ghc-8.4
butcher.cabal view
@@ -1,5 +1,5 @@ name:                butcher-version:             1.3.0.1+version:             1.3.1.0 synopsis:            Chops a command or program invocation into digestable pieces. description:         See the <https://github.com/lspitzner/butcher/blob/master/README.md README> (it is properly formatted on github). license:             BSD3
src/UI/Butcher/Monadic/Command.hs view
@@ -73,7 +73,9 @@   , addCmdPartMany   , addCmdPartInp   , addCmdPartManyInp+  , addAlternatives   , ManyUpperBound (..)+  , varPartDesc   ) where 
src/UI/Butcher/Monadic/Internal/Core.hs view
@@ -23,6 +23,7 @@   , addCmdHidden   , addNullCmd   , addCmdImpl+  , addAlternatives   , reorderStart   , reorderStop   , checkCmdParser@@ -31,6 +32,7 @@   , runCmdParserA   , runCmdParserAExt   , mapOut+  , varPartDesc   ) where @@ -236,6 +238,25 @@ addCmdHidden str sub =   liftF $ CmdParserChild (Just str) Hidden sub (pure ()) () +-- | Add a list of sub-parsers one of which will be selected and used based+-- on the provided predicate function. The input elements consist of:+-- a) a name used for the command description of the output,+-- b) a predicate function; the first True predicate determines which element+--    to apply+-- c) a CmdParser.+addAlternatives+  :: Typeable p+  => [(String, String -> Bool, CmdParser f out p)]+  -> CmdParser f out p+addAlternatives elems = liftF $ CmdParserAlternatives desc alts id+ where+  desc = PartAlts $ [PartVariable s | (s, _, _) <- elems]+  alts = [(a, b) | (_, a, b) <- elems]++-- | Create a simple PartDesc from a string.+varPartDesc :: String -> PartDesc+varPartDesc = PartVariable+ -- | Add a new nameless child command in the current context. Nameless means -- that this command matches the empty input, i.e. will always apply. -- This feature is experimental and CommandDesc pretty-printing might not@@ -334,13 +355,13 @@         <$ desc { _cmd_parts = Data.Foldable.toList descs }     StackLayer _ _ _ -> Left "unclosed ReorderStart or GroupStart"   processMain-    :: CmdParser f out ()+    :: CmdParser f out a     -> MultiRWSS.MultiRWST          '[]          '[]          '[CommandDesc out, CmdDescStack]          (Either String)-         ()+         a   processMain = \case     Pure x                      -> return x     Free (CmdParserHelp h next) -> do@@ -428,6 +449,21 @@       stackCur <- mGet       mSet $ StackLayer mempty "" stackCur       processMain next+    Free (CmdParserAlternatives desc alts nextF) -> do+      mModify (descStackAdd desc)+      states <- MultiRWSS.mGetRawS+      let go+            :: [(String -> Bool, CmdParser f out p)]+            -> MultiRWSS.MultiRWST+                 '[] '[] '[CommandDesc out, CmdDescStack] (Either String) p+          go [] = lift $ Left $ "Empty alternatives"+          go [(_, alt)] = processMain alt+          go ((_, alt1):altr) = do+            case MultiRWSS.runMultiRWSTNil $ MultiRWSS.withMultiStates states (processMain alt1) of+              Left{} -> go altr+              Right (p, states') -> MultiRWSS.mPutRawS states' $> p+      p <- go alts+      processMain $ nextF p    monadMisuseError :: a   monadMisuseError =@@ -530,7 +566,8 @@     res =       if null errs' then Right cmd' else Left $ ParsingError errs' inputRest   processMain-    :: CmdParser f out ()+    :: -- forall a+       CmdParser f out ()     -> MultiRWSS.MultiRWS          '[]          '[[String]]@@ -540,7 +577,7 @@            ()]          (f ())   processMain = \case-    Pure ()                     -> return $ pure $ ()+    Pure ()                     -> return $ pure ()     Free (CmdParserHelp h next) -> do       cmd :: CommandDesc out <- mGet       mSet $ cmd { _cmd_help = Just h }@@ -551,7 +588,7 @@         $ cmd { _cmd_synopsis = Just $ PP.fsep $ fmap PP.text $ List.words s }       processMain next     Free (CmdParserPeekDesc nextF) -> do-      parser                    <- mGet+      parser :: CmdParser f out () <- mGet       -- partialDesc :: CommandDesc out <- mGet       -- partialStack :: CmdDescStack <- mGet       -- run the rest without affecting the actual stack@@ -813,6 +850,18 @@           actRest <- processMain fr           return $ acts *> actRest         else monadMisuseError+    Free (CmdParserAlternatives desc alts nextF) -> do+      input :: Input <- mGet+      case input of+        InputString str+          | Just (_, sub) <- find (\(predicate, _sub) -> predicate str) alts ->+              processMain $ sub >>= nextF+        InputArgs (str:_)+          | Just (_, sub) <- find (\(predicate, _sub) -> predicate str) alts ->+              processMain $ sub >>= nextF+        _ -> do+          mTell ["could not parse any of " ++ getPartSeqDescPositionName desc]+          processMain $ nextF monadMisuseError    reorderPartGather     :: ( MonadMultiState Int m@@ -854,6 +903,7 @@     CmdParserReorderStart{} -> restCase     CmdParserGrouped{}      -> restCase     CmdParserGroupEnd{}     -> restCase+    CmdParserAlternatives{} -> restCase    where     restCase = do       mTell ["Did not find expected ReorderStop after the reordered parts"]@@ -873,7 +923,7 @@     Free (CmdParserPeekInput nextF) -> do       childrenGather $ nextF $ inputToString inputInitial     Free (CmdParserPeekDesc nextF) -> do-      parser                    <- mGet+      parser :: CmdParser f out () <- mGet       -- partialDesc :: CommandDesc out <- mGet       -- partialStack :: CmdDescStack <- mGet       -- run the rest without affecting the actual stack@@ -1010,8 +1060,8 @@   -- user needs to use check for that purpose instead.   processCmdShallow     :: (MonadMultiState (CommandDesc out) m, MonadMultiState CmdDescStack m)-    => CmdParserF f out (m ())-    -> m ()+    => CmdParserF f out (m a)+    -> m a   processCmdShallow = \case     CmdParserHelp h next -> do       cmd :: CommandDesc out <- mGet@@ -1062,15 +1112,13 @@     CmdParserGroupEnd next -> do       stackCur <- mGet       case stackCur of-        StackBottom{} -> do-          return ()-        StackLayer _descs "" _up -> do-          return ()+        StackBottom{} -> pure ()+        StackLayer _descs "" _up -> pure ()         StackLayer descs groupName up -> do           mSet $ descStackAdd             (PartRedirect groupName (PartSeq (Data.Foldable.toList descs)))             up-          next+      next     CmdParserReorderStop next -> do       stackCur <- mGet       case stackCur of@@ -1083,6 +1131,10 @@       stackCur <- mGet       mSet $ StackLayer mempty "" stackCur       next+    CmdParserAlternatives _ [] _ -> error "empty alternatives"+    CmdParserAlternatives desc ((_, alt):_) nextF -> do+      mModify (descStackAdd desc)+      nextF =<< iterM processCmdShallow alt    failureCurrentShallowRerun     :: ( m ~ MultiRWSS.MultiRWST r w s m0@@ -1093,7 +1145,7 @@        )     => m ()   failureCurrentShallowRerun = do-    parser                 <- mGet+    parser :: CmdParser f out () <- mGet     cmd :: CommandDesc out <-       MultiRWSS.withMultiStateS emptyCommandDesc         $ iterM processCmdShallow parser@@ -1161,7 +1213,7 @@   return r  -- | map over the @out@ type argument-mapOut :: (outa -> outb) -> CmdParser f outa () -> CmdParser f outb ()+mapOut :: (outa -> outb) -> CmdParser f outa a -> CmdParser f outb a mapOut f = hoistFree $ \case   CmdParserHelp     doc r     -> CmdParserHelp doc r   CmdParserSynopsis s   r     -> CmdParserSynopsis s r@@ -1175,11 +1227,15 @@     CmdParserPartManyInp bound desc fp fa fr   CmdParserChild s vis child act r ->     CmdParserChild s vis (mapOut f child) act r-  CmdParserImpl out r     -> CmdParserImpl (f out) r-  CmdParserReorderStart r -> CmdParserReorderStart r-  CmdParserReorderStop  r -> CmdParserReorderStop r-  CmdParserGrouped s r    -> CmdParserGrouped s r-  CmdParserGroupEnd r     -> CmdParserGroupEnd r+  CmdParserImpl out r               -> CmdParserImpl (f out) r+  CmdParserReorderStart r           -> CmdParserReorderStart r+  CmdParserReorderStop  r           -> CmdParserReorderStop r+  CmdParserGrouped s r              -> CmdParserGrouped s r+  CmdParserGroupEnd r               -> CmdParserGroupEnd r+  CmdParserAlternatives desc alts r -> CmdParserAlternatives+    desc+    [ (predicate, mapOut f sub) | (predicate, sub) <- alts ]+    r  -- cmdActionPartial :: CommandDesc out -> Either String out -- cmdActionPartial = maybe (Left err) Right . _cmd_out
src/UI/Butcher/Monadic/Internal/Types.hs view
@@ -80,6 +80,7 @@   |                          CmdParserReorderStop                              a   |                          CmdParserGrouped String                           a   |                          CmdParserGroupEnd                                 a+  | forall p . Typeable p => CmdParserAlternatives PartDesc [((String -> Bool), CmdParser f out p)] (p -> a)  -- | The CmdParser monad type. It is a free monad over some functor but users -- of butcher don't need to know more than that 'CmdParser' is a 'Monad'.