module Yi.Keymap.Vim2.StateUtils ( switchMode , switchModeE , resetCount , resetCountE , setCountE , modifyStateE , getMaybeCountE , getCountE , accumulateEventE , accumulateBindingEventE , accumulateTextObjectEventE , flushAccumulatorIntoRepeatableActionE , dropAccumulatorE , dropBindingAccumulatorE , dropTextObjectAccumulatorE , setRegisterE , getRegisterE , normalizeCountE , setStickyEolE , maybeMult , updateModeIndicatorE , saveInsertEventStringE ) where import Yi.Prelude import Prelude () import qualified Data.HashMap.Strict as HM import Data.Maybe (fromMaybe) import qualified Data.Rope as R import Yi.Buffer.Normal import Yi.Editor import Yi.Event import Yi.Keymap.Vim2.Common import Yi.Keymap.Vim2.EventUtils import Yi.Style (defaultStyle) switchMode :: VimMode -> VimState -> VimState switchMode mode state = state { vsMode = mode } switchModeE :: VimMode -> EditorM () switchModeE mode = modifyStateE $ switchMode mode modifyStateE :: (VimState -> VimState) -> EditorM () modifyStateE f = do currentState <- getDynamic setDynamic $ f currentState resetCount :: VimState -> VimState resetCount s = s { vsCount = Nothing } resetCountE :: EditorM () resetCountE = modifyStateE resetCount getMaybeCountE :: EditorM (Maybe Int) getMaybeCountE = fmap vsCount getDynamic getCountE :: EditorM Int getCountE = do currentState <- getDynamic return $! fromMaybe 1 (vsCount currentState) setCountE :: Int -> EditorM () setCountE n = modifyStateE $ \s -> s { vsCount = Just n } accumulateBindingEventE :: Event -> EditorM () accumulateBindingEventE e = modifyStateE $ \s -> s { vsBindingAccumulator = vsBindingAccumulator s ++ eventToString e } accumulateEventE :: Event -> EditorM () accumulateEventE e = modifyStateE $ \s -> s { vsAccumulator = vsAccumulator s ++ eventToString e } accumulateTextObjectEventE :: EventString -> EditorM () accumulateTextObjectEventE evs = modifyStateE $ \s -> s { vsTextObjectAccumulator = vsTextObjectAccumulator s ++ evs } flushAccumulatorIntoRepeatableActionE :: EditorM () flushAccumulatorIntoRepeatableActionE = do currentState <- getDynamic let repeatableAction = stringToRepeatableAction $ vsAccumulator currentState modifyStateE $ \s -> s { vsRepeatableAction = Just repeatableAction , vsAccumulator = [] } dropAccumulatorE :: EditorM () dropAccumulatorE = modifyStateE $ \s -> s { vsAccumulator = [] } dropBindingAccumulatorE :: EditorM () dropBindingAccumulatorE = modifyStateE $ \s -> s { vsBindingAccumulator = [] } dropTextObjectAccumulatorE :: EditorM () dropTextObjectAccumulatorE = modifyStateE $ \s -> s { vsTextObjectAccumulator = [] } getRegisterE :: RegisterName -> EditorM (Maybe Register) getRegisterE name = fmap (HM.lookup name . vsRegisterMap) getDynamic setRegisterE :: RegisterName -> RegionStyle -> R.Rope -> EditorM () setRegisterE name style rope = do rmap <- fmap vsRegisterMap getDynamic let rmap' = HM.insert name (Register style rope) rmap modifyStateE $ \state -> state { vsRegisterMap = rmap' } normalizeCountE :: Maybe Int -> EditorM () normalizeCountE n = do mcount <- getMaybeCountE modifyStateE $ \s -> s { vsCount = maybeMult mcount n , vsAccumulator = show (fromMaybe 1 (maybeMult mcount n)) ++ snd (splitCountedCommand (normalizeCount (vsAccumulator s))) } maybeMult :: Num a => Maybe a -> Maybe a -> Maybe a maybeMult (Just a) (Just b) = Just (a * b) maybeMult Nothing Nothing = Nothing maybeMult a Nothing = a maybeMult Nothing b = b setStickyEolE :: Bool -> EditorM () setStickyEolE b = modifyStateE $ \s -> s { vsStickyEol = b } updateModeIndicatorE :: VimMode -> EditorM () updateModeIndicatorE prevMode = do currentState <- getDynamic let mode = vsMode currentState paste = vsPaste currentState when (mode /= prevMode) $ do let modeName = case mode of Insert _ -> "INSERT" ++ if paste then " (paste) " else "" InsertNormal -> "(insert)" InsertVisual -> "(insert) VISUAL" Replace -> "REPLACE" Visual Block -> "VISUAL BLOCK" Visual LineWise -> "VISUAL LINE" Visual _ -> "VISUAL" _ -> "" decoratedModeName = if null modeName then "" else "-- " ++ modeName ++ " --" setStatus ([decoratedModeName], defaultStyle) saveInsertEventStringE :: EventString -> EditorM () saveInsertEventStringE evs = modifyStateE $ \s -> s { vsOngoingInsertEvents = vsOngoingInsertEvents s ++ evs }