calamity-commands 0.1.3.0 → 0.2.0.0
raw patch · 15 files changed
+219/−213 lines, 15 filesdep ~polysemy-plugindep ~textPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: polysemy-plugin, text
API changes (from Hackage documentation)
- CalamityCommands.Context: constructContext :: forall msg_aFlx ctx_aFlv m'_aFlu a'_aFlw r_aFo7. MemberWithError (ConstructContext msg_aFlx ctx_aFlv m'_aFlu a'_aFlw) r_aFo7 => (Text, Command m'_aFlu ctx_aFlv a'_aFlw, Text) -> msg_aFlx -> Sem r_aFo7 (Maybe ctx_aFlv)
+ CalamityCommands.Context: constructContext :: forall msg_aF5w ctx_aF5u m'_aF5t a'_aF5v r_aF86. Member (ConstructContext msg_aF5w ctx_aF5u m'_aF5t a'_aF5v) r_aF86 => (Text, Command m'_aF5t ctx_aF5u a'_aF5v, Text) -> msg_aF5w -> Sem r_aF86 (Maybe ctx_aF5u)
- CalamityCommands.Internal.LocalWriter: llisten :: forall o_ajsg r_ajDx a_Xjsg. MemberWithError (LocalWriter o_ajsg) r_ajDx => Sem r_ajDx a_Xjsg -> Sem r_ajDx (o_ajsg, a_Xjsg)
+ CalamityCommands.Internal.LocalWriter: llisten :: forall o_ajlk r_ajwB a_Xjlk. Member (LocalWriter o_ajlk) r_ajwB => Sem r_ajwB a_Xjlk -> Sem r_ajwB (o_ajlk, a_Xjlk)
- CalamityCommands.Internal.LocalWriter: ltell :: forall o_ajsc r_ajDv. MemberWithError (LocalWriter o_ajsc) r_ajDv => o_ajsc -> Sem r_ajDv ()
+ CalamityCommands.Internal.LocalWriter: ltell :: forall o_ajlg r_ajwz. Member (LocalWriter o_ajlg) r_ajwz => o_ajlg -> Sem r_ajwz ()
- CalamityCommands.ParsePrefix: parsePrefix :: forall msg_aG9X r_aGaN. MemberWithError (ParsePrefix msg_aG9X) r_aGaN => msg_aG9X -> Sem r_aGaN (Maybe (Text, Text))
+ CalamityCommands.ParsePrefix: parsePrefix :: forall msg_aFSM r_aFTC. Member (ParsePrefix msg_aFSM) r_aFTC => msg_aFSM -> Sem r_aFTC (Maybe (Text, Text))
Files
- CalamityCommands.hs +7/−7
- CalamityCommands/Check.hs +5/−6
- CalamityCommands/Command.hs +8/−9
- CalamityCommands/CommandUtils.hs +9/−10
- CalamityCommands/Context.hs +6/−6
- CalamityCommands/Dsl.hs +38/−39
- CalamityCommands/Error.hs +21/−14
- CalamityCommands/Group.hs +9/−10
- CalamityCommands/Help.hs +40/−39
- CalamityCommands/ParsePrefix.hs +14/−10
- CalamityCommands/Parser.hs +28/−28
- CalamityCommands/Utils.hs +19/−20
- ChangeLog.md +4/−0
- README.md +7/−9
- calamity-commands.cabal +4/−6
CalamityCommands.hs view
@@ -65,7 +65,7 @@ handler is generic over the context used: @- h' :: 'CommandContext' 'Data.Functor.Identity.Identity' c ('Either' 'Data.Text.Lazy.Text' 'Int') => 'CommandHandler' 'Data.Functor.Identity.Identity' c ('Either' 'Data.Text.Lazy.Text' 'Int')+ h' :: 'CommandContext' 'Data.Functor.Identity.Identity' c ('Either' 'Data.Text.Text' 'Int') => 'CommandHandler' 'Data.Functor.Identity.Identity' c ('Either' 'Data.Text.Text' 'Int') h' = 'Data.Functor.Identity.runIdentity' . 'Polysemy.runFinal' $ do (h, _) <- 'buildCommands' $ do 'command' \@\'[Int, Int] "add" $ \ctx a b -> 'pure' $ 'Right' (a '+' b)@@ -91,9 +91,9 @@ the invoked command and runs it, returning the result. @- r :: 'Data.Text.Lazy.Text' -> 'Maybe' ('Either'- ('CmdInvokeFailReason' ('BasicContext' 'Data.Functor.Identity.Identity' ('Either' 'Data.Text.Lazy.Text' 'Int')))- ('BasicContext' 'Data.Functor.Identity.Identity' ('Either' 'Data.Text.Lazy.Text' 'Int'), 'Either' 'Data.Text.Lazy.Text' 'Int'))+ r :: 'Data.Text.Text' -> 'Maybe' ('Either'+ ('CmdInvokeFailReason' ('BasicContext' 'Data.Functor.Identity.Identity' ('Either' 'Data.Text.Text' 'Int')))+ ('BasicContext' 'Data.Functor.Identity.Identity' ('Either' 'Data.Text.Text' 'Int'), 'Either' 'Data.Text.Text' 'Int')) r = 'Data.Functor.Identity.runIdentity' . 'Polysemy.runFinal' . 'Polysemy.embedToFinal' . 'useBasicContext' . 'useConstantPrefix' "!" . 'processCommands' h' @ @@ -102,16 +102,16 @@ invoked successfully, and prints the error nicely if not. @- rm :: 'Data.Text.Lazy.Text' -> IO ()+ rm :: 'Data.Text.Text' -> IO () rm s = case r s of Just (Right (_, Right r)) -> print r Just (Right (_, Left h)) ->- 'Data.Text.Lazy.IO.putStrLn' h+ 'Data.Text.IO.putStrLn' h Just (Left ('CommandInvokeError' _ ('ParseError' t r))) ->- 'Data.Text.Lazy.IO.putStrLn' ("Parsing parameter " '<>' 'Data.Text.Lazy.fromStrict' t '<>' " failed with reason: " '<>' r)+ 'Data.Text.IO.putStrLn' ("Parsing parameter " '<>' t '<>' " failed with reason: " '<>' r) _ -> pure () @
CalamityCommands/Check.hs view
@@ -14,8 +14,7 @@ import Data.Generics.Labels () import Data.Maybe-import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T import GHC.Generics @@ -27,24 +26,24 @@ -} data Check m c = MkCheck { -- | The name of the check.- name :: S.Text+ name :: T.Text , -- | The callback for the check, returns Nothing if it passes, otherwise -- returns the reason for it not passing.- callback :: c -> m (Maybe L.Text)+ callback :: c -> m (Maybe T.Text) } deriving (Generic) {- | Given the name of a check and a callback in the 'P.Sem' monad, build a check by transforming the Polysemy action into an @m@ action. -}-buildCheck :: (Monad m, P.Member (P.Final m) r) => S.Text -> (c -> P.Sem r (Maybe L.Text)) -> P.Sem r (Check m c)+buildCheck :: (Monad m, P.Member (P.Final m) r) => T.Text -> (c -> P.Sem r (Maybe T.Text)) -> P.Sem r (Check m c) buildCheck name cb = do cb' <- bindSemToM cb let cb'' = fromMaybe (Just "failed internally") <.> cb' pure $ MkCheck name cb'' -- | Given the name of a check and a pure callback function, build a check.-buildCheckPure :: Monad m => S.Text -> (c -> Maybe L.Text) -> Check m c+buildCheckPure :: Monad m => T.Text -> (c -> Maybe T.Text) -> Check m c buildCheckPure name cb = MkCheck name (pure . cb) {- | Given an invokation context @c@, run a check and transform the result into an
CalamityCommands/Command.hs view
@@ -12,8 +12,7 @@ import Data.Kind (Type) import Data.List.NonEmpty (NonEmpty)-import Data.Text as S-import Data.Text.Lazy as L+import Data.Text as T import GHC.Generics @@ -21,10 +20,10 @@ import TextShow import qualified TextShow.Generic as TSG --- | A command, paremeterised over it's context+-- | A command, paremeterised over its context data Command (m :: Type -> Type) (c :: Type) (a :: Type) = forall p. Command- { names :: NonEmpty S.Text+ { names :: NonEmpty T.Text , parent :: Maybe (Group m c a) , -- | If this command is hidden hidden :: Bool@@ -33,20 +32,20 @@ , -- | A list of parameter metadata params :: [ParameterInfo] , -- | A function producing the \'help\' for the command.- help :: c -> L.Text+ help :: c -> T.Text , -- | A function that parses the context for the command, producing the input -- @a@ for the command. parser :: c -> m (Either CommandError p) , -- | A function that given the context and the input (@p@) of the command, -- performs the action of the command.- callback :: (c, p) -> m (Either L.Text a)+ callback :: (c, p) -> m (Either T.Text a) } data CommandS = CommandS- { names :: NonEmpty S.Text+ { names :: NonEmpty T.Text , params :: [ParameterInfo]- , parent :: Maybe S.Text- , checks :: [S.Text]+ , parent :: Maybe T.Text+ , checks :: [T.Text] , hidden :: Bool } deriving (Generic, Show)
CalamityCommands/CommandUtils.hs view
@@ -32,7 +32,6 @@ import qualified Data.List.NonEmpty as NE import Data.Maybe import qualified Data.Text as S-import qualified Data.Text.Lazy as L import qualified Polysemy as P import qualified Polysemy.Error as P@@ -45,7 +44,7 @@ commandPath Command{names, parent} = foldMap groupPath parent <> [NE.head names] -- | Format a command's parameters-commandParams :: Command m c a -> L.Text+commandParams :: Command m c a -> S.Text commandParams Command{params} = let formatted = map@@ -53,7 +52,7 @@ "`" <> name <> ":" <> S.pack (show type_) <> "`" ) params- in L.fromStrict $ S.intercalate ", " formatted+ in S.intercalate ", " formatted {- | Given the properties of a 'Command' with the @parser@ and @callback@ in the 'P.Sem' monad, build a command by transforming the Polysemy actions into @m@@@ -73,7 +72,7 @@ -- | The command's parameter metadata [ParameterInfo] -> -- | The help generator for this command- (c -> L.Text) ->+ (c -> S.Text) -> -- | The parser for this command (c -> P.Sem r (Either CommandError p)) -> -- | The callback for this command@@ -110,7 +109,7 @@ -- | The checks for the command [Check m c] -> -- | The help generator for this command- (c -> L.Text) ->+ (c -> S.Text) -> -- | The callback foor this command (c -> CommandForParsers ps r a) -> P.Sem r (Command m c a)@@ -136,9 +135,9 @@ transforming the Polysemy action into an @m@ action. -} buildCallback ::- (Monad m, P.Member (P.Final m) r) => ((c, p) -> P.Sem (P.Fail ': r) a) -> P.Sem r ((c, p) -> m (Either L.Text a))+ (Monad m, P.Member (P.Final m) r) => ((c, p) -> P.Sem (P.Fail ': r) a) -> P.Sem r ((c, p) -> m (Either S.Text a)) buildCallback cb = do- cb' <- bindSemToM (\x -> P.runFail (cb x) <&> mapLeft L.pack)+ cb' <- bindSemToM (\x -> P.runFail (cb x) <&> mapLeft S.pack) let cb'' = fromMaybe (Left "failed internally") <.> cb' pure cb'' @@ -207,7 +206,7 @@ forall (ps :: [Type]) c r. ParameterParser (ListToTup ps) c r => c ->- L.Text ->+ S.Text -> P.Sem r (Either CommandError (ParserResult (ListToTup ps))) buildTypedCommandParser ctx t = runCommandParser ctx t (parse @(ListToTup ps) @c @r) <&> \case@@ -224,8 +223,8 @@ As an example: @- 'CommandForParsers' [ 'L.Text', 'Int', 'CalamityCommands.Parser.Named' "something" 'L.Text' ] r a ~- ('L.Text' -> 'Int' -> 'L.Text' -> 'P.Sem' r ('P.Fail' ': r) a)+ 'CommandForParsers' [ 'S.Text', 'Int', 'CalamityCommands.Parser.Named' "something" 'S.Text' ] r a ~+ ('S.Text' -> 'Int' -> 'S.Text' -> 'P.Sem' r ('P.Fail' ': r) a) @ -} type family CommandForParsers (ps :: [Type]) r a where
CalamityCommands/Context.hs view
@@ -9,7 +9,7 @@ useBasicContext, ) where -import qualified Data.Text.Lazy as L+import qualified Data.Text as T import GHC.Generics (Generic) import qualified Polysemy as P @@ -17,13 +17,13 @@ class CommandContext m c a | c -> m, c -> a where -- | The prefix that was used to invoke the command- ctxPrefix :: c -> L.Text+ ctxPrefix :: c -> T.Text -- | The command that was invoked ctxCommand :: c -> Command m c a -- | The message remaining after consuming the prefix- ctxUnparsedParams :: c -> L.Text+ ctxUnparsedParams :: c -> T.Text -- | An effect for constructing the context for a command data ConstructContext msg ctx m' a' m a where@@ -31,7 +31,7 @@ -- success, or Nothing if a context could not be constructed ConstructContext :: -- | The (prefix, command, remaining)- (L.Text, Command m' ctx a', L.Text) ->+ (T.Text, Command m' ctx a', T.Text) -> -- | The message type to extract the context from msg -> ConstructContext msg ctx m' a' m (Maybe ctx)@@ -40,9 +40,9 @@ -- | A basic context that only knows the prefix used and the unparsed input data BasicContext m a = BasicContext- { bcPrefix :: L.Text+ { bcPrefix :: T.Text , bcCommand :: Command m (BasicContext m a) a- , bcUnparsedParams :: L.Text+ , bcUnparsedParams :: T.Text } deriving (Show, Generic)
CalamityCommands/Dsl.hs view
@@ -34,8 +34,7 @@ import CalamityCommands.Internal.LocalWriter import qualified Data.HashMap.Lazy as LH-import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T import Data.List.NonEmpty (NonEmpty (..)) import qualified Polysemy as P@@ -63,12 +62,12 @@ 'command' \@\'[] "test" \\ctx -> 'pure' () @ - In the above block, any command declared inside 'hide' will have it's+ In the above block, any command declared inside 'hide' will have its \'hidden\' flag set and will not be shown by the default help command: 'CalamityCommands.Help.helpCommand' The 'CalamityCommands.Help.helpCommand' function can be used to create a- help command for the commands DSL action it is used in, read it's doc page+ help command for the commands DSL action it is used in, read its doc page for more information on how it functions. The 'CalamityCommands.Utils.buildCommands' function is used to@@ -78,12 +77,12 @@ -} type DSLState m c a r =- ( LocalWriter (LH.HashMap S.Text (Command m c a, AliasType))- ': LocalWriter (LH.HashMap S.Text (Group m c a, AliasType))+ ( LocalWriter (LH.HashMap T.Text (Command m c a, AliasType))+ ': LocalWriter (LH.HashMap T.Text (Group m c a, AliasType)) ': P.Reader (Maybe (Group m c a)) ': P.Tagged "hidden" (P.Reader Bool)- ': P.Reader (c -> L.Text)- ': P.Tagged "original-help" (P.Reader (c -> L.Text))+ ': P.Reader (c -> T.Text)+ ': P.Tagged "original-help" (P.Reader (c -> T.Text)) ': P.Reader [Check m c] ': P.Reader (CommandHandler m c a) ': P.Fixpoint@@ -103,7 +102,7 @@ command' :: (Monad m, P.Member (P.Final m) r) => -- | The name of the command- S.Text ->+ T.Text -> -- | The command's parameter metadata [ParameterInfo] -> -- | The parser for this command@@ -124,9 +123,9 @@ forall p c a m r. (Monad m, P.Member (P.Final m) r) => -- | The name of the command- S.Text ->+ T.Text -> -- | The aliases for the command- [S.Text] ->+ [T.Text] -> -- | The command's parameter metadata [ParameterInfo] -> -- | The parser for this command@@ -138,7 +137,7 @@ parent <- P.ask @(Maybe (Group m c a)) hidden <- P.tag $ P.ask @Bool checks <- P.ask @[Check m c]- help' <- P.ask @(c -> L.Text)+ help' <- P.ask @(c -> T.Text) cmd <- raiseDSL $ buildCommand' (name :| aliases) parent hidden checks params help' parser cb ltell $ LH.singleton name (cmd, Original) ltell $ LH.fromList [(name, (cmd, Alias)) | name <- aliases]@@ -172,7 +171,7 @@ , CommandContext m c a ) => -- | The name of the command- S.Text ->+ T.Text -> -- | The callback for this command (c -> CommandForParsers ps r a) -> P.Sem (DSLState m c a r) (Command m c a)@@ -202,9 +201,9 @@ , CommandContext m c a ) => -- | The name of the command- S.Text ->+ T.Text -> -- | The aliases for the command- [S.Text] ->+ [T.Text] -> -- | The callback for this command (c -> CommandForParsers ps r a) -> P.Sem (DSLState m c a r) (Command m c a)@@ -212,7 +211,7 @@ parent <- P.ask @(Maybe (Group m c a)) hidden <- P.tag $ P.ask @Bool checks <- P.ask @[Check m c]- help' <- P.ask @(c -> L.Text)+ help' <- P.ask @(c -> T.Text) cmd' <- raiseDSL $ buildCommand @ps (name :| aliases) parent hidden checks help' cmd ltell $ LH.singleton name (cmd', Original) ltell $ LH.fromList [(name, (cmd', Alias)) | name <- aliases]@@ -238,8 +237,8 @@ @ -} help ::- P.Member (P.Reader (c -> L.Text)) r =>- (c -> L.Text) ->+ P.Member (P.Reader (c -> T.Text)) r =>+ (c -> T.Text) -> P.Sem r a -> P.Sem r a help = P.local . const@@ -261,9 +260,9 @@ requires' :: (Monad m, P.Member (P.Final m) r) => -- | The name of the check- S.Text ->+ T.Text -> -- | The callback for the check- (c -> P.Sem r (Maybe L.Text)) ->+ (c -> P.Sem r (Maybe T.Text)) -> P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x requires' name cb m = do@@ -285,7 +284,7 @@ -} requiresPure :: Monad m =>- [(S.Text, c -> Maybe L.Text)] ->+ [(T.Text, c -> Maybe T.Text)] -> -- A list of check names and check callbacks P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x@@ -294,13 +293,13 @@ {- | Construct a group and place any commands registered in the given action into the new group. - This also resets the @help@ function back to it's original value, use+ This also resets the @help@ function back to its original value, use 'group'' if you don't want that (i.e. your help function is context aware). -} group :: (Monad m, P.Member (P.Final m) r) => -- | The name of the group- S.Text ->+ T.Text -> P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x group name m = groupA name [] m@@ -311,35 +310,35 @@ The parent group, visibility, checks, and command help are drawn from the reader context. - This also resets the @help@ function back to it's original value, use+ This also resets the @help@ function back to its original value, use 'group'' if you don't want that (i.e. your help function is context aware). -} groupA :: forall x c m a r. (Monad m, P.Member (P.Final m) r) => -- | The name of the group- S.Text ->+ T.Text -> -- | The aliases of the group- [S.Text] ->+ [T.Text] -> P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x groupA name aliases m = mdo parent <- P.ask @(Maybe (Group m c a)) hidden <- P.tag $ P.ask @Bool checks <- P.ask @[Check m c]- help' <- P.ask @(c -> L.Text)+ help' <- P.ask @(c -> T.Text) origHelp <- fetchOrigHelp let group' = Group (name :| aliases) parent hidden commands children help' checks (children, (commands, res)) <-- llisten @(LH.HashMap S.Text (Group m c a, AliasType)) $- llisten @(LH.HashMap S.Text (Command m c a, AliasType)) $+ llisten @(LH.HashMap T.Text (Group m c a, AliasType)) $+ llisten @(LH.HashMap T.Text (Command m c a, AliasType)) $ P.local @(Maybe (Group m c a)) (const $ Just group') $- P.local @(c -> L.Text) (const origHelp) m+ P.local @(c -> T.Text) (const origHelp) m ltell $ LH.singleton name (group', Original) ltell $ LH.fromList [(name, (group', Alias)) | name <- aliases] pure res -fetchOrigHelp :: P.Member (P.Tagged "original-help" (P.Reader (c -> L.Text))) r => P.Sem r (c -> L.Text)+fetchOrigHelp :: P.Member (P.Tagged "original-help" (P.Reader (c -> T.Text))) r => P.Sem r (c -> T.Text) fetchOrigHelp = P.tag P.ask {- | Construct a group and place any commands registered in the given action@@ -348,13 +347,13 @@ The parent group, visibility, checks, and command help are drawn from the reader context. - Unlike 'help' this doesn't reset the @help@ function back to it's original+ Unlike 'help' this doesn't reset the @help@ function back to its original value. -} group' :: P.Member (P.Final m) r => -- | The name of the group- S.Text ->+ T.Text -> P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x group' name m = groupA' name [] m@@ -365,27 +364,27 @@ The parent group, visibility, checks, and command help are drawn from the reader context. - Unlike 'help' this doesn't reset the @help@ function back to it's original+ Unlike 'help' this doesn't reset the @help@ function back to its original value. -} groupA' :: forall x c m a r. P.Member (P.Final m) r => -- | The name of the group- S.Text ->+ T.Text -> -- | The aliases of the group- [S.Text] ->+ [T.Text] -> P.Sem (DSLState m c a r) x -> P.Sem (DSLState m c a r) x groupA' name aliases m = mdo parent <- P.ask @(Maybe (Group m c a)) hidden <- P.tag $ P.ask @Bool checks <- P.ask @[Check m c]- help' <- P.ask @(c -> L.Text)+ help' <- P.ask @(c -> T.Text) let group' = Group (name :| aliases) parent hidden commands children help' checks (children, (commands, res)) <-- llisten @(LH.HashMap S.Text (Group m c a, AliasType)) $- llisten @(LH.HashMap S.Text (Command m c a, AliasType)) $+ llisten @(LH.HashMap T.Text (Group m c a, AliasType)) $+ llisten @(LH.HashMap T.Text (Command m c a, AliasType)) $ P.local @(Maybe (Group m c a)) (const $ Just group') m ltell $ LH.singleton name (group', Original) ltell $ LH.fromList [(name, (group', Alias)) | name <- aliases]
CalamityCommands/Error.hs view
@@ -1,21 +1,28 @@ -- | Command errors-module CalamityCommands.Error- ( CommandError(..) ) where+module CalamityCommands.Error (CommandError (..)) where -import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T -import GHC.Generics+import GHC.Generics -import TextShow+import TextShow import qualified TextShow.Generic as TSG data CommandError- = ParseError S.Text -- ^ The type of the parser- L.Text -- ^ The reason that parsing failed- | CheckError S.Text -- ^ The name of the check that failed- L.Text -- ^ The reason for the check failing- | InvokeError S.Text -- ^ The name of the command that failed- L.Text -- ^ The reason for failing- deriving ( Show, Generic )- deriving ( TextShow ) via TSG.FromGeneric CommandError+ = ParseError+ T.Text+ -- ^ The type of the parser+ T.Text+ -- ^ The reason that parsing failed+ | CheckError+ T.Text+ -- ^ The name of the check that failed+ T.Text+ -- ^ The reason for the check failing+ | InvokeError+ T.Text+ -- ^ The name of the command that failed+ T.Text+ -- ^ The reason for failing+ deriving (Show, Generic)+ deriving (TextShow) via TSG.FromGeneric CommandError
CalamityCommands/Group.hs view
@@ -10,8 +10,7 @@ import Control.Lens hiding (Context, (<.>)) import qualified Data.HashMap.Lazy as LH-import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T import GHC.Generics @@ -22,25 +21,25 @@ -- | A group of commands data Group m c a = Group- { names :: NonEmpty S.Text+ { names :: NonEmpty T.Text , parent :: Maybe (Group m c a) , hidden :: Bool , -- | Any child commands of this group- commands :: LH.HashMap S.Text (Command m c a, AliasType)+ commands :: LH.HashMap T.Text (Command m c a, AliasType) , -- | Any child groups of this group- children :: LH.HashMap S.Text (Group m c a, AliasType)+ children :: LH.HashMap T.Text (Group m c a, AliasType) , -- | A function producing the \'help\' for the group- help :: c -> L.Text+ help :: c -> T.Text , -- | A list of checks that must pass checks :: [Check m c] } deriving (Generic) data GroupS m c a = GroupS- { names :: NonEmpty S.Text- , parent :: Maybe S.Text- , commands :: [(S.Text, (Command m c a, AliasType))]- , children :: [(S.Text, (Group m c a, AliasType))]+ { names :: NonEmpty T.Text+ , parent :: Maybe T.Text+ , commands :: [(T.Text, (Command m c a, AliasType))]+ , children :: [(T.Text, (Group m c a, AliasType))] , hidden :: Bool } deriving (Generic, Show)
CalamityCommands/Help.hs view
@@ -22,8 +22,7 @@ import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as NE import Data.Maybe (mapMaybe)-import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T import qualified Polysemy as P import qualified Polysemy.Fail as P@@ -31,18 +30,20 @@ data CommandOrGroup m c a = Command' (Command m c a)- | Group' (Group m c a) [S.Text]+ | Group' (Group m c a) [T.Text] -parameterTypeHelp :: [ParameterInfo] -> L.Text+parameterTypeHelp :: [ParameterInfo] -> T.Text parameterTypeHelp pinfo = let dedup = LH.toList . LH.fromList $ map (\(ParameterInfo _ t d) -> (t, d)) pinfo- typeDescs = L.unlines ["- " <> L.pack (show t) <> ": " <> L.fromStrict d | (t, d) <- dedup]- in "Types:\n" <> typeDescs <> "\n"+ typeDescs = T.unlines ["- " <> T.pack (show t) <> ": " <> d | (t, d) <- dedup]+ in if null dedup+ then ""+ else "Types:\n" <> typeDescs <> "\n" -helpCommandHelp :: c -> L.Text+helpCommandHelp :: c -> T.Text helpCommandHelp _ = "Show help for a command or group." -helpForCommand :: CommandContext m c a => c -> Command m c a -> L.Text+helpForCommand :: CommandContext m c a => c -> Command m c a -> T.Text helpForCommand ctx cmd@Command{names, checks, help, params} = "Usage: " <> prefix' <> path' <> " " <> params' <> "\n" <> aliasesFmt@@ -51,28 +52,28 @@ <> help ctx where prefix' = ctxPrefix ctx- path' = L.unwords . map L.fromStrict $ commandPath cmd+ path' = T.unwords $ commandPath cmd params' = commandParams cmd- aliases = map L.fromStrict $ NE.tail names- checks' = map (L.fromStrict . (^. #name)) checks+ aliases = NE.tail names+ checks' = map (^. #name) checks aliasesFmt = if null aliases then ""- else "Aliases: " <> L.unwords aliases <> "\n"+ else "Aliases: " <> T.unwords aliases <> "\n" checksFmt = if null checks' then ""- else "Checks: " <> L.unwords checks' <> "\n\n"+ else "Checks: " <> T.unwords checks' <> "\n\n" -fmtCommandWithParams :: Command m c a -> L.Text+fmtCommandWithParams :: Command m c a -> T.Text fmtCommandWithParams cmd@Command{names} = formatWithAliases names <> " " <> commandParams cmd -formatWithAliases :: NonEmpty S.Text -> L.Text-formatWithAliases (name :| aliases) = L.fromStrict name <> aliasesFmt+formatWithAliases :: NonEmpty T.Text -> T.Text+formatWithAliases (name :| aliases) = name <> aliasesFmt where aliasesFmt = case aliases of [] -> ""- aliases' -> "[" <> L.intercalate "|" (map L.fromStrict aliases') <> "]"+ aliases' -> "[" <> T.intercalate "|" aliases' <> "]" onlyOriginals :: [(a, AliasType)] -> [a] onlyOriginals = mapMaybe inner@@ -86,7 +87,7 @@ onlyVisibleG :: [Group m c a] -> [Group m c a] onlyVisibleG = mapMaybe notHiddenG -helpForGroup :: CommandContext m c a => c -> Group m c a -> L.Text+helpForGroup :: CommandContext m c a => c -> Group m c a -> T.Text helpForGroup ctx grp = "Group: " <> path' <> "\n" <> aliasesFmt@@ -96,30 +97,30 @@ <> groupsMsg <> commandsMsg where- path' = L.fromStrict . S.unwords $ groupPath grp+ path' = T.unwords $ groupPath grp groups = onlyVisibleG . onlyOriginals . LH.elems $ grp ^. #children commands = onlyVisibleC . onlyOriginals . LH.elems $ grp ^. #commands groupsFmt = map formatWithAliases (groups ^.. traverse . #names) groupsMsg = if null groups then ""- else "The following child groups exist:\n" <> (L.unlines . map ("- " <>) $ groupsFmt)+ else "The following child groups exist:\n" <> (T.unlines . map ("- " <>) $ groupsFmt) commandsMsg = if null commands then ""- else "\nThe following child commands exist:\n" <> (L.unlines . map (("- " <>) . fmtCommandWithParams) $ commands)- aliases = map L.fromStrict . NE.tail $ grp ^. #names- checks' = map (L.fromStrict . (^. #name)) $ grp ^. #checks+ else "\nThe following child commands exist:\n" <> (T.unlines . map (("- " <>) . fmtCommandWithParams) $ commands)+ aliases = NE.tail $ grp ^. #names+ checks' = map (^. #name) $ grp ^. #checks aliasesFmt = if null aliases then ""- else "Aliases: " <> L.unwords aliases <> "\n"+ else "Aliases: " <> T.unwords aliases <> "\n" checksFmt = if null checks' then ""- else "Checks: " <> L.unwords checks' <> "\n\n"+ else "Checks: " <> T.unwords checks' <> "\n\n" -rootHelp :: CommandHandler m c a -> L.Text+rootHelp :: CommandHandler m c a -> T.Text rootHelp handler = groupsMsg <> commandsMsg where groups = onlyVisibleG . onlyOriginals . LH.elems $ handler ^. #groups@@ -128,28 +129,28 @@ groupsMsg = if null groups then ""- else "The following groups exist:\n" <> (L.unlines . map ("- " <>) $ groupsFmt)+ else "The following groups exist:\n" <> (T.unlines . map ("- " <>) $ groupsFmt) commandsMsg = if null commands then ""- else "\nThe following commands exist:\n" <> (L.unlines . map (("- " <>) . fmtCommandWithParams) $ commands)+ else "\nThe following commands exist:\n" <> (T.unlines . map (("- " <>) . fmtCommandWithParams) $ commands) -renderHelp :: CommandContext m c a => CommandHandler m c a -> c -> [S.Text] -> L.Text+renderHelp :: CommandContext m c a => CommandHandler m c a -> c -> [T.Text] -> T.Text renderHelp handler ctx path = case findCommandOrGroup handler path of Just (Command' cmd@Command{names}) ->- "Help for command `" <> L.fromStrict (NE.head names) <> "`: \n" <> helpForCommand ctx cmd+ "Help for command `" <> NE.head names <> "`: \n" <> helpForCommand ctx cmd Just (Group' grp@Group{names} remainingPath) -> let failedMsg = if null remainingPath then ""- else "No command or group with the path: `" <> L.fromStrict (S.unwords remainingPath) <> "` exists for the group: `" <> L.fromStrict (NE.head names) <> "`\n"- in failedMsg <> "Help for group `" <> L.fromStrict (NE.head names) <> "`: \n" <> helpForGroup ctx grp+ else "No command or group with the path: `" <> T.unwords remainingPath <> "` exists for the group: `" <> NE.head names <> "`\n"+ in failedMsg <> "Help for group `" <> NE.head names <> "`: \n" <> helpForGroup ctx grp Nothing -> let failedMsg = if null path then ""- else "No command or group with the path: `" <> L.fromStrict (S.unwords path) <> "` was found.\n"+ else "No command or group with the path: `" <> T.unwords path <> "` was found.\n" in failedMsg <> rootHelp handler {- | Given a 'CommandHandler', optionally a parent 'Group', and a list of 'Check's,@@ -161,10 +162,10 @@ CommandHandler m c a -> Maybe (Group m c a) -> [Check m c] ->- (c -> L.Text -> P.Sem (P.Fail ': r) a) ->+ (c -> T.Text -> P.Sem (P.Fail ': r) a) -> P.Sem r (Command m c a) helpCommand' handler parent checks render =- buildCommand @'[[S.Text]]+ buildCommand @'[[T.Text]] ("help" :| []) parent False@@ -223,7 +224,7 @@ helpCommand :: forall c m a r. (Monad m, P.Member (P.Final m) r, CommandContext m c a) =>- (c -> L.Text -> P.Sem (P.Fail ': r) a) ->+ (c -> T.Text -> P.Sem (P.Fail ': r) a) -> P.Sem (DSLState m c a r) (Command m c a) helpCommand render = do handler <- P.ask @(CommandHandler m c a)@@ -239,12 +240,12 @@ notHiddenG :: Group m c a -> Maybe (Group m c a) notHiddenG g@Group{hidden} = if hidden then Nothing else Just g -findCommandOrGroup :: CommandHandler m c a -> [S.Text] -> Maybe (CommandOrGroup m c a)+findCommandOrGroup :: CommandHandler m c a -> [T.Text] -> Maybe (CommandOrGroup m c a) findCommandOrGroup handler path = go (handler ^. #commands, handler ^. #groups) path where go ::- (LH.HashMap S.Text (Command m c a, AliasType), LH.HashMap S.Text (Group m c a, AliasType)) ->- [S.Text] ->+ (LH.HashMap T.Text (Command m c a, AliasType), LH.HashMap T.Text (Group m c a, AliasType)) ->+ [T.Text] -> Maybe (CommandOrGroup m c a) go (commands, groups) (x : xs) = case LH.lookup x commands of
CalamityCommands/ParsePrefix.hs view
@@ -1,23 +1,27 @@ {-# LANGUAGE TemplateHaskell #-} -- | Command prefix parsing effect-module CalamityCommands.ParsePrefix- ( ParsePrefix(..)- , parsePrefix- , useConstantPrefix ) where+module CalamityCommands.ParsePrefix (+ ParsePrefix (..),+ parsePrefix,+ useConstantPrefix,+) where -import qualified Data.Text.Lazy as L+import qualified Data.Text as T -import qualified Polysemy as P+import qualified Polysemy as P -- | An effect for parsing the prefix of a command. data ParsePrefix msg m a where -- | Parse a prefix in a message, returning a tuple of @(prefix, remaining message)@- ParsePrefix :: msg -> ParsePrefix msg m (Maybe (L.Text, L.Text))+ ParsePrefix :: msg -> ParsePrefix msg m (Maybe (T.Text, T.Text)) P.makeSem ''ParsePrefix -- | A default interpretation for 'ParsePrefix' that uses a single constant prefix.-useConstantPrefix :: L.Text -> P.Sem (ParsePrefix L.Text ': r) a -> P.Sem r a-useConstantPrefix pre = P.interpret (\case- ParsePrefix msg -> pure ((pre, ) <$> L.stripPrefix pre msg))+useConstantPrefix :: T.Text -> P.Sem (ParsePrefix T.Text ': r) a -> P.Sem r a+useConstantPrefix pre =+ P.interpret+ ( \case+ ParsePrefix msg -> pure ((pre,) <$> T.stripPrefix pre msg)+ )
CalamityCommands/Parser.hs view
@@ -24,7 +24,7 @@ import Data.List.NonEmpty (NonEmpty (..)) import Data.Maybe (fromMaybe) import Data.Semigroup-import qualified Data.Text as S+import qualified Data.Text as T import qualified Data.Text.Lazy as L import Data.Typeable @@ -41,7 +41,7 @@ import Text.Megaparsec.Char import Text.Megaparsec.Char.Lexer (decimal, float, signed) -data SpannedError = SpannedError L.Text !Int !Int+data SpannedError = SpannedError T.Text !Int !Int deriving (Show, Eq, Ord) {- | The current state of the parser, used so that the entire remaining input is@@ -55,20 +55,20 @@ { -- | The current offset, or where the next parser should start parsing at off :: Int , -- | The input message ot parse- msg :: L.Text+ msg :: T.Text } deriving (Show, Generic) -- | type ParserEffs c r = ( P.State ParserState- ': P.Error (S.Text, L.Text) -- (failing parser name, error reason)+ ': P.Error (T.Text, T.Text) -- (failing parser name, error reason) ': P.Reader c -- the current parser state ': r -- context ) -- | Run a command parser, @ctx@ is the context, @t@ is the text input-runCommandParser :: c -> L.Text -> P.Sem (ParserEffs c r) a -> P.Sem r (Either (S.Text, L.Text) a)+runCommandParser :: c -> T.Text -> P.Sem (ParserEffs c r) a -> P.Sem r (Either (T.Text, T.Text) a) runCommandParser ctx t = P.runReader ctx . P.runError . P.evalState (ParserState 0 t) {- | A typeclass for things that can be parsed as parameters to commands.@@ -86,7 +86,7 @@ default parameterInfo :: ParameterInfo parameterInfo = ParameterInfo Nothing (typeRep $ Proxy @a) (parameterDescription @a @c @r) - parameterDescription :: S.Text+ parameterDescription :: T.Text parse :: P.Sem (ParserEffs c r) (ParserResult a) @@ -100,16 +100,16 @@ parameterInfo = let ParameterInfo _ type_ typeDescription = parameterInfo @a @c @r- in ParameterInfo (Just . S.pack . symbolVal $ Proxy @s) type_ typeDescription+ in ParameterInfo (Just . T.pack . symbolVal $ Proxy @s) type_ typeDescription parameterDescription = parameterDescription @a @c @r parse = mapE (_1 .~ parserName @(Named s a) @c @r) $ parse @a @c @r -parserName :: forall a c r. ParameterParser a c r => S.Text+parserName :: forall a c r. ParameterParser a c r => T.Text parserName = let ParameterInfo (fromMaybe "" -> name) type_ _ = parameterInfo @a @c @r- in name <> ":" <> S.pack (show type_)+ in name <> ":" <> T.pack (show type_) mapE :: P.Member (P.Error e) r => (e -> e) -> P.Sem r a -> P.Sem r a mapE f m = P.catch m (P.throw . f)@@ -120,9 +120,9 @@ -} parseMP :: -- | The name of the parser- S.Text ->+ T.Text -> -- | The megaparsec parser- ParsecT SpannedError L.Text (P.Sem (P.Reader c ': r)) a ->+ ParsecT SpannedError T.Text (P.Sem (P.Reader c ': r)) a -> P.Sem (ParserEffs c r) a parseMP n m = do s <- P.get@@ -131,14 +131,14 @@ Right (a, offset) -> do P.modify (#off +~ offset) pure a- Left s -> P.throw (n, L.pack $ errorBundlePretty s)+ Left s -> P.throw (n, T.pack $ errorBundlePretty s) instance ParameterParser L.Text c r where- parse = parseMP (parserName @L.Text) item+ parse = parseMP (parserName @L.Text) (L.fromStrict <$> item) parameterDescription = "word or quoted string" -instance ParameterParser S.Text c r where- parse = parseMP (parserName @S.Text) (L.toStrict <$> item)+instance ParameterParser T.Text c r where+ parse = parseMP (parserName @T.Text) item parameterDescription = "word or quoted string" instance ParameterParser Integer c r where@@ -203,7 +203,7 @@ {- | A parser that consumes zero or more of @a@ then concatenates them together. - @'KleeneStarConcat' 'L.Text'@ therefore consumes all remaining input.+ @'KleeneStarConcat' 'T.Text'@ therefore consumes all remaining input. -} data KleeneStarConcat (a :: Type) @@ -217,19 +217,19 @@ type ParserResult (KleeneStarConcat L.Text) = ParserResult L.Text -- consume rest on text just takes everything remaining- parse = parseMP (parserName @(KleeneStarConcat L.Text)) manySingle+ parse = parseMP (parserName @(KleeneStarConcat T.Text)) (L.fromStrict <$> manySingle) parameterDescription = "the remaining input" -instance {-# OVERLAPS #-} ParameterParser (KleeneStarConcat S.Text) c r where- type ParserResult (KleeneStarConcat S.Text) = ParserResult S.Text+instance {-# OVERLAPS #-} ParameterParser (KleeneStarConcat T.Text) c r where+ type ParserResult (KleeneStarConcat T.Text) = ParserResult T.Text -- consume rest on text just takes everything remaining- parse = parseMP (parserName @(KleeneStarConcat S.Text)) (L.toStrict <$> manySingle)+ parse = parseMP (parserName @(KleeneStarConcat T.Text)) manySingle parameterDescription = "the remaining input" {- | A parser that consumes one or more of @a@ then concatenates them together. - @'KleenePlusConcat' 'L.Text'@ therefore consumes all remaining input.+ @'KleenePlusConcat' 'T.Text'@ therefore consumes all remaining input. -} data KleenePlusConcat (a :: Type) @@ -243,14 +243,14 @@ type ParserResult (KleenePlusConcat L.Text) = ParserResult L.Text -- consume rest on text just takes everything remaining- parse = parseMP (parserName @(KleenePlusConcat L.Text)) someSingle+ parse = parseMP (parserName @(KleenePlusConcat L.Text)) (L.fromStrict <$> someSingle) parameterDescription = "the remaining input" -instance {-# OVERLAPS #-} ParameterParser (KleenePlusConcat S.Text) c r where- type ParserResult (KleenePlusConcat S.Text) = ParserResult S.Text+instance {-# OVERLAPS #-} ParameterParser (KleenePlusConcat T.Text) c r where+ type ParserResult (KleenePlusConcat T.Text) = ParserResult T.Text -- consume rest on text just takes everything remaining- parse = parseMP (parserName @(KleenePlusConcat S.Text)) (L.toStrict <$> someSingle)+ parse = parseMP (parserName @(KleenePlusConcat T.Text)) someSingle parameterDescription = "the remaining input" instance (ParameterParser a c r, ParameterParser b c r) => ParameterParser (a, b) c r where@@ -267,7 +267,7 @@ parameterDescription = "whitespace" instance ShowErrorComponent SpannedError where- showErrorComponent (SpannedError t _ _) = L.unpack t+ showErrorComponent (SpannedError t _ _) = T.unpack t errorComponentLen (SpannedError _ s e) = max 1 $ e - s skipN :: (Stream s, Ord e) => Int -> ParsecT e s m ()@@ -280,7 +280,7 @@ offe <- getOffset pure (a, offe - offs) -item :: MonadParsec e L.Text m => m L.Text+item :: MonadParsec e T.Text m => m T.Text item = try quotedString <|> someNonWS manySingle :: MonadParsec e s m => m (Tokens s)@@ -289,7 +289,7 @@ someSingle :: MonadParsec e s m => m (Tokens s) someSingle = takeWhile1P (Just "any character") (const True) -quotedString :: MonadParsec e L.Text m => m L.Text+quotedString :: MonadParsec e T.Text m => m T.Text quotedString = try (between (chunk "'") (chunk "'") (takeWhileP (Just "any character") (/= '\''))) <|> between (chunk "\"") (chunk "\"") (takeWhileP (Just "any character") (/= '"'))
CalamityCommands/Utils.hs view
@@ -25,8 +25,7 @@ import Data.Char (isSpace) import qualified Data.HashMap.Lazy as LH-import qualified Data.Text as S-import qualified Data.Text.Lazy as L+import qualified Data.Text as T import GHC.Generics (Generic) @@ -42,7 +41,7 @@ data CmdInvokeFailReason c = NoContext- | NotFound [L.Text]+ | NotFound [T.Text] | CommandInvokeError c CommandError deriving (Show, Generic) @@ -82,9 +81,9 @@ -- | The message that invoked the command msg -> -- | The prefix used- L.Text ->+ T.Text -> -- | The command string, without a prefix- L.Text ->+ T.Text -> P.Sem r (Either (CmdInvokeFailReason c) (c, a)) handleCommands handler msg prefix cmd = P.runError $ do (command, unparsedParams) <- P.fromEither . mapLeft NotFound $ findCommand handler cmd@@ -108,8 +107,8 @@ P.Sem (DSLState m c a r) x -> P.Sem (P.Fixpoint ': r)- ( LH.HashMap S.Text (Group m c a, AliasType)- , (LH.HashMap S.Text (Command m c a, AliasType), x)+ ( LH.HashMap T.Text (Group m c a, AliasType)+ , (LH.HashMap T.Text (Command m c a, AliasType), x) ) inner h = P.runReader h@@ -120,12 +119,12 @@ . P.runReader False . P.untag @"hidden" . P.runReader Nothing- . runLocalWriter @(LH.HashMap S.Text (Group m c a, AliasType))- . runLocalWriter @(LH.HashMap S.Text (Command m c a, AliasType))+ . runLocalWriter @(LH.HashMap T.Text (Group m c a, AliasType))+ . runLocalWriter @(LH.HashMap T.Text (Command m c a, AliasType)) defaultHelp = const "This command or group has no help." -nextWord :: L.Text -> (L.Text, L.Text)-nextWord = L.break isSpace . L.stripStart+nextWord :: T.Text -> (T.Text, T.Text)+nextWord = T.break isSpace . T.stripStart {- | Attempt to find what command was used. @@ -139,31 +138,31 @@ This function isn't greedy, if you have a group and a command at the same level, this will find the command first and ignore the group. -}-findCommand :: forall c a m. CommandHandler m c a -> L.Text -> Either [L.Text] (Command m c a, L.Text)+findCommand :: forall c a m. CommandHandler m c a -> T.Text -> Either [T.Text] (Command m c a, T.Text) findCommand handler msg = goH $ nextWord msg where- goH :: (L.Text, L.Text) -> Either [L.Text] (Command m c a, L.Text)+ goH :: (T.Text, T.Text) -> Either [T.Text] (Command m c a, T.Text) goH ("", _) = Left [] goH (x, xs) = attachSoFar x- ( ((,xs) <$> attachInitial (LH.lookup (L.toStrict x) (handler ^. #commands)))- <> (attachInitial (LH.lookup (L.toStrict x) (handler ^. #groups)) >>= goG (nextWord xs))+ ( ((,xs) <$> attachInitial (LH.lookup x (handler ^. #commands)))+ <> (attachInitial (LH.lookup x (handler ^. #groups)) >>= goG (nextWord xs)) ) - goG :: (L.Text, L.Text) -> Group m c a -> Either [L.Text] (Command m c a, L.Text)+ goG :: (T.Text, T.Text) -> Group m c a -> Either [T.Text] (Command m c a, T.Text) goG ("", _) _ = Left [] goG (x, xs) g = attachSoFar x- ( ((,xs) <$> attachInitial (LH.lookup (L.toStrict x) (g ^. #commands)))- <> (attachInitial (LH.lookup (L.toStrict x) (g ^. #children)) >>= goG (nextWord xs))+ ( ((,xs) <$> attachInitial (LH.lookup x (g ^. #commands)))+ <> (attachInitial (LH.lookup x (g ^. #children)) >>= goG (nextWord xs)) ) - attachInitial :: forall a b. Maybe (a, b) -> Either [L.Text] a+ attachInitial :: forall a b. Maybe (a, b) -> Either [T.Text] a attachInitial (Just (a, _)) = Right a attachInitial Nothing = Left [] - attachSoFar :: forall a. L.Text -> Either [L.Text] a -> Either [L.Text] a+ attachSoFar :: forall a. T.Text -> Either [T.Text] a -> Either [T.Text] a attachSoFar cmd (Left xs) = Left (cmd : xs) attachSoFar _ r = r
ChangeLog.md view
@@ -1,5 +1,9 @@ # Changelog for Calamity Commands +## 0.2.0.0+++ Remove all usages of lazy Text (except from typeclass instances)+ ## 0.1.3.0 + Fixed some parameter parser instances causing type inference to fail
README.md view
@@ -43,13 +43,11 @@ import CalamityCommands.Commands.ParsePrefix import Data.Functor.Identity import qualified Data.Text as T-import qualified Data.Text.Lazy as LT import qualified Data.Text.IO as T-import qualified Data.Text.Lazy.IO as LT -- Make a command handler, we don't actually use the context and therefore this -- handler is generic over the context used-h' :: CommandContext Identity c (Either LT.Text Int) => CommandHandler Identity c (Either LT.Text Int)+h' :: CommandContext Identity c (Either T.Text Int) => CommandHandler Identity c (Either T.Text Int) h' = runIdentity . runFinal $ do (h, _) <- buildCommands $ do command @'[Int, Int] "add" $ \ctx a b -> pure $ Right (a + b)@@ -71,24 +69,24 @@ -- -- This function 'r' takes an input string such as "!add 1 2", and then looks up -- the invoked command and runs it, returning the result.-r :: LT.Text -> Maybe (Either- (CmdInvokeFailReason (BasicContext Identity (Either LT.Text Int)))- (BasicContext Identity (Either LT.Text Int), Either LT.Text Int))+r :: T.Text -> Maybe (Either+ (CmdInvokeFailReason (BasicContext Identity (Either T.Text Int)))+ (BasicContext Identity (Either T.Text Int), Either T.Text Int)) r = runIdentity . runFinal . embedToFinal . useBasicContext . useConstantPrefix "!" . processCommands h' -- Then to display the result of processing the command nicely, we can use a -- something like this function, which prints the result of a command if one was -- invoked successfully, and prints the error nicely if not.-rm :: LT.Text -> IO ()+rm :: T.Text -> IO () rm s = case r s of Just (Right (_, Right r)) -> print r Just (Right (_, Left h)) ->- LT.putStrLn h+ T.putStrLn h Just (Left (CommandInvokeError _ (ParseError t r))) ->- LT.putStrLn ("Parsing parameter " <> LT.fromStrict t <> " failed with reason: " <> r)+ T.putStrLn ("Parsing parameter " <> t <> " failed with reason: " <> r) _ -> pure () ```
calamity-commands.cabal view
@@ -3,11 +3,9 @@ -- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack------ hash: ec3fda8daa0c65a69c2b8cfae6a5cb025d8069ab3fe541918c0d14456fa3143b name: calamity-commands-version: 0.1.3.0+version: 0.2.0.0 synopsis: A library for declaring, parsing, and invoking text-input based commands description: Please see the README on GitHub at <https://github.com/simmsb/calamity#readme> category: Utils@@ -18,9 +16,9 @@ copyright: 2020 Ben Simms license: MIT license-file: LICENSE+build-type: Simple tested-with: GHC == 8.10.4-build-type: Simple extra-source-files: README.md ChangeLog.md@@ -112,8 +110,8 @@ , lens >=4.18 && <6 , megaparsec >=8 && <10 , polysemy >=1.5 && <2- , polysemy-plugin ==0.3.*- , text >=1.2 && <2+ , polysemy-plugin >=0.3 && <0.5+ , text >=1.2 && <2.1 , text-show >=3.8 && <4 , unordered-containers ==0.2.* default-language: Haskell2010