Copyright | Brent Yorgey |
---|---|
License | BSD-3-Clause |
Maintainer | byorgey@gmail.com |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Application state for the brick
-based Swarm TUI.
Synopsis
- data AppEvent
- data Name
- data ModalType
- data ButtonSelection
- data Modal = Modal {}
- modalType :: Lens' Modal ModalType
- modalDialog :: Lens' Modal (Dialog ButtonSelection)
- data MainMenuEntry
- mainMenu :: MainMenuEntry -> List Name MainMenuEntry
- data Menu
- _NewGameMenu :: Prism' Menu (NonEmpty (List Name ScenarioItem))
- mkScenarioList :: Bool -> ScenarioCollection -> List Name ScenarioItem
- mkNewGameMenu :: Bool -> ScenarioCollection -> FilePath -> Maybe Menu
- data REPLHistItem
- replItemText :: REPLHistItem -> Text
- isREPLEntry :: REPLHistItem -> Bool
- getREPLEntry :: REPLHistItem -> Maybe Text
- data REPLHistory
- replIndex :: Lens' REPLHistory Int
- replLength :: REPLHistory -> Int
- replSeq :: Lens' REPLHistory (Seq REPLHistItem)
- newREPLHistory :: [REPLHistItem] -> REPLHistory
- addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory
- restartREPLHistory :: REPLHistory -> REPLHistory
- getLatestREPLHistoryItems :: Int -> REPLHistory -> [REPLHistItem]
- moveReplHistIndex :: TimeDir -> Text -> REPLHistory -> REPLHistory
- getCurrentItemText :: REPLHistory -> Maybe Text
- replIndexIsAtInput :: REPLHistory -> Bool
- data TimeDir
- data REPLPrompt
- mkCmdPrompt :: Text -> REPLPrompt
- replPromptAsWidget :: REPLPrompt -> Widget Name
- promptTextL :: Lens' REPLPrompt Text
- promptUpdateL :: Lens UIState (Form REPLPrompt AppEvent Name) Text Text
- mkReplForm :: REPLPrompt -> Form REPLPrompt AppEvent Name
- removeEntry :: Text -> REPLHistory -> REPLHistory
- resetWithREPLForm :: Form REPLPrompt AppEvent Name -> UIState -> UIState
- data InventoryListEntry
- _Separator :: Prism' InventoryListEntry Text
- _InventoryEntry :: Prism' InventoryListEntry (Count, Entity)
- _InstalledEntry :: Prism' InventoryListEntry Entity
- data UIState
- uiMenu :: Lens' UIState Menu
- uiPlaying :: Lens' UIState Bool
- uiCheatMode :: Lens' UIState Bool
- uiFocusRing :: Lens' UIState (FocusRing Name)
- uiWorldCursor :: Lens' UIState (Maybe Coords)
- uiReplForm :: Lens' UIState (Form REPLPrompt AppEvent Name)
- uiReplType :: Lens' UIState (Maybe Polytype)
- uiReplHistory :: Lens' UIState REPLHistory
- uiReplLast :: Lens' UIState Text
- uiInventory :: Lens' UIState (Maybe (Int, List Name InventoryListEntry))
- uiMoreInfoTop :: Lens' UIState Bool
- uiMoreInfoBot :: Lens' UIState Bool
- uiScrollToEnd :: Lens' UIState Bool
- uiError :: Lens' UIState (Maybe Text)
- uiModal :: Lens' UIState (Maybe Modal)
- uiGoal :: Lens' UIState (Maybe [Text])
- lgTicksPerSecond :: Lens' UIState Int
- lastFrameTime :: Lens' UIState TimeSpec
- accumulatedTime :: Lens' UIState TimeSpec
- tickCount :: Lens' UIState Int
- frameCount :: Lens' UIState Int
- frameTickCount :: Lens' UIState Int
- lastInfoTime :: Lens' UIState TimeSpec
- uiShowFPS :: Lens' UIState Bool
- uiShowZero :: Lens' UIState Bool
- uiInventoryShouldUpdate :: Lens' UIState Bool
- uiTPF :: Lens' UIState Double
- uiFPS :: Lens' UIState Double
- appData :: Lens' UIState (Map Text Text)
- initFocusRing :: FocusRing Name
- defaultPrompt :: REPLPrompt
- initReplForm :: Form REPLPrompt AppEvent Name
- initLgTicksPerSecond :: Int
- initUIState :: Bool -> Bool -> ExceptT Text IO UIState
- lastEntry :: Text -> REPLHistory -> Maybe Text
- populateInventoryList :: MonadState UIState m => Maybe Robot -> m ()
- infoScroll :: ViewportScroll Name
- modalScroll :: ViewportScroll Name
- data RuntimeState
- webPort :: Lens' RuntimeState (Maybe Port)
- upstreamRelease :: Lens' RuntimeState (Either NewReleaseFailure String)
- eventLog :: Lens' RuntimeState (Notifications LogEntry)
- logEvent :: LogSource -> (Text, RID) -> Text -> Notifications LogEntry -> Notifications LogEntry
- data AppState
- gameState :: Lens' AppState GameState
- uiState :: Lens' AppState UIState
- runtimeState :: Lens' AppState RuntimeState
- data AppOpts = AppOpts {}
- initAppState :: AppOpts -> ExceptT Text IO AppState
- startGame :: (MonadIO m, MonadState AppState m) => Scenario -> ScenarioInfo -> Maybe FilePath -> m ()
- scenarioToAppState :: (MonadIO m, MonadState AppState m) => Scenario -> Maybe Seed -> Maybe String -> m ()
- type Seed = Int
- focusedItem :: AppState -> Maybe InventoryListEntry
- focusedEntity :: AppState -> Maybe Entity
- nextScenario :: Menu -> Maybe (Scenario, ScenarioInfo)
- initRuntimeState :: RuntimeState
Custom UI label types
These types are used as parameters to various brick
types.
Name
represents names to uniquely identify various components
of the UI, such as forms, panels, caches, extents, and lists.
REPLPanel | The panel containing the REPL. |
WorldPanel | The panel containing the world view. |
RobotPanel | The panel showing robot info and inventory on the top left. |
InfoPanel | The info panel on the bottom left. |
REPLInput | The REPL input form. |
WorldCache | The render cache for the world view. |
WorldExtent | The cached extent for the world view. |
InventoryList | The list of inventory items for the currently focused robot. |
InventoryListItem Int | The inventory item position in the InventoryList. |
MenuList | The list of main menu choices. |
ScenarioList | The list of scenario choices. |
InfoViewport | The scrollable viewport for the info panel. |
ModalViewport | The scrollable viewport for any modal dialog. |
Menus and dialogs
data MainMenuEntry Source #
Instances
_NewGameMenu :: Prism' Menu (NonEmpty (List Name ScenarioItem)) Source #
mkScenarioList :: Bool -> ScenarioCollection -> List Name ScenarioItem Source #
Create a brick List
of scenario items from a ScenarioCollection
.
mkNewGameMenu :: Bool -> ScenarioCollection -> FilePath -> Maybe Menu Source #
Given a ScenarioCollection
and a FilePath
which is the canonical
path to some folder or scenario, construct a NewGameMenu
stack
focused on the given item, if possible.
UI state
REPL
data REPLHistItem Source #
An item in the REPL history.
REPLEntry Text | Something entered by the user. |
REPLOutput Text | A response printed by the system. |
Instances
Read REPLHistItem Source # | |
Defined in Swarm.TUI.Model readsPrec :: Int -> ReadS REPLHistItem # readList :: ReadS [REPLHistItem] # | |
Show REPLHistItem Source # | |
Defined in Swarm.TUI.Model showsPrec :: Int -> REPLHistItem -> ShowS # show :: REPLHistItem -> String # showList :: [REPLHistItem] -> ShowS # | |
Eq REPLHistItem Source # | |
Defined in Swarm.TUI.Model (==) :: REPLHistItem -> REPLHistItem -> Bool # (/=) :: REPLHistItem -> REPLHistItem -> Bool # | |
Ord REPLHistItem Source # | |
Defined in Swarm.TUI.Model compare :: REPLHistItem -> REPLHistItem -> Ordering # (<) :: REPLHistItem -> REPLHistItem -> Bool # (<=) :: REPLHistItem -> REPLHistItem -> Bool # (>) :: REPLHistItem -> REPLHistItem -> Bool # (>=) :: REPLHistItem -> REPLHistItem -> Bool # max :: REPLHistItem -> REPLHistItem -> REPLHistItem # min :: REPLHistItem -> REPLHistItem -> REPLHistItem # |
replItemText :: REPLHistItem -> Text Source #
Get the text of REPL input/output.
isREPLEntry :: REPLHistItem -> Bool Source #
Useful helper function to filter out REPL output.
getREPLEntry :: REPLHistItem -> Maybe Text Source #
Useful helper function to only get user input text.
data REPLHistory Source #
History of the REPL with indices (0 is first entry) to the current line and to the first entry since loading saved history. We also (ab)use the length of the REPL as the index of current input line, since that number is one past the index of last entry.
replIndex :: Lens' REPLHistory Int Source #
The current index in the REPL history (if the user is going back through the history using up/down keys).
replLength :: REPLHistory -> Int Source #
Current number lines of the REPL history - (ab)used as index of input buffer.
replSeq :: Lens' REPLHistory (Seq REPLHistItem) Source #
Sequence of REPL inputs and outputs, oldest entry is leftmost.
newREPLHistory :: [REPLHistItem] -> REPLHistory Source #
Create new REPL history (i.e. from loaded history file lines).
addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory Source #
Add new REPL input - the index must have been pointing one past the last element already, so we increment it to keep it that way.
restartREPLHistory :: REPLHistory -> REPLHistory Source #
Point the start of REPL history after current last line. See replStart
.
getLatestREPLHistoryItems :: Int -> REPLHistory -> [REPLHistItem] Source #
Get the latest N items in history, starting with the oldest one.
This is used to show previous REPL lines in UI, so we need the items sorted in the order they were entered and will be drawn top to bottom.
moveReplHistIndex :: TimeDir -> Text -> REPLHistory -> REPLHistory Source #
replIndexIsAtInput :: REPLHistory -> Bool Source #
Prompt utils
data REPLPrompt Source #
This data type represent what is prompted to the player and how the REPL show interpret the user input.
CmdPrompt Text [Text] | Interpret the given text as a regular command. The list is for potential completions, which we can cycle through by hitting Tab repeatedly |
SearchPrompt Text REPLHistory | Interpret the given text as "search this text in history" |
mkCmdPrompt :: Text -> REPLPrompt Source #
replPromptAsWidget :: REPLPrompt -> Widget Name Source #
Turn the repl prompt into a decorator for the form
promptTextL :: Lens' REPLPrompt Text Source #
Lens for accesing the text of the prompt. Notice that setting the text clears any pending completions.
promptUpdateL :: Lens UIState (Form REPLPrompt AppEvent Name) Text Text Source #
Lens for accesing the text of the prompt. Notice that setting the text clears any pending completions.
mkReplForm :: REPLPrompt -> Form REPLPrompt AppEvent Name Source #
Creates the repl form as a decorated form.
removeEntry :: Text -> REPLHistory -> REPLHistory Source #
Given some text, removes the REPLEntry within REPLHistory which is equal to that. This is used when the user enters in search mode and want to traverse the history. If a command has been used many times, the history will be populated with it causing the effect that search command always finds the same command.
resetWithREPLForm :: Form REPLPrompt AppEvent Name -> UIState -> UIState Source #
Set the REPLForm to the given value, resetting type error checks to Nothing and removing uiError.
Inventory
data InventoryListEntry Source #
An entry in the inventory list displayed in the info panel. We can either have an entity with a count in the robot's inventory, an entity installed on the robot, or a labelled separator. The purpose of the separators is to show a clear distinction between the robot's inventory and its installed devices.
Instances
Eq InventoryListEntry Source # | |
Defined in Swarm.TUI.Model (==) :: InventoryListEntry -> InventoryListEntry -> Bool # (/=) :: InventoryListEntry -> InventoryListEntry -> Bool # |
UI Model
The main record holding the UI state. For access to the fields, see the lenses below.
uiPlaying :: Lens' UIState Bool Source #
Are we currently playing the game? True = we are playing, and should thus display a world, REPL, etc.; False = we should display the current menu.
uiCheatMode :: Lens' UIState Bool Source #
Cheat mode, i.e. are we allowed to turn creative mode on and off?
uiFocusRing :: Lens' UIState (FocusRing Name) Source #
The focus ring is the set of UI panels we can cycle among using the Tab key.
uiReplForm :: Lens' UIState (Form REPLPrompt AppEvent Name) Source #
The form where the user can type input at the REPL.
uiReplType :: Lens' UIState (Maybe Polytype) Source #
The type of the current REPL input which should be displayed to the user (if any).
uiReplHistory :: Lens' UIState REPLHistory Source #
History of things the user has typed at the REPL, interleaved with outputs the system has generated.
uiReplLast :: Lens' UIState Text Source #
The last thing the user has typed which isn't part of the history. This is used to restore the repl form after the user visited the history.
uiInventory :: Lens' UIState (Maybe (Int, List Name InventoryListEntry)) Source #
The hash value of the focused robot entity (so we can tell if its inventory changed) along with a list of the items in the focused robot's inventory.
uiMoreInfoTop :: Lens' UIState Bool Source #
Does the info panel contain more content past the top of the panel?
uiMoreInfoBot :: Lens' UIState Bool Source #
Does the info panel contain more content past the bottom of the panel?
uiScrollToEnd :: Lens' UIState Bool Source #
A flag telling the UI to scroll the info panel to the very end (used when a new log message is appended).
uiError :: Lens' UIState (Maybe Text) Source #
When this is Just
, it represents a popup box containing an
error message that is shown on top of the rest of the UI.
uiModal :: Lens' UIState (Maybe Modal) Source #
When this is Just
, it represents a modal to be displayed on
top of the UI, e.g. for the Help screen.
uiGoal :: Lens' UIState (Maybe [Text]) Source #
Status of the scenario goal: whether there is one, and whether it has been displayed to the user initially.
lgTicksPerSecond :: Lens' UIState Int Source #
The base-2 logarithm of the current game speed in ticks/second. Note that we cap this value to the range of +/- log2 INTMAX.
accumulatedTime :: Lens' UIState TimeSpec Source #
The amount of accumulated real time. Every time we get a Frame
event, we accumulate the amount of real time that happened since
the last frame, then attempt to take an appropriate number of
ticks to "catch up", based on the target tick rate.
tickCount :: Lens' UIState Int Source #
A counter used to track how many ticks have happened since the last time we updated the ticks/frame statistics.
frameCount :: Lens' UIState Int Source #
A counter used to track how many frames have been rendered since the last time we updated the ticks/frame statistics.
frameTickCount :: Lens' UIState Int Source #
A counter used to track how many ticks have happened in the current frame, so we can stop when we get to the tick cap.
uiShowZero :: Lens' UIState Bool Source #
A toggle to show or hide inventory items with count 0 by pressing `0`
appData :: Lens' UIState (Map Text Text) Source #
Free-form data loaded from the data
directory, for things like
the logo, about page, tutorial story, etc.
Initialization
initFocusRing :: FocusRing Name Source #
The initial state of the focus ring.
initReplForm :: Form REPLPrompt AppEvent Name Source #
The initial state of the REPL entry form.
initLgTicksPerSecond :: Int Source #
The initial tick speed.
initUIState :: Bool -> Bool -> ExceptT Text IO UIState Source #
Initialize the UI state. This needs to be in the IO monad since
it involves reading a REPL history file, getting the current
time, and loading text files from the data directory. The Bool
parameter indicates whether we should start off by showing the
main menu.
lastEntry :: Text -> REPLHistory -> Maybe Text Source #
Get the last REPLEntry in REPLHistory matching the given text
Updating
populateInventoryList :: MonadState UIState m => Maybe Robot -> m () Source #
Given the focused robot, populate the UI inventory list in the info panel with information about its inventory.
Runtime state
data RuntimeState Source #
webPort :: Lens' RuntimeState (Maybe Port) Source #
The port on which the HTTP debug service is running.
upstreamRelease :: Lens' RuntimeState (Either NewReleaseFailure String) Source #
The upstream release version.
eventLog :: Lens' RuntimeState (Notifications LogEntry) Source #
A log of runtime events.
This logging is separate from the logging done during game-play. If some error happens before a game is even selected, this is the place to log it.
logEvent :: LogSource -> (Text, RID) -> Text -> Notifications LogEntry -> Notifications LogEntry Source #
Simply log to the runtime event log.
App state
The AppState
just stores together the other states.
This is so you can use a smaller state when e.g. writing some game logic or updating the UI. Also consider that GameState can change when loading a new scenario - if the state should persist games, use RuntimeState.
runtimeState :: Lens' AppState RuntimeState Source #
The RuntimeState
record
Initialization
Command-line options for configuring the app.
startGame :: (MonadIO m, MonadState AppState m) => Scenario -> ScenarioInfo -> Maybe FilePath -> m () Source #
Load a Scenario
and start playing the game.
scenarioToAppState :: (MonadIO m, MonadState AppState m) => Scenario -> Maybe Seed -> Maybe String -> m () Source #
Modify the AppState
appropriately when starting a new scenario.
Utility
focusedItem :: AppState -> Maybe InventoryListEntry Source #
Get the currently focused InventoryListEntry
from the robot
info panel (if any).
focusedEntity :: AppState -> Maybe Entity Source #
Get the currently focused entity from the robot info panel (if
any). This is just like focusedItem
but forgets the
distinction between plain inventory items and installed devices.
nextScenario :: Menu -> Maybe (Scenario, ScenarioInfo) Source #
Extract the scenario which would come next in the menu from the
currently selected scenario (if any). Can return Nothing
if
either we are not in the NewGameMenu
, or the current scenario
is the last among its siblings.