{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Sum types representing the Swarm events
-- abstracted away from keybindings.
module Swarm.TUI.Model.Event (
  SwarmEvent (..),
  MainEvent (..),
  REPLEvent (..),
  WorldEvent (..),
  RobotEvent (..),
  swarmEvents,
  defaultSwarmBindings,
) where

import Brick.Keybindings
import Control.Arrow ((&&&))
import Data.Bifunctor (first)
import Data.List.Extra (enumerate)
import Data.Text (Text)
import GHC.Generics (Generic)
import Generic.Data (FiniteEnumeration (..))
import Graphics.Vty qualified as V
import Swarm.Language.Syntax.Direction (AbsoluteDir (..), Direction (..), directionSyntax)

-- | Swarm named TUI event type.
--
-- See Note [how Swarm event handlers work]
data SwarmEvent
  = Main MainEvent
  | REPL REPLEvent
  | World WorldEvent
  | Robot RobotEvent
  deriving (SwarmEvent -> SwarmEvent -> Bool
(SwarmEvent -> SwarmEvent -> Bool)
-> (SwarmEvent -> SwarmEvent -> Bool) -> Eq SwarmEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SwarmEvent -> SwarmEvent -> Bool
== :: SwarmEvent -> SwarmEvent -> Bool
$c/= :: SwarmEvent -> SwarmEvent -> Bool
/= :: SwarmEvent -> SwarmEvent -> Bool
Eq, Eq SwarmEvent
Eq SwarmEvent =>
(SwarmEvent -> SwarmEvent -> Ordering)
-> (SwarmEvent -> SwarmEvent -> Bool)
-> (SwarmEvent -> SwarmEvent -> Bool)
-> (SwarmEvent -> SwarmEvent -> Bool)
-> (SwarmEvent -> SwarmEvent -> Bool)
-> (SwarmEvent -> SwarmEvent -> SwarmEvent)
-> (SwarmEvent -> SwarmEvent -> SwarmEvent)
-> Ord SwarmEvent
SwarmEvent -> SwarmEvent -> Bool
SwarmEvent -> SwarmEvent -> Ordering
SwarmEvent -> SwarmEvent -> SwarmEvent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: SwarmEvent -> SwarmEvent -> Ordering
compare :: SwarmEvent -> SwarmEvent -> Ordering
$c< :: SwarmEvent -> SwarmEvent -> Bool
< :: SwarmEvent -> SwarmEvent -> Bool
$c<= :: SwarmEvent -> SwarmEvent -> Bool
<= :: SwarmEvent -> SwarmEvent -> Bool
$c> :: SwarmEvent -> SwarmEvent -> Bool
> :: SwarmEvent -> SwarmEvent -> Bool
$c>= :: SwarmEvent -> SwarmEvent -> Bool
>= :: SwarmEvent -> SwarmEvent -> Bool
$cmax :: SwarmEvent -> SwarmEvent -> SwarmEvent
max :: SwarmEvent -> SwarmEvent -> SwarmEvent
$cmin :: SwarmEvent -> SwarmEvent -> SwarmEvent
min :: SwarmEvent -> SwarmEvent -> SwarmEvent
Ord, Int -> SwarmEvent -> ShowS
[SwarmEvent] -> ShowS
SwarmEvent -> String
(Int -> SwarmEvent -> ShowS)
-> (SwarmEvent -> String)
-> ([SwarmEvent] -> ShowS)
-> Show SwarmEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SwarmEvent -> ShowS
showsPrec :: Int -> SwarmEvent -> ShowS
$cshow :: SwarmEvent -> String
show :: SwarmEvent -> String
$cshowList :: [SwarmEvent] -> ShowS
showList :: [SwarmEvent] -> ShowS
Show, (forall x. SwarmEvent -> Rep SwarmEvent x)
-> (forall x. Rep SwarmEvent x -> SwarmEvent) -> Generic SwarmEvent
forall x. Rep SwarmEvent x -> SwarmEvent
forall x. SwarmEvent -> Rep SwarmEvent x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SwarmEvent -> Rep SwarmEvent x
from :: forall x. SwarmEvent -> Rep SwarmEvent x
$cto :: forall x. Rep SwarmEvent x -> SwarmEvent
to :: forall x. Rep SwarmEvent x -> SwarmEvent
Generic)
  deriving (Int -> SwarmEvent
SwarmEvent -> Int
SwarmEvent -> [SwarmEvent]
SwarmEvent -> SwarmEvent
SwarmEvent -> SwarmEvent -> [SwarmEvent]
SwarmEvent -> SwarmEvent -> SwarmEvent -> [SwarmEvent]
(SwarmEvent -> SwarmEvent)
-> (SwarmEvent -> SwarmEvent)
-> (Int -> SwarmEvent)
-> (SwarmEvent -> Int)
-> (SwarmEvent -> [SwarmEvent])
-> (SwarmEvent -> SwarmEvent -> [SwarmEvent])
-> (SwarmEvent -> SwarmEvent -> [SwarmEvent])
-> (SwarmEvent -> SwarmEvent -> SwarmEvent -> [SwarmEvent])
-> Enum SwarmEvent
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: SwarmEvent -> SwarmEvent
succ :: SwarmEvent -> SwarmEvent
$cpred :: SwarmEvent -> SwarmEvent
pred :: SwarmEvent -> SwarmEvent
$ctoEnum :: Int -> SwarmEvent
toEnum :: Int -> SwarmEvent
$cfromEnum :: SwarmEvent -> Int
fromEnum :: SwarmEvent -> Int
$cenumFrom :: SwarmEvent -> [SwarmEvent]
enumFrom :: SwarmEvent -> [SwarmEvent]
$cenumFromThen :: SwarmEvent -> SwarmEvent -> [SwarmEvent]
enumFromThen :: SwarmEvent -> SwarmEvent -> [SwarmEvent]
$cenumFromTo :: SwarmEvent -> SwarmEvent -> [SwarmEvent]
enumFromTo :: SwarmEvent -> SwarmEvent -> [SwarmEvent]
$cenumFromThenTo :: SwarmEvent -> SwarmEvent -> SwarmEvent -> [SwarmEvent]
enumFromThenTo :: SwarmEvent -> SwarmEvent -> SwarmEvent -> [SwarmEvent]
Enum, SwarmEvent
SwarmEvent -> SwarmEvent -> Bounded SwarmEvent
forall a. a -> a -> Bounded a
$cminBound :: SwarmEvent
minBound :: SwarmEvent
$cmaxBound :: SwarmEvent
maxBound :: SwarmEvent
Bounded) via (FiniteEnumeration SwarmEvent)

swarmEvents :: KeyEvents SwarmEvent
swarmEvents :: KeyEvents SwarmEvent
swarmEvents =
  [(Text, SwarmEvent)] -> KeyEvents SwarmEvent
forall k. Ord k => [(Text, k)] -> KeyEvents k
keyEvents ([(Text, SwarmEvent)] -> KeyEvents SwarmEvent)
-> [(Text, SwarmEvent)] -> KeyEvents SwarmEvent
forall a b. (a -> b) -> a -> b
$
    [[(Text, SwarmEvent)]] -> [(Text, SwarmEvent)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
      [ (MainEvent -> SwarmEvent)
-> KeyEvents MainEvent -> [(Text, SwarmEvent)]
forall {a} {b}. (a -> b) -> KeyEvents a -> [(Text, b)]
embed MainEvent -> SwarmEvent
Main KeyEvents MainEvent
mainEvents
      , (REPLEvent -> SwarmEvent)
-> KeyEvents REPLEvent -> [(Text, SwarmEvent)]
forall {a} {b}. (a -> b) -> KeyEvents a -> [(Text, b)]
embed REPLEvent -> SwarmEvent
REPL KeyEvents REPLEvent
replEvents
      , (WorldEvent -> SwarmEvent)
-> KeyEvents WorldEvent -> [(Text, SwarmEvent)]
forall {a} {b}. (a -> b) -> KeyEvents a -> [(Text, b)]
embed WorldEvent -> SwarmEvent
World KeyEvents WorldEvent
worldPanelEvents
      , (RobotEvent -> SwarmEvent)
-> KeyEvents RobotEvent -> [(Text, SwarmEvent)]
forall {a} {b}. (a -> b) -> KeyEvents a -> [(Text, b)]
embed RobotEvent -> SwarmEvent
Robot KeyEvents RobotEvent
robotPanelEvents
      ]
 where
  embed :: (a -> b) -> KeyEvents a -> [(Text, b)]
embed a -> b
f = ((Text, a) -> (Text, b)) -> [(Text, a)] -> [(Text, b)]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> (Text, a) -> (Text, b)
forall a b. (a -> b) -> (Text, a) -> (Text, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f) ([(Text, a)] -> [(Text, b)])
-> (KeyEvents a -> [(Text, a)]) -> KeyEvents a -> [(Text, b)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. KeyEvents a -> [(Text, a)]
forall k. KeyEvents k -> [(Text, k)]
keyEventsList

defaultSwarmBindings :: [(SwarmEvent, [Binding])]
defaultSwarmBindings :: [(SwarmEvent, [Binding])]
defaultSwarmBindings =
  [[(SwarmEvent, [Binding])]] -> [(SwarmEvent, [Binding])]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ (MainEvent -> SwarmEvent)
-> [(MainEvent, [Binding])] -> [(SwarmEvent, [Binding])]
forall {a} {b} {c}. (a -> b) -> [(a, c)] -> [(b, c)]
embed MainEvent -> SwarmEvent
Main [(MainEvent, [Binding])]
defaultMainBindings
    , (REPLEvent -> SwarmEvent)
-> [(REPLEvent, [Binding])] -> [(SwarmEvent, [Binding])]
forall {a} {b} {c}. (a -> b) -> [(a, c)] -> [(b, c)]
embed REPLEvent -> SwarmEvent
REPL [(REPLEvent, [Binding])]
defaultReplBindings
    , (WorldEvent -> SwarmEvent)
-> [(WorldEvent, [Binding])] -> [(SwarmEvent, [Binding])]
forall {a} {b} {c}. (a -> b) -> [(a, c)] -> [(b, c)]
embed WorldEvent -> SwarmEvent
World [(WorldEvent, [Binding])]
defaultWorldPanelBindings
    , (RobotEvent -> SwarmEvent)
-> [(RobotEvent, [Binding])] -> [(SwarmEvent, [Binding])]
forall {a} {b} {c}. (a -> b) -> [(a, c)] -> [(b, c)]
embed RobotEvent -> SwarmEvent
Robot [(RobotEvent, [Binding])]
defaultRobotPanelBindings
    ]
 where
  embed :: (a -> b) -> [(a, c)] -> [(b, c)]
embed = ((a, c) -> (b, c)) -> [(a, c)] -> [(b, c)]
forall a b. (a -> b) -> [a] -> [b]
map (((a, c) -> (b, c)) -> [(a, c)] -> [(b, c)])
-> ((a -> b) -> (a, c) -> (b, c))
-> (a -> b)
-> [(a, c)]
-> [(b, c)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> (a, c) -> (b, c)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first

-- ----------------------------------------------
--                 MAIN EVENTS
-- ----------------------------------------------

-- | Main abstract keybinding events while running the game itself.
--
-- See 'Swarm.TUI.Controller.MainEventHandler.'.
data MainEvent
  = QuitEvent
  | ViewHelpEvent
  | ViewRobotsEvent
  | ViewRecipesEvent
  | ViewCommandsEvent
  | ViewMessagesEvent
  | ViewStructuresEvent
  | ViewGoalEvent
  | HideRobotsEvent
  | ShowCESKDebugEvent
  | PauseEvent
  | RunSingleTickEvent
  | IncreaseTpsEvent
  | DecreaseTpsEvent
  | FocusWorldEvent
  | FocusRobotEvent
  | FocusREPLEvent
  | FocusInfoEvent
  | ToggleCreativeModeEvent
  | ToggleWorldEditorEvent
  | ToggleREPLVisibilityEvent
  | ViewBaseEvent
  | ToggleFPSEvent
  deriving (MainEvent -> MainEvent -> Bool
(MainEvent -> MainEvent -> Bool)
-> (MainEvent -> MainEvent -> Bool) -> Eq MainEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MainEvent -> MainEvent -> Bool
== :: MainEvent -> MainEvent -> Bool
$c/= :: MainEvent -> MainEvent -> Bool
/= :: MainEvent -> MainEvent -> Bool
Eq, Eq MainEvent
Eq MainEvent =>
(MainEvent -> MainEvent -> Ordering)
-> (MainEvent -> MainEvent -> Bool)
-> (MainEvent -> MainEvent -> Bool)
-> (MainEvent -> MainEvent -> Bool)
-> (MainEvent -> MainEvent -> Bool)
-> (MainEvent -> MainEvent -> MainEvent)
-> (MainEvent -> MainEvent -> MainEvent)
-> Ord MainEvent
MainEvent -> MainEvent -> Bool
MainEvent -> MainEvent -> Ordering
MainEvent -> MainEvent -> MainEvent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: MainEvent -> MainEvent -> Ordering
compare :: MainEvent -> MainEvent -> Ordering
$c< :: MainEvent -> MainEvent -> Bool
< :: MainEvent -> MainEvent -> Bool
$c<= :: MainEvent -> MainEvent -> Bool
<= :: MainEvent -> MainEvent -> Bool
$c> :: MainEvent -> MainEvent -> Bool
> :: MainEvent -> MainEvent -> Bool
$c>= :: MainEvent -> MainEvent -> Bool
>= :: MainEvent -> MainEvent -> Bool
$cmax :: MainEvent -> MainEvent -> MainEvent
max :: MainEvent -> MainEvent -> MainEvent
$cmin :: MainEvent -> MainEvent -> MainEvent
min :: MainEvent -> MainEvent -> MainEvent
Ord, Int -> MainEvent -> ShowS
[MainEvent] -> ShowS
MainEvent -> String
(Int -> MainEvent -> ShowS)
-> (MainEvent -> String)
-> ([MainEvent] -> ShowS)
-> Show MainEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MainEvent -> ShowS
showsPrec :: Int -> MainEvent -> ShowS
$cshow :: MainEvent -> String
show :: MainEvent -> String
$cshowList :: [MainEvent] -> ShowS
showList :: [MainEvent] -> ShowS
Show, Int -> MainEvent
MainEvent -> Int
MainEvent -> [MainEvent]
MainEvent -> MainEvent
MainEvent -> MainEvent -> [MainEvent]
MainEvent -> MainEvent -> MainEvent -> [MainEvent]
(MainEvent -> MainEvent)
-> (MainEvent -> MainEvent)
-> (Int -> MainEvent)
-> (MainEvent -> Int)
-> (MainEvent -> [MainEvent])
-> (MainEvent -> MainEvent -> [MainEvent])
-> (MainEvent -> MainEvent -> [MainEvent])
-> (MainEvent -> MainEvent -> MainEvent -> [MainEvent])
-> Enum MainEvent
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: MainEvent -> MainEvent
succ :: MainEvent -> MainEvent
$cpred :: MainEvent -> MainEvent
pred :: MainEvent -> MainEvent
$ctoEnum :: Int -> MainEvent
toEnum :: Int -> MainEvent
$cfromEnum :: MainEvent -> Int
fromEnum :: MainEvent -> Int
$cenumFrom :: MainEvent -> [MainEvent]
enumFrom :: MainEvent -> [MainEvent]
$cenumFromThen :: MainEvent -> MainEvent -> [MainEvent]
enumFromThen :: MainEvent -> MainEvent -> [MainEvent]
$cenumFromTo :: MainEvent -> MainEvent -> [MainEvent]
enumFromTo :: MainEvent -> MainEvent -> [MainEvent]
$cenumFromThenTo :: MainEvent -> MainEvent -> MainEvent -> [MainEvent]
enumFromThenTo :: MainEvent -> MainEvent -> MainEvent -> [MainEvent]
Enum, MainEvent
MainEvent -> MainEvent -> Bounded MainEvent
forall a. a -> a -> Bounded a
$cminBound :: MainEvent
minBound :: MainEvent
$cmaxBound :: MainEvent
maxBound :: MainEvent
Bounded)

mainEvents :: KeyEvents MainEvent
mainEvents :: KeyEvents MainEvent
mainEvents = (MainEvent -> Text) -> KeyEvents MainEvent
forall e. (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents ((MainEvent -> Text) -> KeyEvents MainEvent)
-> (MainEvent -> Text) -> KeyEvents MainEvent
forall a b. (a -> b) -> a -> b
$ \case
  MainEvent
QuitEvent -> Text
"quit"
  MainEvent
ViewHelpEvent -> Text
"view help"
  MainEvent
ViewRobotsEvent -> Text
"view robots"
  MainEvent
ViewRecipesEvent -> Text
"view recipes"
  MainEvent
ViewCommandsEvent -> Text
"view commands"
  MainEvent
ViewMessagesEvent -> Text
"view messages"
  MainEvent
ViewStructuresEvent -> Text
"view structures"
  MainEvent
ViewGoalEvent -> Text
"view goal"
  MainEvent
HideRobotsEvent -> Text
"hide robots"
  MainEvent
ShowCESKDebugEvent -> Text
"debug CESK"
  MainEvent
PauseEvent -> Text
"pause"
  MainEvent
RunSingleTickEvent -> Text
"run single tick"
  MainEvent
IncreaseTpsEvent -> Text
"increse TPS"
  MainEvent
DecreaseTpsEvent -> Text
"decrease TPS"
  MainEvent
FocusWorldEvent -> Text
"focus World"
  MainEvent
FocusRobotEvent -> Text
"focus Robot"
  MainEvent
FocusREPLEvent -> Text
"focus REPL"
  MainEvent
FocusInfoEvent -> Text
"focus Info"
  MainEvent
ToggleCreativeModeEvent -> Text
"creative mode"
  MainEvent
ToggleWorldEditorEvent -> Text
"world editor"
  MainEvent
ToggleREPLVisibilityEvent -> Text
"toggle REPL"
  MainEvent
ViewBaseEvent -> Text
"view base robot"
  MainEvent
ToggleFPSEvent -> Text
"toggle FPS"

defaultMainBindings :: [(MainEvent, [Binding])]
defaultMainBindings :: [(MainEvent, [Binding])]
defaultMainBindings = (MainEvent -> [Binding]) -> [(MainEvent, [Binding])]
forall e.
(Bounded e, Enum e) =>
(e -> [Binding]) -> [(e, [Binding])]
allBindings ((MainEvent -> [Binding]) -> [(MainEvent, [Binding])])
-> (MainEvent -> [Binding]) -> [(MainEvent, [Binding])]
forall a b. (a -> b) -> a -> b
$ \case
  MainEvent
QuitEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'q']
  MainEvent
ViewHelpEvent -> [Int -> Binding
fn Int
1]
  MainEvent
ViewRobotsEvent -> [Int -> Binding
fn Int
2]
  MainEvent
ViewRecipesEvent -> [Int -> Binding
fn Int
3]
  MainEvent
ViewCommandsEvent -> [Int -> Binding
fn Int
4]
  MainEvent
ViewMessagesEvent -> [Int -> Binding
fn Int
5]
  MainEvent
ViewStructuresEvent -> [Int -> Binding
fn Int
6]
  MainEvent
ViewGoalEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'g']
  MainEvent
HideRobotsEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'h']
  MainEvent
ShowCESKDebugEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'd']
  MainEvent
PauseEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'p']
  MainEvent
RunSingleTickEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'o']
  MainEvent
IncreaseTpsEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'x']
  MainEvent
DecreaseTpsEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'z']
  MainEvent
FocusWorldEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'w']
  MainEvent
FocusRobotEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'e']
  MainEvent
FocusREPLEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'r']
  MainEvent
FocusInfoEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
't']
  MainEvent
ToggleCreativeModeEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'v']
  MainEvent
ToggleWorldEditorEvent -> []
  MainEvent
ToggleREPLVisibilityEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
',']
  MainEvent
ViewBaseEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'c']
  MainEvent
ToggleFPSEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'f']

-- ----------------------------------------------
--                 REPL EVENTS
-- ----------------------------------------------

-- | REPL abstract keybinding events.
--
-- See 'Swarm.TUI.Controller.REPLEventHandler'.
data REPLEvent
  = CancelRunningProgramEvent
  | TogglePilotingModeEvent
  | ToggleCustomKeyHandlingEvent
  deriving (REPLEvent -> REPLEvent -> Bool
(REPLEvent -> REPLEvent -> Bool)
-> (REPLEvent -> REPLEvent -> Bool) -> Eq REPLEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: REPLEvent -> REPLEvent -> Bool
== :: REPLEvent -> REPLEvent -> Bool
$c/= :: REPLEvent -> REPLEvent -> Bool
/= :: REPLEvent -> REPLEvent -> Bool
Eq, Eq REPLEvent
Eq REPLEvent =>
(REPLEvent -> REPLEvent -> Ordering)
-> (REPLEvent -> REPLEvent -> Bool)
-> (REPLEvent -> REPLEvent -> Bool)
-> (REPLEvent -> REPLEvent -> Bool)
-> (REPLEvent -> REPLEvent -> Bool)
-> (REPLEvent -> REPLEvent -> REPLEvent)
-> (REPLEvent -> REPLEvent -> REPLEvent)
-> Ord REPLEvent
REPLEvent -> REPLEvent -> Bool
REPLEvent -> REPLEvent -> Ordering
REPLEvent -> REPLEvent -> REPLEvent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: REPLEvent -> REPLEvent -> Ordering
compare :: REPLEvent -> REPLEvent -> Ordering
$c< :: REPLEvent -> REPLEvent -> Bool
< :: REPLEvent -> REPLEvent -> Bool
$c<= :: REPLEvent -> REPLEvent -> Bool
<= :: REPLEvent -> REPLEvent -> Bool
$c> :: REPLEvent -> REPLEvent -> Bool
> :: REPLEvent -> REPLEvent -> Bool
$c>= :: REPLEvent -> REPLEvent -> Bool
>= :: REPLEvent -> REPLEvent -> Bool
$cmax :: REPLEvent -> REPLEvent -> REPLEvent
max :: REPLEvent -> REPLEvent -> REPLEvent
$cmin :: REPLEvent -> REPLEvent -> REPLEvent
min :: REPLEvent -> REPLEvent -> REPLEvent
Ord, Int -> REPLEvent -> ShowS
[REPLEvent] -> ShowS
REPLEvent -> String
(Int -> REPLEvent -> ShowS)
-> (REPLEvent -> String)
-> ([REPLEvent] -> ShowS)
-> Show REPLEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> REPLEvent -> ShowS
showsPrec :: Int -> REPLEvent -> ShowS
$cshow :: REPLEvent -> String
show :: REPLEvent -> String
$cshowList :: [REPLEvent] -> ShowS
showList :: [REPLEvent] -> ShowS
Show, Int -> REPLEvent
REPLEvent -> Int
REPLEvent -> [REPLEvent]
REPLEvent -> REPLEvent
REPLEvent -> REPLEvent -> [REPLEvent]
REPLEvent -> REPLEvent -> REPLEvent -> [REPLEvent]
(REPLEvent -> REPLEvent)
-> (REPLEvent -> REPLEvent)
-> (Int -> REPLEvent)
-> (REPLEvent -> Int)
-> (REPLEvent -> [REPLEvent])
-> (REPLEvent -> REPLEvent -> [REPLEvent])
-> (REPLEvent -> REPLEvent -> [REPLEvent])
-> (REPLEvent -> REPLEvent -> REPLEvent -> [REPLEvent])
-> Enum REPLEvent
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: REPLEvent -> REPLEvent
succ :: REPLEvent -> REPLEvent
$cpred :: REPLEvent -> REPLEvent
pred :: REPLEvent -> REPLEvent
$ctoEnum :: Int -> REPLEvent
toEnum :: Int -> REPLEvent
$cfromEnum :: REPLEvent -> Int
fromEnum :: REPLEvent -> Int
$cenumFrom :: REPLEvent -> [REPLEvent]
enumFrom :: REPLEvent -> [REPLEvent]
$cenumFromThen :: REPLEvent -> REPLEvent -> [REPLEvent]
enumFromThen :: REPLEvent -> REPLEvent -> [REPLEvent]
$cenumFromTo :: REPLEvent -> REPLEvent -> [REPLEvent]
enumFromTo :: REPLEvent -> REPLEvent -> [REPLEvent]
$cenumFromThenTo :: REPLEvent -> REPLEvent -> REPLEvent -> [REPLEvent]
enumFromThenTo :: REPLEvent -> REPLEvent -> REPLEvent -> [REPLEvent]
Enum, REPLEvent
REPLEvent -> REPLEvent -> Bounded REPLEvent
forall a. a -> a -> Bounded a
$cminBound :: REPLEvent
minBound :: REPLEvent
$cmaxBound :: REPLEvent
maxBound :: REPLEvent
Bounded)

replEvents :: KeyEvents REPLEvent
replEvents :: KeyEvents REPLEvent
replEvents = (REPLEvent -> Text) -> KeyEvents REPLEvent
forall e. (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents ((REPLEvent -> Text) -> KeyEvents REPLEvent)
-> (REPLEvent -> Text) -> KeyEvents REPLEvent
forall a b. (a -> b) -> a -> b
$ \case
  REPLEvent
CancelRunningProgramEvent -> Text
"cancel running program"
  REPLEvent
ToggleCustomKeyHandlingEvent -> Text
"toggle custom key handling"
  REPLEvent
TogglePilotingModeEvent -> Text
"toggle piloting mode"

defaultReplBindings :: [(REPLEvent, [Binding])]
defaultReplBindings :: [(REPLEvent, [Binding])]
defaultReplBindings = (REPLEvent -> [Binding]) -> [(REPLEvent, [Binding])]
forall e.
(Bounded e, Enum e) =>
(e -> [Binding]) -> [(e, [Binding])]
allBindings ((REPLEvent -> [Binding]) -> [(REPLEvent, [Binding])])
-> (REPLEvent -> [Binding]) -> [(REPLEvent, [Binding])]
forall a b. (a -> b) -> a -> b
$ \case
  REPLEvent
CancelRunningProgramEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
ctrl Char
'c', Key -> Binding
forall a. ToBinding a => a -> Binding
bind Key
V.KEsc]
  REPLEvent
TogglePilotingModeEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'p']
  REPLEvent
ToggleCustomKeyHandlingEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
meta Char
'k']

-- ----------------------------------------------
--                 REPL EVENTS
-- ----------------------------------------------

newtype WorldEvent
  = MoveViewEvent AbsoluteDir
  deriving (WorldEvent -> WorldEvent -> Bool
(WorldEvent -> WorldEvent -> Bool)
-> (WorldEvent -> WorldEvent -> Bool) -> Eq WorldEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WorldEvent -> WorldEvent -> Bool
== :: WorldEvent -> WorldEvent -> Bool
$c/= :: WorldEvent -> WorldEvent -> Bool
/= :: WorldEvent -> WorldEvent -> Bool
Eq, Eq WorldEvent
Eq WorldEvent =>
(WorldEvent -> WorldEvent -> Ordering)
-> (WorldEvent -> WorldEvent -> Bool)
-> (WorldEvent -> WorldEvent -> Bool)
-> (WorldEvent -> WorldEvent -> Bool)
-> (WorldEvent -> WorldEvent -> Bool)
-> (WorldEvent -> WorldEvent -> WorldEvent)
-> (WorldEvent -> WorldEvent -> WorldEvent)
-> Ord WorldEvent
WorldEvent -> WorldEvent -> Bool
WorldEvent -> WorldEvent -> Ordering
WorldEvent -> WorldEvent -> WorldEvent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: WorldEvent -> WorldEvent -> Ordering
compare :: WorldEvent -> WorldEvent -> Ordering
$c< :: WorldEvent -> WorldEvent -> Bool
< :: WorldEvent -> WorldEvent -> Bool
$c<= :: WorldEvent -> WorldEvent -> Bool
<= :: WorldEvent -> WorldEvent -> Bool
$c> :: WorldEvent -> WorldEvent -> Bool
> :: WorldEvent -> WorldEvent -> Bool
$c>= :: WorldEvent -> WorldEvent -> Bool
>= :: WorldEvent -> WorldEvent -> Bool
$cmax :: WorldEvent -> WorldEvent -> WorldEvent
max :: WorldEvent -> WorldEvent -> WorldEvent
$cmin :: WorldEvent -> WorldEvent -> WorldEvent
min :: WorldEvent -> WorldEvent -> WorldEvent
Ord, Int -> WorldEvent -> ShowS
[WorldEvent] -> ShowS
WorldEvent -> String
(Int -> WorldEvent -> ShowS)
-> (WorldEvent -> String)
-> ([WorldEvent] -> ShowS)
-> Show WorldEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> WorldEvent -> ShowS
showsPrec :: Int -> WorldEvent -> ShowS
$cshow :: WorldEvent -> String
show :: WorldEvent -> String
$cshowList :: [WorldEvent] -> ShowS
showList :: [WorldEvent] -> ShowS
Show, (forall x. WorldEvent -> Rep WorldEvent x)
-> (forall x. Rep WorldEvent x -> WorldEvent) -> Generic WorldEvent
forall x. Rep WorldEvent x -> WorldEvent
forall x. WorldEvent -> Rep WorldEvent x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. WorldEvent -> Rep WorldEvent x
from :: forall x. WorldEvent -> Rep WorldEvent x
$cto :: forall x. Rep WorldEvent x -> WorldEvent
to :: forall x. Rep WorldEvent x -> WorldEvent
Generic)
  deriving (Int -> WorldEvent
WorldEvent -> Int
WorldEvent -> [WorldEvent]
WorldEvent -> WorldEvent
WorldEvent -> WorldEvent -> [WorldEvent]
WorldEvent -> WorldEvent -> WorldEvent -> [WorldEvent]
(WorldEvent -> WorldEvent)
-> (WorldEvent -> WorldEvent)
-> (Int -> WorldEvent)
-> (WorldEvent -> Int)
-> (WorldEvent -> [WorldEvent])
-> (WorldEvent -> WorldEvent -> [WorldEvent])
-> (WorldEvent -> WorldEvent -> [WorldEvent])
-> (WorldEvent -> WorldEvent -> WorldEvent -> [WorldEvent])
-> Enum WorldEvent
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: WorldEvent -> WorldEvent
succ :: WorldEvent -> WorldEvent
$cpred :: WorldEvent -> WorldEvent
pred :: WorldEvent -> WorldEvent
$ctoEnum :: Int -> WorldEvent
toEnum :: Int -> WorldEvent
$cfromEnum :: WorldEvent -> Int
fromEnum :: WorldEvent -> Int
$cenumFrom :: WorldEvent -> [WorldEvent]
enumFrom :: WorldEvent -> [WorldEvent]
$cenumFromThen :: WorldEvent -> WorldEvent -> [WorldEvent]
enumFromThen :: WorldEvent -> WorldEvent -> [WorldEvent]
$cenumFromTo :: WorldEvent -> WorldEvent -> [WorldEvent]
enumFromTo :: WorldEvent -> WorldEvent -> [WorldEvent]
$cenumFromThenTo :: WorldEvent -> WorldEvent -> WorldEvent -> [WorldEvent]
enumFromThenTo :: WorldEvent -> WorldEvent -> WorldEvent -> [WorldEvent]
Enum, WorldEvent
WorldEvent -> WorldEvent -> Bounded WorldEvent
forall a. a -> a -> Bounded a
$cminBound :: WorldEvent
minBound :: WorldEvent
$cmaxBound :: WorldEvent
maxBound :: WorldEvent
Bounded) via (FiniteEnumeration WorldEvent)

worldPanelEvents :: KeyEvents WorldEvent
worldPanelEvents :: KeyEvents WorldEvent
worldPanelEvents = (WorldEvent -> Text) -> KeyEvents WorldEvent
forall e. (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents ((WorldEvent -> Text) -> KeyEvents WorldEvent)
-> (WorldEvent -> Text) -> KeyEvents WorldEvent
forall a b. (a -> b) -> a -> b
$ \case
  MoveViewEvent AbsoluteDir
d -> Text
"move view " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Direction -> Text
directionSyntax (AbsoluteDir -> Direction
DAbsolute AbsoluteDir
d)

defaultWorldPanelBindings :: [(WorldEvent, [Binding])]
defaultWorldPanelBindings :: [(WorldEvent, [Binding])]
defaultWorldPanelBindings = (WorldEvent -> [Binding]) -> [(WorldEvent, [Binding])]
forall e.
(Bounded e, Enum e) =>
(e -> [Binding]) -> [(e, [Binding])]
allBindings ((WorldEvent -> [Binding]) -> [(WorldEvent, [Binding])])
-> (WorldEvent -> [Binding]) -> [(WorldEvent, [Binding])]
forall a b. (a -> b) -> a -> b
$ \case
  MoveViewEvent AbsoluteDir
DWest -> [Key -> Binding
forall a. ToBinding a => a -> Binding
bind Key
V.KLeft, Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'h']
  MoveViewEvent AbsoluteDir
DSouth -> [Key -> Binding
forall a. ToBinding a => a -> Binding
bind Key
V.KDown, Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'j']
  MoveViewEvent AbsoluteDir
DNorth -> [Key -> Binding
forall a. ToBinding a => a -> Binding
bind Key
V.KUp, Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'k']
  MoveViewEvent AbsoluteDir
DEast -> [Key -> Binding
forall a. ToBinding a => a -> Binding
bind Key
V.KRight, Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'l']

-- ----------------------------------------------
--                 ROBOT EVENTS
-- ----------------------------------------------

data RobotEvent
  = MakeEntityEvent
  | ShowZeroInventoryEntitiesEvent
  | CycleInventorySortEvent
  | SwitchInventorySortDirection
  | SearchInventoryEvent
  deriving (RobotEvent -> RobotEvent -> Bool
(RobotEvent -> RobotEvent -> Bool)
-> (RobotEvent -> RobotEvent -> Bool) -> Eq RobotEvent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: RobotEvent -> RobotEvent -> Bool
== :: RobotEvent -> RobotEvent -> Bool
$c/= :: RobotEvent -> RobotEvent -> Bool
/= :: RobotEvent -> RobotEvent -> Bool
Eq, Eq RobotEvent
Eq RobotEvent =>
(RobotEvent -> RobotEvent -> Ordering)
-> (RobotEvent -> RobotEvent -> Bool)
-> (RobotEvent -> RobotEvent -> Bool)
-> (RobotEvent -> RobotEvent -> Bool)
-> (RobotEvent -> RobotEvent -> Bool)
-> (RobotEvent -> RobotEvent -> RobotEvent)
-> (RobotEvent -> RobotEvent -> RobotEvent)
-> Ord RobotEvent
RobotEvent -> RobotEvent -> Bool
RobotEvent -> RobotEvent -> Ordering
RobotEvent -> RobotEvent -> RobotEvent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: RobotEvent -> RobotEvent -> Ordering
compare :: RobotEvent -> RobotEvent -> Ordering
$c< :: RobotEvent -> RobotEvent -> Bool
< :: RobotEvent -> RobotEvent -> Bool
$c<= :: RobotEvent -> RobotEvent -> Bool
<= :: RobotEvent -> RobotEvent -> Bool
$c> :: RobotEvent -> RobotEvent -> Bool
> :: RobotEvent -> RobotEvent -> Bool
$c>= :: RobotEvent -> RobotEvent -> Bool
>= :: RobotEvent -> RobotEvent -> Bool
$cmax :: RobotEvent -> RobotEvent -> RobotEvent
max :: RobotEvent -> RobotEvent -> RobotEvent
$cmin :: RobotEvent -> RobotEvent -> RobotEvent
min :: RobotEvent -> RobotEvent -> RobotEvent
Ord, Int -> RobotEvent -> ShowS
[RobotEvent] -> ShowS
RobotEvent -> String
(Int -> RobotEvent -> ShowS)
-> (RobotEvent -> String)
-> ([RobotEvent] -> ShowS)
-> Show RobotEvent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> RobotEvent -> ShowS
showsPrec :: Int -> RobotEvent -> ShowS
$cshow :: RobotEvent -> String
show :: RobotEvent -> String
$cshowList :: [RobotEvent] -> ShowS
showList :: [RobotEvent] -> ShowS
Show, Int -> RobotEvent
RobotEvent -> Int
RobotEvent -> [RobotEvent]
RobotEvent -> RobotEvent
RobotEvent -> RobotEvent -> [RobotEvent]
RobotEvent -> RobotEvent -> RobotEvent -> [RobotEvent]
(RobotEvent -> RobotEvent)
-> (RobotEvent -> RobotEvent)
-> (Int -> RobotEvent)
-> (RobotEvent -> Int)
-> (RobotEvent -> [RobotEvent])
-> (RobotEvent -> RobotEvent -> [RobotEvent])
-> (RobotEvent -> RobotEvent -> [RobotEvent])
-> (RobotEvent -> RobotEvent -> RobotEvent -> [RobotEvent])
-> Enum RobotEvent
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: RobotEvent -> RobotEvent
succ :: RobotEvent -> RobotEvent
$cpred :: RobotEvent -> RobotEvent
pred :: RobotEvent -> RobotEvent
$ctoEnum :: Int -> RobotEvent
toEnum :: Int -> RobotEvent
$cfromEnum :: RobotEvent -> Int
fromEnum :: RobotEvent -> Int
$cenumFrom :: RobotEvent -> [RobotEvent]
enumFrom :: RobotEvent -> [RobotEvent]
$cenumFromThen :: RobotEvent -> RobotEvent -> [RobotEvent]
enumFromThen :: RobotEvent -> RobotEvent -> [RobotEvent]
$cenumFromTo :: RobotEvent -> RobotEvent -> [RobotEvent]
enumFromTo :: RobotEvent -> RobotEvent -> [RobotEvent]
$cenumFromThenTo :: RobotEvent -> RobotEvent -> RobotEvent -> [RobotEvent]
enumFromThenTo :: RobotEvent -> RobotEvent -> RobotEvent -> [RobotEvent]
Enum, RobotEvent
RobotEvent -> RobotEvent -> Bounded RobotEvent
forall a. a -> a -> Bounded a
$cminBound :: RobotEvent
minBound :: RobotEvent
$cmaxBound :: RobotEvent
maxBound :: RobotEvent
Bounded)

robotPanelEvents :: KeyEvents RobotEvent
robotPanelEvents :: KeyEvents RobotEvent
robotPanelEvents = (RobotEvent -> Text) -> KeyEvents RobotEvent
forall e. (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents ((RobotEvent -> Text) -> KeyEvents RobotEvent)
-> (RobotEvent -> Text) -> KeyEvents RobotEvent
forall a b. (a -> b) -> a -> b
$ \case
  RobotEvent
MakeEntityEvent -> Text
"make entity"
  RobotEvent
ShowZeroInventoryEntitiesEvent -> Text
"show zero inventory entities"
  RobotEvent
CycleInventorySortEvent -> Text
"cycle inventory sort"
  RobotEvent
SwitchInventorySortDirection -> Text
"switch inventory direction"
  RobotEvent
SearchInventoryEvent -> Text
"search inventory"

defaultRobotPanelBindings :: [(RobotEvent, [Binding])]
defaultRobotPanelBindings :: [(RobotEvent, [Binding])]
defaultRobotPanelBindings = (RobotEvent -> [Binding]) -> [(RobotEvent, [Binding])]
forall e.
(Bounded e, Enum e) =>
(e -> [Binding]) -> [(e, [Binding])]
allBindings ((RobotEvent -> [Binding]) -> [(RobotEvent, [Binding])])
-> (RobotEvent -> [Binding]) -> [(RobotEvent, [Binding])]
forall a b. (a -> b) -> a -> b
$ \case
  RobotEvent
MakeEntityEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'm']
  RobotEvent
ShowZeroInventoryEntitiesEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'0']
  RobotEvent
CycleInventorySortEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
';']
  RobotEvent
SwitchInventorySortDirection -> [Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
':']
  RobotEvent
SearchInventoryEvent -> [Char -> Binding
forall a. ToBinding a => a -> Binding
bind Char
'/']

-- ----------------
-- Helper methods

allKeyEvents :: (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents :: forall e. (Ord e, Bounded e, Enum e) => (e -> Text) -> KeyEvents e
allKeyEvents e -> Text
f = [(Text, e)] -> KeyEvents e
forall k. Ord k => [(Text, k)] -> KeyEvents k
keyEvents ([(Text, e)] -> KeyEvents e) -> [(Text, e)] -> KeyEvents e
forall a b. (a -> b) -> a -> b
$ (e -> (Text, e)) -> [e] -> [(Text, e)]
forall a b. (a -> b) -> [a] -> [b]
map (e -> Text
f (e -> Text) -> (e -> e) -> e -> (Text, e)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& e -> e
forall a. a -> a
id) [e]
forall a. (Enum a, Bounded a) => [a]
enumerate

allBindings :: (Bounded e, Enum e) => (e -> [Binding]) -> [(e, [Binding])]
allBindings :: forall e.
(Bounded e, Enum e) =>
(e -> [Binding]) -> [(e, [Binding])]
allBindings e -> [Binding]
f = (e -> (e, [Binding])) -> [e] -> [(e, [Binding])]
forall a b. (a -> b) -> [a] -> [b]
map (\e
e -> (e
e, e -> [Binding]
f e
e)) [e]
forall a. (Enum a, Bounded a) => [a]
enumerate