Simplify command system

This commit is contained in:
Joscha 2020-04-09 19:15:39 +00:00
parent 1313d22056
commit 46dc9242cf
2 changed files with 31 additions and 21 deletions

View file

@ -2,8 +2,9 @@
module Haboli.Euphoria.Command module Haboli.Euphoria.Command
( Command ( Command
, runCommands , cmdSequential
, respondingToCommands , cmdParallel
, respondingToCommand
) where ) where
import Control.Monad import Control.Monad
@ -15,32 +16,41 @@ import Haboli.Euphoria.Client
-- it should return 'True'. Otherwise. it should return 'False'. -- it should return 'True'. Otherwise. it should return 'False'.
type Command e = Message -> Client e Bool type Command e = Message -> Client e Bool
-- | Apply multiple 'Command's to a 'Message' in order until one returns 'True'. -- | Try out multiple 'Command's in order until one returns 'True'. All commands
-- All commands following that one are not applied. -- following that one are not applied. Returns 'True' if any of the commands
runCommands :: [Command e] -> Message -> Client e Bool -- returned 'True'. Returns 'False' otherwise.
runCommands [] _ = pure False cmdSequential :: [Command e] -> Command e
runCommands (c:cs) msg = do cmdSequential [] _ = pure False
cmdSequential (c:cs) msg = do
abort <- c msg abort <- c msg
if abort if abort
then pure True then pure True
else runCommands cs msg else cmdSequential cs msg
-- | @'respondingToCommands' getCommands getEvent@ runs a list of 'Command's on -- | Apply multiple 'Command's in order. Each command will be applied. Returns
-- all 'EventSend's. It passes through all events unmodified. -- 'True' if at least one of the commands returned 'True'. Returns 'False'
-- otherwise.
cmdParallel :: [Command e] -> Command e
cmdParallel commands msg = do
results <- traverse ($msg) commands
pure $ or results
-- | @'respondingToCommand' getCommand getEvent@ runs a 'Command' on all
-- 'EventSend's. It passes through all events unmodified.
-- --
-- The @getEvent@ action is used to obtain the next 'Event'. The @getCommands@ -- The @getEvent@ action is used to obtain the next 'Event'. The @getCommand@
-- action is used to obtain the currently available commands. @getCommands@ is -- action is used to obtain the currently available command. @getCommand@ is
-- called directly after a new 'Event' becomes available through @getEvent@. -- called directly after a new 'Event' becomes available through @getEvent@.
-- --
-- This utility function is meant to be wrapped directly or indirectly around -- This utility function is meant to be wrapped directly or indirectly around
-- 'nextEvent': -- 'nextEvent':
-- --
-- > event <- respondingToCommands commands nextEvent -- > event <- respondingToCommand command nextEvent
respondingToCommands :: Client e [Command e] -> Client e Event -> Client e Event respondingToCommand :: Client e (Command e) -> Client e Event -> Client e Event
respondingToCommands getCommands getEvent = do respondingToCommand getCommand getEvent = do
event <- getEvent event <- getEvent
commands <- getCommands command <- getCommand
case event of case event of
EventSend e -> void $ runCommands commands $ sendMessage e EventSend e -> void $ command $ sendMessage e
_ -> pure () _ -> pure ()
pure event pure event

View file

@ -50,15 +50,15 @@ exampleBot mPasswd = do
botMain :: MVar BotState -> Client T.Text () botMain :: MVar BotState -> Client T.Text ()
botMain stateVar = forever $ do botMain stateVar = forever $ do
event <- respondingToCommands (getCommands stateVar) $ event <- respondingToCommand (getCommand stateVar) $
respondingToPing nextEvent respondingToPing nextEvent
updateFromEventVia botListing stateVar event updateFromEventVia botListing stateVar event
getCommands :: MVar BotState -> Client e [Command T.Text] getCommand :: MVar BotState -> Client e (Command T.Text)
getCommands stateVar = do getCommand stateVar = do
state <- liftIO $ readMVar stateVar state <- liftIO $ readMVar stateVar
let name = state ^. botListing . lsSelfL . svNickL let name = state ^. botListing . lsSelfL . svNickL
pure pure $ cmdSequential
[ botrulezPingGeneral [ botrulezPingGeneral
, botrulezPingSpecific name , botrulezPingSpecific name
, botrulezHelpSpecific name , botrulezHelpSpecific name