From 3cc76d881c9999589825a8e89da4c1637a5a6a21 Mon Sep 17 00:00:00 2001 From: Jonathan Lamothe Date: Sat, 24 Aug 2019 16:23:56 -0400 Subject: [PATCH] basic prompting framework --- src/Mtlstats/Actions.hs | 10 ++++++ src/Mtlstats/Prompt.hs | 74 +++++++++++++++++++++++++++++++++++++++++ src/Mtlstats/Types.hs | 15 ++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/Mtlstats/Prompt.hs diff --git a/src/Mtlstats/Actions.hs b/src/Mtlstats/Actions.hs index 89e129b..d66f312 100644 --- a/src/Mtlstats/Actions.hs +++ b/src/Mtlstats/Actions.hs @@ -23,6 +23,8 @@ module Mtlstats.Actions ( startNewSeason , resetYtd , startNewGame + , addChar + , removeChar ) where import Lens.Micro (over, (&), (.~), (?~), (%~)) @@ -44,3 +46,11 @@ startNewGame :: ProgState -> ProgState startNewGame = (progMode .~ NewGame newGameState) . (database . dbGames %~ succ) + +-- | Adds a character to the input buffer +addChar :: Char -> ProgState -> ProgState +addChar = undefined + +-- | Removes a character from the input buffer (if possible) +removeChar :: ProgState -> ProgState +removeChar = undefined diff --git a/src/Mtlstats/Prompt.hs b/src/Mtlstats/Prompt.hs new file mode 100644 index 0000000..5048d09 --- /dev/null +++ b/src/Mtlstats/Prompt.hs @@ -0,0 +1,74 @@ +{- | + +mtlstats +Copyright (C) 2019 Rhéal Lamothe + + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or (at +your option) any later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +-} + +module Mtlstats.Prompt ( + -- * Prompt Functions + drawPrompt, + promptHandler, +) where + +import Control.Monad (when) +import Control.Monad.Trans.State (gets, modify) +import Data.Char (isDigit, toUpper) +import Data.Foldable (forM_) +import Lens.Micro ((^.), (.~), (?~)) +import Lens.Micro.Extras (view) +import Text.Read (readMaybe) +import qualified UI.NCurses as C + +import Mtlstats.Actions +import Mtlstats.Types + +-- | Draws the prompt to the screen +drawPrompt :: Prompt -> ProgState -> C.Update C.CursorMode +drawPrompt p s = do + promptDrawer p s + return C.CursorVisible + +-- | Event handler for a prompt +promptHandler :: Prompt -> C.Event -> Action () +promptHandler p (C.EventCharacter '\n') = do + val <- gets $ view inputBuffer + modify $ inputBuffer .~ "" + promptAction p val +promptHandler p (C.EventCharacter c) = let + c' = toUpper c + in when (promptCharCheck p c') $ + modify $ addChar c' +promptHandler _ (C.EventSpecialKey C.KeyBackspace) = + modify removeChar +promptHandler p (C.EventSpecialKey (C.KeyFunction k)) = + promptFunctionKey p k +promptHandler _ _ = return () + +-- | Builds a numeric prompt +numPrompt + :: String + -- ^ The prompt string + -> (Int -> Action ()) + -- ^ The callback function for the result + -> Prompt +numPrompt pStr act = Prompt + { promptDrawer = \s -> C.drawString $ pStr ++ s ^. inputBuffer + , promptCharCheck = isDigit + , promptAction = \inStr -> forM_ (readMaybe inStr) act + , promptFunctionKey = const $ return () + } diff --git a/src/Mtlstats/Types.hs b/src/Mtlstats/Types.hs index 6aeb018..9dece99 100644 --- a/src/Mtlstats/Types.hs +++ b/src/Mtlstats/Types.hs @@ -33,6 +33,7 @@ module Mtlstats.Types ( PlayerStats (..), Goalie (..), GoalieStats (..), + Prompt (..), -- * Lenses -- ** ProgState Lenses database, @@ -102,7 +103,7 @@ import Data.Aeson ) import Lens.Micro (Lens', lens, (&), (^.), (.~)) import Lens.Micro.TH (makeLenses) -import UI.NCurses (Curses) +import UI.NCurses (Curses, Update) -- | Action which maintains program state type Action a = StateT ProgState Curses a @@ -308,6 +309,18 @@ instance ToJSON GoalieStats where "losses" .= l <> "ties" .= t +-- | Defines a user prompt +data Prompt = Prompt + { promptDrawer :: ProgState -> Update () + -- ^ Draws the prompt to thr screen + , promptCharCheck :: Char -> Bool + -- ^ Determines whether or not the character is valid + , promptAction :: String -> Action () + -- ^ Action to perform when the value is entered + , promptFunctionKey :: Integer -> Action () + -- ^ Action to perform when a function key is pressed + } + makeLenses ''ProgState makeLenses ''GameState makeLenses ''Database