{-# LANGUAGE RecursiveDo #-}

-- | A DSL for generating commands and groups
module Calamity.Commands.Dsl
    ( -- * Commands DSL
      -- $dslTutorial
      command
    , command'
    , commandA
    , commandA'
    , hide
    , help
    , requires
    , requires'
    , requiresPure
    , group
    , group'
    , groupA
    , groupA'
    , DSLState
    , raiseDSL
    , fetchHandler ) where

import           Calamity.Commands.AliasType
import           Calamity.Commands.Check
import           Calamity.Commands.Command     hiding ( help )
import           Calamity.Commands.CommandUtils
import           Calamity.Commands.Context     hiding ( command )
import           Calamity.Commands.Error
import           Calamity.Commands.Group       hiding ( help )
import           Calamity.Commands.Handler
import           Calamity.Internal.LocalWriter

import qualified Data.HashMap.Lazy             as LH
import qualified Data.Text                     as S
import qualified Data.Text.Lazy                as L

import qualified Polysemy                      as P
import qualified Polysemy.Fail                 as P
import qualified Polysemy.Tagged               as P
import qualified Polysemy.Fixpoint             as P
import qualified Polysemy.Reader               as P
import Data.List.NonEmpty (NonEmpty(..))

-- $dslTutorial
--
-- This module provides a way of constructing bot commands in a declarative way.
--
-- The main component of this is the 'command' function, which takes a
-- type-level list of command parameters, the name, and the callback and
-- produces a command. There are also the alternatives 'command'', 'commandA'
-- and 'commandA'', for when you want to handle parsing of the input yourself,
-- and/or want aliases of the command.
--
-- The functions: 'hide', 'help', 'requires', and 'group' can be used to change
-- attributes of any commands declared inside the monadic action passed to them,
-- for example:
--
-- @
-- 'hide' '$' do
--   'command' \@'[] "test" \\ctx -> 'pure' ()
-- @
--
-- In the above block, any command declared inside 'hide' will have it's
-- \'hidden\' flag set and will not be shown by the default help command:
-- 'Calamity.Commands.Help.helpCommand'
--
-- The 'Calamity.Commands.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
-- for more information on how it functions.
--
-- The 'Calamity.Commands.Utils.addCommands' function creates the command
-- handler for the commands registered in the passed action, it is what reads a
-- message to determine what command was invoked. It should be used to register the
-- commands with the bot by using it inside the setup action, for example:
--
-- @
-- 'Calamity.Client.runBotIO' ('Calamity.BotToken' token)
--   $ 'Calamity.Commands.Utils.addCommands' $ do
--     'Calamity.Commands.Help.helpCommand'
--     'Calamity.Commands.Dsl.command' \@'[] "test" \\ctx ->
--       'Control.Monad.void' $ 'Calamity.Types.Tellable.tell' \@'L.Text' ctx "hi"
-- @
--
-- The above block will create a command with no parameters named \'test\',
-- along with a help command.

type DSLState r =
  ( LocalWriter (LH.HashMap S.Text (Command, AliasType))
      ': LocalWriter (LH.HashMap S.Text (Group, AliasType))
      ': P.Reader (Maybe Group)
      ': P.Tagged "hidden" (P.Reader Bool)
      ': P.Reader (Context -> L.Text)
      ': P.Tagged "original-help" (P.Reader (Context -> L.Text))
      ': P.Reader [Check]
      ': P.Reader CommandHandler
      ': P.Fixpoint
      ': r
  )

raiseDSL :: P.Sem r a -> P.Sem (DSLState r) a
raiseDSL :: Sem r a -> Sem (DSLState r) a
raiseDSL = Sem
  (LocalWriter (HashMap Text (Group, AliasType))
     : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
     : Reader (Context -> Text)
     : Tagged "original-help" (Reader (Context -> Text))
     : Reader [Check] : Reader CommandHandler : Fixpoint : r)
  a
-> Sem (DSLState r) a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem
   (LocalWriter (HashMap Text (Group, AliasType))
      : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
      : Reader (Context -> Text)
      : Tagged "original-help" (Reader (Context -> Text))
      : Reader [Check] : Reader CommandHandler : Fixpoint : r)
   a
 -> Sem (DSLState r) a)
-> (Sem r a
    -> Sem
         (LocalWriter (HashMap Text (Group, AliasType))
            : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
            : Reader (Context -> Text)
            : Tagged "original-help" (Reader (Context -> Text))
            : Reader [Check] : Reader CommandHandler : Fixpoint : r)
         a)
-> Sem r a
-> Sem (DSLState r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem
  (Reader (Maybe Group)
     : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
     : Tagged "original-help" (Reader (Context -> Text))
     : Reader [Check] : Reader CommandHandler : Fixpoint : r)
  a
-> Sem
     (LocalWriter (HashMap Text (Group, AliasType))
        : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
        : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem
   (Reader (Maybe Group)
      : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
      : Tagged "original-help" (Reader (Context -> Text))
      : Reader [Check] : Reader CommandHandler : Fixpoint : r)
   a
 -> Sem
      (LocalWriter (HashMap Text (Group, AliasType))
         : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
         : Reader (Context -> Text)
         : Tagged "original-help" (Reader (Context -> Text))
         : Reader [Check] : Reader CommandHandler : Fixpoint : r)
      a)
-> (Sem r a
    -> Sem
         (Reader (Maybe Group)
            : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
            : Tagged "original-help" (Reader (Context -> Text))
            : Reader [Check] : Reader CommandHandler : Fixpoint : r)
         a)
-> Sem r a
-> Sem
     (LocalWriter (HashMap Text (Group, AliasType))
        : Reader (Maybe Group) : Tagged "hidden" (Reader Bool)
        : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem
  (Tagged "hidden" (Reader Bool)
     : Reader (Context -> Text)
     : Tagged "original-help" (Reader (Context -> Text))
     : Reader [Check] : Reader CommandHandler : Fixpoint : r)
  a
-> Sem
     (Reader (Maybe Group)
        : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem
   (Tagged "hidden" (Reader Bool)
      : Reader (Context -> Text)
      : Tagged "original-help" (Reader (Context -> Text))
      : Reader [Check] : Reader CommandHandler : Fixpoint : r)
   a
 -> Sem
      (Reader (Maybe Group)
         : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
         : Tagged "original-help" (Reader (Context -> Text))
         : Reader [Check] : Reader CommandHandler : Fixpoint : r)
      a)
-> (Sem r a
    -> Sem
         (Tagged "hidden" (Reader Bool)
            : Reader (Context -> Text)
            : Tagged "original-help" (Reader (Context -> Text))
            : Reader [Check] : Reader CommandHandler : Fixpoint : r)
         a)
-> Sem r a
-> Sem
     (Reader (Maybe Group)
        : Tagged "hidden" (Reader Bool) : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem
  (Reader (Context -> Text)
     : Tagged "original-help" (Reader (Context -> Text))
     : Reader [Check] : Reader CommandHandler : Fixpoint : r)
  a
-> Sem
     (Tagged "hidden" (Reader Bool)
        : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem
   (Reader (Context -> Text)
      : Tagged "original-help" (Reader (Context -> Text))
      : Reader [Check] : Reader CommandHandler : Fixpoint : r)
   a
 -> Sem
      (Tagged "hidden" (Reader Bool)
         : Reader (Context -> Text)
         : Tagged "original-help" (Reader (Context -> Text))
         : Reader [Check] : Reader CommandHandler : Fixpoint : r)
      a)
-> (Sem r a
    -> Sem
         (Reader (Context -> Text)
            : Tagged "original-help" (Reader (Context -> Text))
            : Reader [Check] : Reader CommandHandler : Fixpoint : r)
         a)
-> Sem r a
-> Sem
     (Tagged "hidden" (Reader Bool)
        : Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem
  (Tagged "original-help" (Reader (Context -> Text))
     : Reader [Check] : Reader CommandHandler : Fixpoint : r)
  a
-> Sem
     (Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem
   (Tagged "original-help" (Reader (Context -> Text))
      : Reader [Check] : Reader CommandHandler : Fixpoint : r)
   a
 -> Sem
      (Reader (Context -> Text)
         : Tagged "original-help" (Reader (Context -> Text))
         : Reader [Check] : Reader CommandHandler : Fixpoint : r)
      a)
-> (Sem r a
    -> Sem
         (Tagged "original-help" (Reader (Context -> Text))
            : Reader [Check] : Reader CommandHandler : Fixpoint : r)
         a)
-> Sem r a
-> Sem
     (Reader (Context -> Text)
        : Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a
-> Sem
     (Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a
 -> Sem
      (Tagged "original-help" (Reader (Context -> Text))
         : Reader [Check] : Reader CommandHandler : Fixpoint : r)
      a)
-> (Sem r a
    -> Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a)
-> Sem r a
-> Sem
     (Tagged "original-help" (Reader (Context -> Text))
        : Reader [Check] : Reader CommandHandler : Fixpoint : r)
     a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Reader CommandHandler : Fixpoint : r) a
-> Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem (Reader CommandHandler : Fixpoint : r) a
 -> Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a)
-> (Sem r a -> Sem (Reader CommandHandler : Fixpoint : r) a)
-> Sem r a
-> Sem (Reader [Check] : Reader CommandHandler : Fixpoint : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem (Fixpoint : r) a
-> Sem (Reader CommandHandler : Fixpoint : r) a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise (Sem (Fixpoint : r) a
 -> Sem (Reader CommandHandler : Fixpoint : r) a)
-> (Sem r a -> Sem (Fixpoint : r) a)
-> Sem r a
-> Sem (Reader CommandHandler : Fixpoint : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem r a -> Sem (Fixpoint : r) a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise

-- | Given the command name and parameter names, @parser@ and @callback@ for a
-- command in the 'P.Sem' monad, build a command by transforming the Polysemy
-- actions into IO actions. Then register the command.
--
-- The parent group, visibility, checks, and command help are drawn from the
-- reader context.
command'
  :: P.Member (P.Final IO) r
  => S.Text
  -- ^ The name of the command
  -> [S.Text]
  -- ^ The names of the command's parameters
  -> (Context -> P.Sem r (Either CommandError a))
  -- ^ The parser for this command
  -> ((Context, a) -> P.Sem (P.Fail ': r) ())
  -- ^ The callback for this command
  -> P.Sem (DSLState r) Command
command' :: Text
-> [Text]
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem (DSLState r) Command
command' Text
name [Text]
params Context -> Sem r (Either CommandError a)
parser (Context, a) -> Sem (Fail : r) ()
cb = Text
-> [Text]
-> [Text]
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem (DSLState r) Command
forall (r :: EffectRow) a.
Member (Final IO) r =>
Text
-> [Text]
-> [Text]
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem (DSLState r) Command
commandA' Text
name [] [Text]
params Context -> Sem r (Either CommandError a)
parser (Context, a) -> Sem (Fail : r) ()
cb

-- | Given the command name, aliases, and parameter names, @parser@ and
-- @callback@ for a command in the 'P.Sem' monad, build a command by
-- transforming the Polysemy actions into IO actions. Then register the command.
--
-- The parent group, visibility, checks, and command help are drawn from the
-- reader context.
commandA'
  :: P.Member (P.Final IO) r
  => S.Text
  -- ^ The name of the command
  -> [S.Text]
  -- ^ The aliases for the command
  -> [S.Text]
  -- ^ The names of the command's parameters
  -> (Context -> P.Sem r (Either CommandError a))
  -- ^ The parser for this command
  -> ((Context, a) -> P.Sem (P.Fail ': r) ())
  -- ^ The callback for this command
  -> P.Sem (DSLState r) Command
commandA' :: Text
-> [Text]
-> [Text]
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem (DSLState r) Command
commandA' Text
name [Text]
aliases [Text]
params Context -> Sem r (Either CommandError a)
parser (Context, a) -> Sem (Fail : r) ()
cb = do
  Maybe Group
parent <- forall (r :: EffectRow).
MemberWithError (Reader (Maybe Group)) r =>
Sem r (Maybe Group)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Maybe Group)
  Bool
hidden <- Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
P.tag (Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool)
-> Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall a b. (a -> b) -> a -> b
$ forall (r :: EffectRow).
MemberWithError (Reader Bool) r =>
Sem r Bool
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @Bool
  [Check]
checks <- forall (r :: EffectRow).
MemberWithError (Reader [Check]) r =>
Sem r [Check]
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @[Check]
  Context -> Text
help' <- forall (r :: EffectRow).
MemberWithError (Reader (Context -> Text)) r =>
Sem r (Context -> Text)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Context -> L.Text)
  Command
cmd <- Sem r Command -> Sem (DSLState r) Command
forall (r :: EffectRow) a. Sem r a -> Sem (DSLState r) a
raiseDSL (Sem r Command -> Sem (DSLState r) Command)
-> Sem r Command -> Sem (DSLState r) Command
forall a b. (a -> b) -> a -> b
$ NonEmpty Text
-> Maybe Group
-> Bool
-> [Check]
-> [Text]
-> (Context -> Text)
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem r Command
forall (r :: EffectRow) a.
Member (Final IO) r =>
NonEmpty Text
-> Maybe Group
-> Bool
-> [Check]
-> [Text]
-> (Context -> Text)
-> (Context -> Sem r (Either CommandError a))
-> ((Context, a) -> Sem (Fail : r) ())
-> Sem r Command
buildCommand' (Text
name Text -> [Text] -> NonEmpty Text
forall a. a -> [a] -> NonEmpty a
:| [Text]
aliases) Maybe Group
parent Bool
hidden [Check]
checks [Text]
params Context -> Text
help' Context -> Sem r (Either CommandError a)
parser (Context, a) -> Sem (Fail : r) ()
cb
  HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Command, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ Text -> (Command, AliasType) -> HashMap Text (Command, AliasType)
forall k v. Hashable k => k -> v -> HashMap k v
LH.singleton Text
name (Command
cmd, AliasType
Original)
  HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Command, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ [(Text, (Command, AliasType))] -> HashMap Text (Command, AliasType)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
LH.fromList [(Text
name, (Command
cmd, AliasType
Alias)) | Text
name <- [Text]
aliases]
  Command -> Sem (DSLState r) Command
forall (f :: * -> *) a. Applicative f => a -> f a
pure Command
cmd

-- | Given the name of a command and a callback, and a type level list of
-- the parameters, build and register a command.
--
-- The parent group, visibility, checks, and command help are drawn from the
-- reader context.
--
-- Command parameters are parsed by first invoking
-- 'Calamity.Commands.Parser.parse' for the first
-- 'Calamity.Commands.Parser.Parser', then running the next parser on the
-- remaining input, and so on.
--
-- ==== Examples
--
-- Building a command that bans a user by id.
--
-- @
-- 'command' \@\'['Calamity.Commands.Parser.Named' "user" ('Calamity.Types.Snowflake' 'Calamity.Types.Model.User'),
--                'Calamity.Commands.Parser.Named' "reason" ('Calamity.Commands.Parser.KleeneStarConcat' 'S.Text')]
--    "ban" $ \\ctx uid r -> case (ctx 'Control.Lens.^.' #guild) of
--      'Just' guild -> do
--        'Control.Monad.void' . 'Calamity.HTTP.invoke' $ 'Calamity.HTTP.Guild.CreateGuildBan' guild uid ('Calamity.HTTP.Guild.CreateGuildBanData' 'Nothing' $ 'Just' r)
--        'Control.Monad.void' $ 'Calamity.Types.Tellable.tell' ctx ("Banned user `" '<>' 'TextShow.showt' uid '<>' "` with reason: " '<>' r)
--      'Nothing' -> 'void' $ 'Calamity.Types.Tellable.tell' @'L.Text' ctx "Can only ban users from guilds."
-- @
command :: forall ps r.
        ( P.Member (P.Final IO) r,
          TypedCommandC ps r)
        => S.Text
        -- ^ The name of the command
        -> (Context -> CommandForParsers ps r)
        -- ^ The callback for this command
        -> P.Sem (DSLState r) Command
command :: Text
-> (Context -> CommandForParsers ps r) -> Sem (DSLState r) Command
command Text
name Context -> CommandForParsers ps r
cmd = Text
-> [Text]
-> (Context -> CommandForParsers ps r)
-> Sem (DSLState r) Command
forall (ps :: [*]) (r :: EffectRow).
(Member (Final IO) r, TypedCommandC ps r) =>
Text
-> [Text]
-> (Context -> CommandForParsers ps r)
-> Sem (DSLState r) Command
commandA @ps Text
name [] Context -> CommandForParsers ps r
cmd

-- | Given the name and aliases of a command and a callback, and a type level list of
-- the parameters, build and register a command.
--
-- The parent group, visibility, checks, and command help are drawn from the
-- reader context.
--
-- ==== Examples
--
-- Building a command that bans a user by id.
--
-- @
-- 'commandA' \@\'['Calamity.Commands.Parser.Named' "user" ('Calamity.Types.Snowflake' 'Calamity.Types.Model.User'),
--                'Calamity.Commands.Parser.Named' "reason" ('Calamity.Commands.Parser.KleeneStarConcat' 'S.Text')]
--    "ban" [] $ \\ctx uid r -> case (ctx 'Control.Lens.^.' #guild) of
--      'Just' guild -> do
--        'Control.Monad.void' . 'Calamity.HTTP.invoke' $ 'Calamity.HTTP.Guild.CreateGuildBan' guild uid ('Calamity.HTTP.Guild.CreateGuildBanData' 'Nothing' $ 'Just' r)
--        'Control.Monad.void' $ 'Calamity.Types.Tellable.tell' ctx ("Banned user `" '<>' 'TextShow.showt' uid '<>' "` with reason: " '<>' r)
--      'Nothing' -> 'void' $ 'Calamity.Types.Tellable.tell' @'L.Text' ctx "Can only ban users from guilds."
-- @
commandA :: forall ps r.
        ( P.Member (P.Final IO) r,
          TypedCommandC ps r)
        => S.Text
        -- ^ The name of the command
        -> [S.Text]
        -- ^ The aliases for the command
        -> (Context -> CommandForParsers ps r)
        -- ^ The callback for this command
        -> P.Sem (DSLState r) Command
commandA :: Text
-> [Text]
-> (Context -> CommandForParsers ps r)
-> Sem (DSLState r) Command
commandA Text
name [Text]
aliases Context -> CommandForParsers ps r
cmd = do
  Maybe Group
parent <- forall (r :: EffectRow).
MemberWithError (Reader (Maybe Group)) r =>
Sem r (Maybe Group)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Maybe Group)
  Bool
hidden <- Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
P.tag (Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool)
-> Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall a b. (a -> b) -> a -> b
$ forall (r :: EffectRow).
MemberWithError (Reader Bool) r =>
Sem r Bool
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @Bool
  [Check]
checks <- forall (r :: EffectRow).
MemberWithError (Reader [Check]) r =>
Sem r [Check]
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @[Check]
  Context -> Text
help' <- forall (r :: EffectRow).
MemberWithError (Reader (Context -> Text)) r =>
Sem r (Context -> Text)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Context -> L.Text)
  Command
cmd' <- Sem r Command -> Sem (DSLState r) Command
forall (r :: EffectRow) a. Sem r a -> Sem (DSLState r) a
raiseDSL (Sem r Command -> Sem (DSLState r) Command)
-> Sem r Command -> Sem (DSLState r) Command
forall a b. (a -> b) -> a -> b
$ NonEmpty Text
-> Maybe Group
-> Bool
-> [Check]
-> (Context -> Text)
-> (Context -> CommandForParsers ps r)
-> Sem r Command
forall (ps :: [*]) (r :: EffectRow).
(Member (Final IO) r, TypedCommandC ps r) =>
NonEmpty Text
-> Maybe Group
-> Bool
-> [Check]
-> (Context -> Text)
-> (Context -> CommandForParsers ps r)
-> Sem r Command
buildCommand @ps (Text
name Text -> [Text] -> NonEmpty Text
forall a. a -> [a] -> NonEmpty a
:| [Text]
aliases) Maybe Group
parent Bool
hidden [Check]
checks Context -> Text
help' Context -> CommandForParsers ps r
cmd
  HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Command, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ Text -> (Command, AliasType) -> HashMap Text (Command, AliasType)
forall k v. Hashable k => k -> v -> HashMap k v
LH.singleton Text
name (Command
cmd', AliasType
Original)
  HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Command, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Command, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ [(Text, (Command, AliasType))] -> HashMap Text (Command, AliasType)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
LH.fromList [(Text
name, (Command
cmd', AliasType
Alias)) | Text
name <- [Text]
aliases]
  Command -> Sem (DSLState r) Command
forall (f :: * -> *) a. Applicative f => a -> f a
pure Command
cmd'

-- | Set the visibility of any groups or commands registered inside the given
-- action to hidden.
hide :: P.Member (P.Tagged "hidden" (P.Reader Bool)) r
     => P.Sem r a
     -> P.Sem r a
hide :: Sem r a -> Sem r a
hide = forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
forall (e :: Effect) (r :: EffectRow) a.
Member (Tagged "hidden" e) r =>
Sem (e : r) a -> Sem r a
P.tag @"hidden" (Sem (Reader Bool : r) a -> Sem r a)
-> (Sem r a -> Sem (Reader Bool : r) a) -> Sem r a -> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> Bool)
-> Sem (Reader Bool : r) a -> Sem (Reader Bool : r) a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local @Bool (Bool -> Bool -> Bool
forall a b. a -> b -> a
const Bool
True) (Sem (Reader Bool : r) a -> Sem (Reader Bool : r) a)
-> (Sem r a -> Sem (Reader Bool : r) a)
-> Sem r a
-> Sem (Reader Bool : r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sem r a -> Sem (Reader Bool : r) a
forall (e :: Effect) (r :: EffectRow) a. Sem r a -> Sem (e : r) a
P.raise

-- | Set the help for any groups or commands registered inside the given action.
help :: P.Member (P.Reader (Context -> L.Text)) r
     => (Context -> L.Text)
     -> P.Sem r a
     -> P.Sem r a
help :: (Context -> Text) -> Sem r a -> Sem r a
help = ((Context -> Text) -> Context -> Text) -> Sem r a -> Sem r a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local (((Context -> Text) -> Context -> Text) -> Sem r a -> Sem r a)
-> ((Context -> Text) -> (Context -> Text) -> Context -> Text)
-> (Context -> Text)
-> Sem r a
-> Sem r a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Context -> Text) -> (Context -> Text) -> Context -> Text
forall a b. a -> b -> a
const

-- | Add to the list of checks for any commands registered inside the given
-- action.
requires :: [Check]
         -> P.Sem (DSLState r) a
         -> P.Sem (DSLState r) a
requires :: [Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
requires = ([Check] -> [Check]) -> Sem (DSLState r) a -> Sem (DSLState r) a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local (([Check] -> [Check]) -> Sem (DSLState r) a -> Sem (DSLState r) a)
-> ([Check] -> [Check] -> [Check])
-> [Check]
-> Sem (DSLState r) a
-> Sem (DSLState r) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Check] -> [Check] -> [Check]
forall a. Semigroup a => a -> a -> a
(<>)

-- | Construct a check and add it to the list of checks for any commands
-- registered inside the given action.
--
-- Refer to 'Calamity.Commands.Check.Check' for more info on checks.
requires' :: P.Member (P.Final IO) r
          => S.Text
          -- ^ The name of the check
          -> (Context -> P.Sem r (Maybe L.Text))
          -- ^ The callback for the check
          -> P.Sem (DSLState r) a
          -> P.Sem (DSLState r) a
requires' :: Text
-> (Context -> Sem r (Maybe Text))
-> Sem (DSLState r) a
-> Sem (DSLState r) a
requires' Text
name Context -> Sem r (Maybe Text)
cb Sem (DSLState r) a
m = do
  Check
check <- Sem r Check -> Sem (DSLState r) Check
forall (r :: EffectRow) a. Sem r a -> Sem (DSLState r) a
raiseDSL (Sem r Check -> Sem (DSLState r) Check)
-> Sem r Check -> Sem (DSLState r) Check
forall a b. (a -> b) -> a -> b
$ Text -> (Context -> Sem r (Maybe Text)) -> Sem r Check
forall (r :: EffectRow).
Member (Final IO) r =>
Text -> (Context -> Sem r (Maybe Text)) -> Sem r Check
buildCheck Text
name Context -> Sem r (Maybe Text)
cb
  [Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
forall (r :: EffectRow) a.
[Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
requires [Check
check] Sem (DSLState r) a
m

-- | Construct some pure checks and add them to the list of checks for any
-- commands registered inside the given action.
--
-- Refer to 'Calamity.Commands.Check.Check' for more info on checks.
requiresPure :: [(S.Text, Context -> Maybe L.Text)]
             -- A list of check names and check callbacks
             -> P.Sem (DSLState r) a
             -> P.Sem (DSLState r) a
requiresPure :: [(Text, Context -> Maybe Text)]
-> Sem (DSLState r) a -> Sem (DSLState r) a
requiresPure [(Text, Context -> Maybe Text)]
checks = [Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
forall (r :: EffectRow) a.
[Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
requires ([Check] -> Sem (DSLState r) a -> Sem (DSLState r) a)
-> [Check] -> Sem (DSLState r) a -> Sem (DSLState r) a
forall a b. (a -> b) -> a -> b
$ ((Text, Context -> Maybe Text) -> Check)
-> [(Text, Context -> Maybe Text)] -> [Check]
forall a b. (a -> b) -> [a] -> [b]
map ((Text -> (Context -> Maybe Text) -> Check)
-> (Text, Context -> Maybe Text) -> Check
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Text -> (Context -> Maybe Text) -> Check
buildCheckPure) [(Text, Context -> Maybe Text)]
checks

-- | 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
-- 'group'' if you don't want that (i.e. your help function is context aware).
group :: P.Member (P.Final IO) r
      => S.Text
      -- ^ The name of the group
      -> P.Sem (DSLState r) a
      -> P.Sem (DSLState r) a
group :: Text -> Sem (DSLState r) a -> Sem (DSLState r) a
group Text
name Sem (DSLState r) a
m = Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
forall (r :: EffectRow) a.
Member (Final IO) r =>
Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
groupA Text
name [] Sem (DSLState r) a
m

-- | Construct a group with aliases and place any commands registered in the
-- given action into the new group.
--
-- 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
-- 'group'' if you don't want that (i.e. your help function is context aware).
groupA :: P.Member (P.Final IO) r
       => S.Text
       -- ^ The name of the group
       -> [S.Text]
       -- ^ The aliases of the group
       -> P.Sem (DSLState r) a
       -> P.Sem (DSLState r) a
groupA :: Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
groupA Text
name [Text]
aliases Sem (DSLState r) a
m = mdo
  Maybe Group
parent <- forall (r :: EffectRow).
MemberWithError (Reader (Maybe Group)) r =>
Sem r (Maybe Group)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Maybe Group)
  Bool
hidden <- Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
P.tag (Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool)
-> Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall a b. (a -> b) -> a -> b
$ forall (r :: EffectRow).
MemberWithError (Reader Bool) r =>
Sem r Bool
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @Bool
  [Check]
checks <- forall (r :: EffectRow).
MemberWithError (Reader [Check]) r =>
Sem r [Check]
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @[Check]
  Context -> Text
help'  <- forall (r :: EffectRow).
MemberWithError (Reader (Context -> Text)) r =>
Sem r (Context -> Text)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Context -> L.Text)
  Context -> Text
origHelp <- Sem (DSLState r) (Context -> Text)
forall (r :: EffectRow).
Member (Tagged "original-help" (Reader (Context -> Text))) r =>
Sem r (Context -> Text)
fetchOrigHelp
  let group' :: Group
group' = NonEmpty Text
-> Maybe Group
-> Bool
-> HashMap Text (Command, AliasType)
-> HashMap Text (Group, AliasType)
-> (Context -> Text)
-> [Check]
-> Group
Group (Text
name Text -> [Text] -> NonEmpty Text
forall a. a -> [a] -> NonEmpty a
:| [Text]
aliases) Maybe Group
parent Bool
hidden HashMap Text (Command, AliasType)
commands HashMap Text (Group, AliasType)
children Context -> Text
help' [Check]
checks
  (HashMap Text (Group, AliasType)
children, (HashMap Text (Command, AliasType)
commands, a
res)) <- forall (r :: EffectRow) a.
MemberWithError
  (LocalWriter (HashMap Text (Group, AliasType))) r =>
Sem r a -> Sem r (HashMap Text (Group, AliasType), a)
forall o (r :: EffectRow) a.
MemberWithError (LocalWriter o) r =>
Sem r a -> Sem r (o, a)
llisten @(LH.HashMap S.Text (Group, AliasType)) (Sem (DSLState r) (HashMap Text (Command, AliasType), a)
 -> Sem
      (DSLState r)
      (HashMap Text (Group, AliasType),
       (HashMap Text (Command, AliasType), a)))
-> Sem (DSLState r) (HashMap Text (Command, AliasType), a)
-> Sem
     (DSLState r)
     (HashMap Text (Group, AliasType),
      (HashMap Text (Command, AliasType), a))
forall a b. (a -> b) -> a -> b
$
                                 forall (r :: EffectRow) a.
MemberWithError
  (LocalWriter (HashMap Text (Command, AliasType))) r =>
Sem r a -> Sem r (HashMap Text (Command, AliasType), a)
forall o (r :: EffectRow) a.
MemberWithError (LocalWriter o) r =>
Sem r a -> Sem r (o, a)
llisten @(LH.HashMap S.Text (Command, AliasType)) (Sem (DSLState r) a
 -> Sem (DSLState r) (HashMap Text (Command, AliasType), a))
-> Sem (DSLState r) a
-> Sem (DSLState r) (HashMap Text (Command, AliasType), a)
forall a b. (a -> b) -> a -> b
$
                                 (Maybe Group -> Maybe Group)
-> Sem (DSLState r) a -> Sem (DSLState r) a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local @(Maybe Group) (Maybe Group -> Maybe Group -> Maybe Group
forall a b. a -> b -> a
const (Maybe Group -> Maybe Group -> Maybe Group)
-> Maybe Group -> Maybe Group -> Maybe Group
forall a b. (a -> b) -> a -> b
$ Group -> Maybe Group
forall a. a -> Maybe a
Just Group
group') (Sem (DSLState r) a -> Sem (DSLState r) a)
-> Sem (DSLState r) a -> Sem (DSLState r) a
forall a b. (a -> b) -> a -> b
$
                                 ((Context -> Text) -> Context -> Text)
-> Sem (DSLState r) a -> Sem (DSLState r) a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local @(Context -> L.Text) ((Context -> Text) -> (Context -> Text) -> Context -> Text
forall a b. a -> b -> a
const Context -> Text
origHelp) Sem (DSLState r) a
m
  HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Group, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ Text -> (Group, AliasType) -> HashMap Text (Group, AliasType)
forall k v. Hashable k => k -> v -> HashMap k v
LH.singleton Text
name (Group
group', AliasType
Original)
  HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Group, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ [(Text, (Group, AliasType))] -> HashMap Text (Group, AliasType)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
LH.fromList [(Text
name, (Group
group', AliasType
Alias)) | Text
name <- [Text]
aliases]
  a -> Sem (DSLState r) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
res

fetchOrigHelp :: P.Member (P.Tagged "original-help" (P.Reader (Context -> L.Text))) r => P.Sem r (Context -> L.Text)
fetchOrigHelp :: Sem r (Context -> Text)
fetchOrigHelp = Sem (Reader (Context -> Text) : r) (Context -> Text)
-> Sem r (Context -> Text)
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
P.tag Sem (Reader (Context -> Text) : r) (Context -> Text)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask

-- | Construct a group and place any commands registered in the given action
-- into the new group.
--
-- 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
-- value.
group' :: P.Member (P.Final IO) r
         => S.Text
         -- The name of the group
         -> P.Sem (DSLState r) a
         -> P.Sem (DSLState r) a
group' :: Text -> Sem (DSLState r) a -> Sem (DSLState r) a
group' Text
name Sem (DSLState r) a
m = Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
forall (r :: EffectRow) a.
Member (Final IO) r =>
Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
groupA' Text
name [] Sem (DSLState r) a
m

-- | Construct a group with aliases and place any commands registered in the given action
-- into the new group.
--
-- 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
-- value.
groupA' :: P.Member (P.Final IO) r
         => S.Text
         -- ^ The name of the group
         -> [S.Text]
         -- ^ The aliases of the group
         -> P.Sem (DSLState r) a
         -> P.Sem (DSLState r) a
groupA' :: Text -> [Text] -> Sem (DSLState r) a -> Sem (DSLState r) a
groupA' Text
name [Text]
aliases Sem (DSLState r) a
m = mdo
  Maybe Group
parent <- forall (r :: EffectRow).
MemberWithError (Reader (Maybe Group)) r =>
Sem r (Maybe Group)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Maybe Group)
  Bool
hidden <- Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Member (Tagged k2 e) r =>
Sem (e : r) a -> Sem r a
P.tag (Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool)
-> Sem (Reader Bool : DSLState r) Bool -> Sem (DSLState r) Bool
forall a b. (a -> b) -> a -> b
$ forall (r :: EffectRow).
MemberWithError (Reader Bool) r =>
Sem r Bool
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @Bool
  [Check]
checks <- forall (r :: EffectRow).
MemberWithError (Reader [Check]) r =>
Sem r [Check]
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @[Check]
  Context -> Text
help'  <- forall (r :: EffectRow).
MemberWithError (Reader (Context -> Text)) r =>
Sem r (Context -> Text)
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask @(Context -> L.Text)
  let group' :: Group
group' = NonEmpty Text
-> Maybe Group
-> Bool
-> HashMap Text (Command, AliasType)
-> HashMap Text (Group, AliasType)
-> (Context -> Text)
-> [Check]
-> Group
Group (Text
name Text -> [Text] -> NonEmpty Text
forall a. a -> [a] -> NonEmpty a
:| [Text]
aliases) Maybe Group
parent Bool
hidden HashMap Text (Command, AliasType)
commands HashMap Text (Group, AliasType)
children Context -> Text
help' [Check]
checks
  (HashMap Text (Group, AliasType)
children, (HashMap Text (Command, AliasType)
commands, a
res)) <- forall (r :: EffectRow) a.
MemberWithError
  (LocalWriter (HashMap Text (Group, AliasType))) r =>
Sem r a -> Sem r (HashMap Text (Group, AliasType), a)
forall o (r :: EffectRow) a.
MemberWithError (LocalWriter o) r =>
Sem r a -> Sem r (o, a)
llisten @(LH.HashMap S.Text (Group, AliasType)) (Sem (DSLState r) (HashMap Text (Command, AliasType), a)
 -> Sem
      (DSLState r)
      (HashMap Text (Group, AliasType),
       (HashMap Text (Command, AliasType), a)))
-> Sem (DSLState r) (HashMap Text (Command, AliasType), a)
-> Sem
     (DSLState r)
     (HashMap Text (Group, AliasType),
      (HashMap Text (Command, AliasType), a))
forall a b. (a -> b) -> a -> b
$
                                 forall (r :: EffectRow) a.
MemberWithError
  (LocalWriter (HashMap Text (Command, AliasType))) r =>
Sem r a -> Sem r (HashMap Text (Command, AliasType), a)
forall o (r :: EffectRow) a.
MemberWithError (LocalWriter o) r =>
Sem r a -> Sem r (o, a)
llisten @(LH.HashMap S.Text (Command, AliasType)) (Sem (DSLState r) a
 -> Sem (DSLState r) (HashMap Text (Command, AliasType), a))
-> Sem (DSLState r) a
-> Sem (DSLState r) (HashMap Text (Command, AliasType), a)
forall a b. (a -> b) -> a -> b
$
                                 (Maybe Group -> Maybe Group)
-> Sem (DSLState r) a -> Sem (DSLState r) a
forall i (r :: EffectRow) a.
MemberWithError (Reader i) r =>
(i -> i) -> Sem r a -> Sem r a
P.local @(Maybe Group) (Maybe Group -> Maybe Group -> Maybe Group
forall a b. a -> b -> a
const (Maybe Group -> Maybe Group -> Maybe Group)
-> Maybe Group -> Maybe Group -> Maybe Group
forall a b. (a -> b) -> a -> b
$ Group -> Maybe Group
forall a. a -> Maybe a
Just Group
group') Sem (DSLState r) a
m
  HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Group, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ Text -> (Group, AliasType) -> HashMap Text (Group, AliasType)
forall k v. Hashable k => k -> v -> HashMap k v
LH.singleton Text
name (Group
group', AliasType
Original)
  HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall o (r :: EffectRow).
MemberWithError (LocalWriter o) r =>
o -> Sem r ()
ltell (HashMap Text (Group, AliasType) -> Sem (DSLState r) ())
-> HashMap Text (Group, AliasType) -> Sem (DSLState r) ()
forall a b. (a -> b) -> a -> b
$ [(Text, (Group, AliasType))] -> HashMap Text (Group, AliasType)
forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
LH.fromList [(Text
name, (Group
group', AliasType
Alias)) | Text
name <- [Text]
aliases]
  a -> Sem (DSLState r) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
res

-- | Retrieve the final command handler for this block
fetchHandler :: P.Sem (DSLState r) CommandHandler
fetchHandler :: Sem (DSLState r) CommandHandler
fetchHandler = Sem (DSLState r) CommandHandler
forall i (r :: EffectRow). MemberWithError (Reader i) r => Sem r i
P.ask