aboutsummaryrefslogtreecommitdiff
path: root/src/Chelleport.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Chelleport.hs')
-rw-r--r--src/Chelleport.hs91
1 files changed, 54 insertions, 37 deletions
diff --git a/src/Chelleport.hs b/src/Chelleport.hs
index 96c9fb6..4b44dd1 100644
--- a/src/Chelleport.hs
+++ b/src/Chelleport.hs
@@ -14,23 +14,18 @@ import Chelleport.Control
)
import Chelleport.Draw (MonadDraw (windowPosition), cellSize)
import Chelleport.KeySequence (findMatchPosition, generateGrid, isKeycodeDigit, isValidKey, keycodeToInt, nextChars, toKeyChar)
+import Chelleport.OCR (MonadOCR, getWordsOnScreen)
import Chelleport.Types
-import Chelleport.Utils (intToCInt)
+import Chelleport.Utils (cIntToInt, intToCInt, isEmpty, isNotEmpty)
import qualified Chelleport.View
import Control.Monad (forM_)
import Control.Monad.IO.Class (MonadIO)
import Control.Monad.Reader (ReaderT (runReaderT))
+import Data.Char (toLower)
+import Data.List (isInfixOf)
import Data.Maybe (fromMaybe, isJust)
import qualified SDL
--- run :: IO ()
--- run = do
--- ctx <- initializeContext
--- benchmark "ocr" $ do
--- res <- (`runReaderT` ctx) . runAppM $ getWordsOnScreen
--- print $ "---" ++ show (length res)
--- pure ()
-
run :: IO ()
run = do
ctx <- initializeContext
@@ -45,19 +40,10 @@ run = do
runAppWithCtx :: (MonadIO m) => DrawContext -> AppM m x -> m x
runAppWithCtx ctx = (`runReaderT` ctx) . runAppM
-initialState :: (Monad m) => m State
+initialState :: (Monad m) => m (State, Maybe AppAction)
initialState = do
let cells = fromMaybe (pure undefined) $ generateGrid 0 (rows, columns) hintKeys
- pure $
- State
- { stateGrid = cells,
- stateKeySequence = [],
- stateIsMatched = False,
- stateIsShiftPressed = False,
- stateIsDragging = False,
- stateRepetition = 1,
- stateMode = ModeSearch
- }
+ pure (defaultAppState {stateGrid = cells}, Just $ SetMode defaultHintsMode)
where
rows = 9
columns = 16
@@ -79,6 +65,12 @@ eventHandler event =
-- 0-9
| isKeycodeDigit (eventToKeycode ev) ->
Just $ UpdateRepetition (fromMaybe 0 $ keycodeToInt $ eventToKeycode ev)
+ -- Enable search mode
+ | withCtrl ev && isKeyPressWith ev SDL.KeycodeS ->
+ Just $ SetMode defaultSearchMode
+ -- Enable hints mode
+ | withCtrl ev && isKeyPressWith ev SDL.KeycodeH ->
+ Just $ SetMode defaultHintsMode
-- Space / Shift+Space
| isKeyPressWith ev SDL.KeycodeSpace ->
if withShift ev
@@ -101,9 +93,18 @@ eventHandler event =
Just $ UpdateShiftState False
_ -> Nothing
-update :: (MonadAppShell m, MonadDraw m, MonadControl m) => State -> AppAction -> m (State, Maybe AppAction)
--- Act on key inputs
-update state (HandleKeyInput key) = do
+update :: (MonadAppShell m, MonadDraw m, MonadControl m, MonadOCR m) => State -> AppAction -> m (State, Maybe AppAction)
+-- Set mode
+update state (SetMode mode) = do
+ case mode of
+ ModeHints -> pure (state {stateMode = mode}, Nothing)
+ ModeSearch {} -> do
+ wordsOnScreen <- getWordsOnScreen
+ let updatedMode = mode {searchWords = wordsOnScreen, searchFilteredWords = wordsOnScreen}
+ pure (state {stateMode = updatedMode}, Nothing)
+
+-- HINTS MODE: Act on key inputs
+update state@(State {stateMode = ModeHints}) (HandleKeyInput key) = do
case (toKeyChar key, validChars) of
(Just keyChar, Just validChars')
| stateIsMatched state && keyChar `elem` ("HJKL" :: String) -> do
@@ -114,35 +115,51 @@ update state (HandleKeyInput key) = do
let newKeySequence = stateKeySequence state ++ [keyChar]
let matchPosition = findMatchPosition newKeySequence $ stateGrid state
let state' = state {stateKeySequence = newKeySequence, stateIsMatched = isJust matchPosition}
- pure (state', MoveMousePosition <$> matchPosition)
+ action <- maybe (pure Nothing) (fmap (Just . MoveMousePosition) . getPosition) matchPosition
+ pure (state', action)
_ -> pure (state, Nothing)
where
validChars = nextChars (stateKeySequence state) (stateGrid state)
+ getPosition (row, col) = do
+ (wcell, hcell) <- cellSize state
+ let x = (wcell `div` 2) + wcell * intToCInt col
+ let y = (hcell `div` 2) + hcell * intToCInt row
+ (winx, winy) <- windowPosition
+ pure (cIntToInt $ winx + x, cIntToInt $ winy + y)
incrementValue = do
(wcell, hcell) <- cellSize state
if stateIsShiftPressed state
then pure (wcell `div` 4, hcell `div` 4)
else pure (wcell `div` 16, hcell `div` 16)
+-- SEARCH MODE: Act on key inputs
+update state@(State {stateMode = ModeSearch {searchWords, searchInputText}}) (HandleKeyInput key) = do
+ case toKeyChar key of
+ Just keyChar -> do
+ let searchText = searchInputText ++ [toLower keyChar]
+ let matches = filterMatches searchText
+ let highlightedWord = if isNotEmpty matches then Just $ head matches else Nothing
+ let updatedMode = (stateMode state) {searchInputText = searchText, searchFilteredWords = matches}
+ pure (state {stateMode = updatedMode}, MoveMousePosition . wordPosition <$> highlightedWord)
+ _ -> do
+ pure (state, Nothing)
+ where
+ wordPosition w = (cIntToInt $ matchStartX w, cIntToInt $ matchStartY w)
+ filterMatches text
+ | isEmpty text = searchWords
+ | otherwise = filter (isInfixOf text . map toLower . matchText) searchWords
+
-- Move mouse incrementally
update state (IncrementMouseCursor (incX, incY)) = do
(curX, curY) <- getMousePointerPosition
- let count = intToCInt $ case stateRepetition state of 0 -> 1; n -> n
- moveMousePointer (curX + count * intToCInt incX) (curY + count * intToCInt incY)
- pure (state {stateRepetition = 1}, Nothing)
+ let count = case stateRepetition state of 0 -> 1; n -> n
+ let pos = (cIntToInt curX + count * incX, cIntToInt curY + count * incY)
+ pure (state {stateRepetition = 1}, Just $ MoveMousePosition pos)
-- Move mouse to given position
-update state (MoveMousePosition (row, col)) = do
- (x, y) <- getPosition
- moveMousePointer x y
+update state (MoveMousePosition (x, y)) = do
+ moveMousePointer (intToCInt x) (intToCInt y)
pure (state, Nothing)
- where
- getPosition = do
- (wcell, hcell) <- cellSize state
- let x = (wcell `div` 2) + wcell * intToCInt col
- let y = (hcell `div` 2) + hcell * intToCInt row
- (winx, winy) <- windowPosition
- pure (winx + x, winy + y)
-- Reset entered key sequence and state
update state ResetKeys = do