ansido-1.0.0: src/Ansido/App/Command.hs
-- | Mapping from key presses to commands.
--
-- Command resolution is pure. Actions that need text input are started by
-- the runner, which owns the line input and the persistence edge.
module Ansido.App.Command
( Key (..)
, Command (..)
, commandForKey
) where
--------------------------------------------------------------------------------
import Data.Char (digitToInt, isDigit, toLower)
import Ansido.App.State (Direction (..), Screen (..))
-- | A decoded terminal key, with arrows and Delete separated from sequences.
data Key
= KeyCharacter Char
| KeyUp
| KeyDown
| KeyLeft
| KeyRight
| KeyDelete
| KeyEnter
| KeyBackspace
| KeyEscape
deriving (Eq, Show)
-- | High level commands produced by the keyboard.
data Command
= QuitCommand
| RedrawCommand
| HelpCommand
| BackCommand
| CategoriesCommand
| DetailsCommand
| EditTaskCommand
| AddTaskCommand
| AddCategoryCommand
| EditCategoryCommand
| DeleteCategoryCommand
| CycleFilterCommand
| CycleSortCommand
| CycleCommand
| DeleteCommand
| MoveRowCommand Direction
| MoveCategoryCommand Direction
| OpenBoardCommand
| SelectCategoryCommand Int
deriving (Eq, Show)
-- | Resolves a key for the current screen.
commandForKey :: Screen -> Key -> Maybe Command
commandForKey screen key =
case key of
KeyEscape -> Just BackCommand
KeyBackspace -> Just BackCommand
KeyUp -> directionCommand screen Previous
KeyDown -> directionCommand screen Next
KeyLeft -> Nothing
KeyRight -> Nothing
KeyDelete -> deleteCommand screen
KeyEnter -> enterCommand screen
KeyCharacter char -> characterCommand screen char
directionCommand :: Screen -> Direction -> Maybe Command
directionCommand screen direction =
case screen of
BoardScreen -> Just (MoveRowCommand direction)
CategoryScreen -> Just (MoveCategoryCommand direction)
_ -> Nothing
enterCommand :: Screen -> Maybe Command
enterCommand screen =
case screen of
BoardScreen -> Just AddTaskCommand
CategoryScreen -> Just OpenBoardCommand
_ -> Nothing
deleteCommand :: Screen -> Maybe Command
deleteCommand screen =
case screen of
BoardScreen -> Just DeleteCommand
DetailsScreen _ -> Just DeleteCommand
CategoryScreen -> Just DeleteCategoryCommand
_ -> Nothing
characterCommand :: Screen -> Char -> Maybe Command
characterCommand screen key =
case key of
'x' -> Just QuitCommand
'X' -> Just QuitCommand
'r' -> Just RedrawCommand
'R' -> Just RedrawCommand
_ ->
case screen of
BoardScreen -> boardCommand (toLower key)
DetailsScreen _ -> detailsCommand (toLower key)
EditTaskScreen _ -> Nothing
HelpScreen -> helpCommand (toLower key)
CategoryScreen -> categoryCommand key
AddTaskScreen -> Nothing
AddCategoryScreen -> Nothing
EditCategoryScreen _ -> Nothing
boardCommand :: Char -> Maybe Command
boardCommand key =
case key of
' ' -> Just CycleCommand
'e' -> Just EditTaskCommand
'f' -> Just CycleFilterCommand
'o' -> Just CycleSortCommand
'v' -> Just DetailsCommand
'w' -> Just (MoveRowCommand Previous)
's' -> Just (MoveRowCommand Next)
'k' -> Just (MoveRowCommand Previous)
'j' -> Just (MoveRowCommand Next)
'?' -> Just HelpCommand
_ -> Nothing
detailsCommand :: Char -> Maybe Command
detailsCommand key =
case key of
' ' -> Just CycleCommand
'e' -> Just EditTaskCommand
'v' -> Just BackCommand
'?' -> Just HelpCommand
_ -> Nothing
helpCommand :: Char -> Maybe Command
helpCommand key =
case key of
'?' -> Just BackCommand
_ -> Nothing
categoryCommand :: Char -> Maybe Command
categoryCommand key
| isDigit key && key /= '0' =
Just (SelectCategoryCommand (digitToInt key))
| otherwise =
case toLower key of
'n' -> Just AddCategoryCommand
'e' -> Just EditCategoryCommand
'j' -> Just (MoveCategoryCommand Next)
'k' -> Just (MoveCategoryCommand Previous)
'w' -> Just (MoveCategoryCommand Previous)
's' -> Just (MoveCategoryCommand Next)
'?' -> Just HelpCommand
_ -> Nothing