{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Yi.Keymap.Vim.StateUtils
( switchMode
, switchModeE
, resetCount
, resetCountE
, setCountE
, modifyStateE
, getMaybeCountE
, getCountE
, accumulateEventE
, accumulateBindingEventE
, accumulateTextObjectEventE
, flushAccumulatorE
, dropAccumulatorE
, dropBindingAccumulatorE
, dropTextObjectAccumulatorE
, setRegisterE
, getRegisterE
, normalizeCountE
, maybeMult
, updateModeIndicatorE
, saveInsertEventStringE
, resetActiveRegisterE
, saveSubstitutionE
, loadSubstitutionE
) where
import Control.Monad (when)
import qualified Data.HashMap.Strict as HM (insert, lookup)
import Data.Maybe (fromMaybe, isJust)
import Data.Monoid ((<>))
import qualified Data.Text as T (null)
import Yi.Buffer.Normal (RegionStyle (Block, LineWise))
import Yi.Editor (EditorM, getEditorDyn, putEditorDyn, setStatus)
import Yi.Event (Event)
import Yi.Keymap.Vim.Common
import Yi.Keymap.Vim.EventUtils
import Yi.Rope (YiString)
import Yi.String (showT)
import Yi.Style (defaultStyle)
switchMode :: VimMode -> VimState -> VimState
switchMode :: VimMode -> VimState -> VimState
switchMode VimMode
mode VimState
state = VimState
state { vsMode :: VimMode
vsMode = VimMode
mode }
switchModeE :: VimMode -> EditorM ()
switchModeE :: VimMode -> EditorM ()
switchModeE VimMode
mode = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimMode -> VimState -> VimState
switchMode VimMode
mode
modifyStateE :: (VimState -> VimState) -> EditorM ()
modifyStateE :: (VimState -> VimState) -> EditorM ()
modifyStateE VimState -> VimState
f = do
VimState
currentState <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
VimState -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (VimState -> EditorM ()) -> VimState -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimState -> VimState
f VimState
currentState
resetCount :: VimState -> VimState
resetCount :: VimState -> VimState
resetCount VimState
s = VimState
s { vsCount :: Maybe Int
vsCount = Maybe Int
forall a. Maybe a
Nothing }
resetCountE :: EditorM ()
resetCountE :: EditorM ()
resetCountE = (VimState -> VimState) -> EditorM ()
modifyStateE VimState -> VimState
resetCount
getMaybeCountE :: EditorM (Maybe Int)
getMaybeCountE :: EditorM (Maybe Int)
getMaybeCountE = (VimState -> Maybe Int) -> EditorM VimState -> EditorM (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimState -> Maybe Int
vsCount EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
getCountE :: EditorM Int
getCountE :: EditorM Int
getCountE = do
VimState
currentState <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
Int -> EditorM Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> EditorM Int) -> Int -> EditorM Int
forall a b. (a -> b) -> a -> b
$! Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (VimState -> Maybe Int
vsCount VimState
currentState)
setCountE :: Int -> EditorM ()
setCountE :: Int -> EditorM ()
setCountE Int
n = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsCount :: Maybe Int
vsCount = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
n }
accumulateBindingEventE :: Event -> EditorM ()
accumulateBindingEventE :: Event -> EditorM ()
accumulateBindingEventE Event
e = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$
\VimState
s -> VimState
s { vsBindingAccumulator :: EventString
vsBindingAccumulator = VimState -> EventString
vsBindingAccumulator VimState
s EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> Event -> EventString
eventToEventString Event
e }
accumulateEventE :: Event -> EditorM ()
accumulateEventE :: Event -> EditorM ()
accumulateEventE Event
e = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$
\VimState
s -> VimState
s { vsAccumulator :: EventString
vsAccumulator = VimState -> EventString
vsAccumulator VimState
s EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> Event -> EventString
eventToEventString Event
e }
accumulateTextObjectEventE :: EventString -> EditorM ()
accumulateTextObjectEventE :: EventString -> EditorM ()
accumulateTextObjectEventE EventString
evs = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$
\VimState
s -> VimState
s { vsTextObjectAccumulator :: EventString
vsTextObjectAccumulator = VimState -> EventString
vsTextObjectAccumulator VimState
s EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> EventString
evs }
flushAccumulatorE :: EditorM ()
flushAccumulatorE :: EditorM ()
flushAccumulatorE = do
EventString
accum <- VimState -> EventString
vsAccumulator (VimState -> EventString)
-> EditorM VimState -> EditorM EventString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
let repeatableAction :: RepeatableAction
repeatableAction = EventString -> RepeatableAction
stringToRepeatableAction EventString
accum
EventString
accum EventString -> EditorM () -> EditorM ()
`seq` (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s ->
VimState
s { vsRepeatableAction :: Maybe RepeatableAction
vsRepeatableAction = RepeatableAction -> Maybe RepeatableAction
forall a. a -> Maybe a
Just RepeatableAction
repeatableAction
, vsAccumulator :: EventString
vsAccumulator = EventString
forall a. Monoid a => a
mempty
, vsCurrentMacroRecording :: Maybe (MacroName, EventString)
vsCurrentMacroRecording = ((MacroName, EventString) -> (MacroName, EventString))
-> Maybe (MacroName, EventString) -> Maybe (MacroName, EventString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((EventString -> EventString)
-> (MacroName, EventString) -> (MacroName, EventString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> EventString
accum))
(VimState -> Maybe (MacroName, EventString)
vsCurrentMacroRecording VimState
s)
}
dropAccumulatorE :: EditorM ()
dropAccumulatorE :: EditorM ()
dropAccumulatorE =
(VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s ->
let accum :: EventString
accum = VimState -> EventString
vsAccumulator VimState
s
in VimState
s { vsAccumulator :: EventString
vsAccumulator = EventString
forall a. Monoid a => a
mempty
, vsCurrentMacroRecording :: Maybe (MacroName, EventString)
vsCurrentMacroRecording = ((MacroName, EventString) -> (MacroName, EventString))
-> Maybe (MacroName, EventString) -> Maybe (MacroName, EventString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((EventString -> EventString)
-> (MacroName, EventString) -> (MacroName, EventString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> EventString
accum))
(VimState -> Maybe (MacroName, EventString)
vsCurrentMacroRecording VimState
s)
}
dropBindingAccumulatorE :: EditorM ()
dropBindingAccumulatorE :: EditorM ()
dropBindingAccumulatorE =
(VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsBindingAccumulator :: EventString
vsBindingAccumulator = EventString
forall a. Monoid a => a
mempty }
dropTextObjectAccumulatorE :: EditorM ()
dropTextObjectAccumulatorE :: EditorM ()
dropTextObjectAccumulatorE =
(VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsTextObjectAccumulator :: EventString
vsTextObjectAccumulator = EventString
forall a. Monoid a => a
mempty }
getRegisterE :: RegisterName -> EditorM (Maybe Register)
getRegisterE :: MacroName -> EditorM (Maybe Register)
getRegisterE MacroName
name = (VimState -> Maybe Register)
-> EditorM VimState -> EditorM (Maybe Register)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (MacroName -> HashMap MacroName Register -> Maybe Register
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HM.lookup MacroName
name (HashMap MacroName Register -> Maybe Register)
-> (VimState -> HashMap MacroName Register)
-> VimState
-> Maybe Register
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VimState -> HashMap MacroName Register
vsRegisterMap) EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
setRegisterE :: RegisterName -> RegionStyle -> YiString -> EditorM ()
setRegisterE :: MacroName -> RegionStyle -> YiString -> EditorM ()
setRegisterE MacroName
name RegionStyle
style YiString
rope = do
HashMap MacroName Register
rmap <- (VimState -> HashMap MacroName Register)
-> EditorM VimState -> EditorM (HashMap MacroName Register)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimState -> HashMap MacroName Register
vsRegisterMap EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
let rmap' :: HashMap MacroName Register
rmap' = MacroName
-> Register
-> HashMap MacroName Register
-> HashMap MacroName Register
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
HM.insert MacroName
name (RegionStyle -> YiString -> Register
Register RegionStyle
style YiString
rope) HashMap MacroName Register
rmap
(VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
state -> VimState
state { vsRegisterMap :: HashMap MacroName Register
vsRegisterMap = HashMap MacroName Register
rmap' }
normalizeCountE :: Maybe Int -> EditorM ()
normalizeCountE :: Maybe Int -> EditorM ()
normalizeCountE Maybe Int
n = do
Maybe Int
mcount <- EditorM (Maybe Int)
getMaybeCountE
(VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s {
vsCount :: Maybe Int
vsCount = Maybe Int -> Maybe Int -> Maybe Int
forall a. Num a => Maybe a -> Maybe a -> Maybe a
maybeMult Maybe Int
mcount Maybe Int
n
, vsAccumulator :: EventString
vsAccumulator = Text -> EventString
Ev (Int -> Text
forall a. Show a => a -> Text
showT (Int -> Text) -> (Maybe Int -> Int) -> Maybe Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1 (Maybe Int -> Text) -> Maybe Int -> Text
forall a b. (a -> b) -> a -> b
$ Maybe Int -> Maybe Int -> Maybe Int
forall a. Num a => Maybe a -> Maybe a -> Maybe a
maybeMult Maybe Int
mcount Maybe Int
n)
EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> (Int, EventString) -> EventString
forall a b. (a, b) -> b
snd (EventString -> (Int, EventString)
splitCountedCommand (EventString -> (Int, EventString))
-> (EventString -> EventString)
-> EventString
-> (Int, EventString)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> EventString
normalizeCount (EventString -> (Int, EventString))
-> EventString -> (Int, EventString)
forall a b. (a -> b) -> a -> b
$ VimState -> EventString
vsAccumulator VimState
s)
}
maybeMult :: Num a => Maybe a -> Maybe a -> Maybe a
maybeMult :: Maybe a -> Maybe a -> Maybe a
maybeMult (Just a
a) (Just a
b) = a -> Maybe a
forall a. a -> Maybe a
Just (a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
b)
maybeMult Maybe a
Nothing Maybe a
Nothing = Maybe a
forall a. Maybe a
Nothing
maybeMult Maybe a
a Maybe a
Nothing = Maybe a
a
maybeMult Maybe a
Nothing Maybe a
b = Maybe a
b
updateModeIndicatorE :: VimState -> EditorM ()
updateModeIndicatorE :: VimState -> EditorM ()
updateModeIndicatorE VimState
prevState = do
VimState
currentState <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
let mode :: VimMode
mode = VimState -> VimMode
vsMode VimState
currentState
prevMode :: VimMode
prevMode = VimState -> VimMode
vsMode VimState
prevState
paste :: Bool
paste = VimState -> Bool
vsPaste VimState
currentState
isRecording :: Bool
isRecording = Maybe (MacroName, EventString) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (MacroName, EventString) -> Bool)
-> (VimState -> Maybe (MacroName, EventString)) -> VimState -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VimState -> Maybe (MacroName, EventString)
vsCurrentMacroRecording (VimState -> Bool) -> VimState -> Bool
forall a b. (a -> b) -> a -> b
$ VimState
currentState
prevRecording :: Bool
prevRecording = Maybe (MacroName, EventString) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (MacroName, EventString) -> Bool)
-> (VimState -> Maybe (MacroName, EventString)) -> VimState -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VimState -> Maybe (MacroName, EventString)
vsCurrentMacroRecording (VimState -> Bool) -> VimState -> Bool
forall a b. (a -> b) -> a -> b
$ VimState
prevState
Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (VimMode
mode VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
/= VimMode
prevMode Bool -> Bool -> Bool
|| Bool
isRecording Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool
prevRecording) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
let modeName :: Text
modeName = case VimMode
mode of
Insert MacroName
_ -> Text
"INSERT" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> if Bool
paste then Text
" (paste) " else Text
""
VimMode
InsertNormal -> Text
"(insert)"
VimMode
InsertVisual -> Text
"(insert) VISUAL"
VimMode
Replace -> Text
"REPLACE"
Visual RegionStyle
Block -> Text
"VISUAL BLOCK"
Visual RegionStyle
LineWise -> Text
"VISUAL LINE"
Visual RegionStyle
_ -> Text
"VISUAL"
VimMode
_ -> Text
""
decoratedModeName' :: Text
decoratedModeName' = if Text -> Bool
T.null Text
modeName
then Text
forall a. Monoid a => a
mempty
else Text
"-- " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
modeName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" --"
decoratedModeName :: Text
decoratedModeName = if Bool
isRecording
then Text
decoratedModeName' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"recording"
else Text
decoratedModeName'
Status -> EditorM ()
forall (m :: * -> *). MonadEditor m => Status -> m ()
setStatus ([Text
decoratedModeName], StyleName
defaultStyle)
saveInsertEventStringE :: EventString -> EditorM ()
saveInsertEventStringE :: EventString -> EditorM ()
saveInsertEventStringE EventString
evs = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s ->
VimState
s { vsOngoingInsertEvents :: EventString
vsOngoingInsertEvents = VimState -> EventString
vsOngoingInsertEvents VimState
s EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> EventString
evs }
resetActiveRegisterE :: EditorM ()
resetActiveRegisterE :: EditorM ()
resetActiveRegisterE = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsActiveRegister :: MacroName
vsActiveRegister = MacroName
'\0' }
saveSubstitutionE :: Substitution -> EditorM ()
saveSubstitutionE :: Substitution -> EditorM ()
saveSubstitutionE Substitution
sub = (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsLastSubstitution :: Maybe Substitution
vsLastSubstitution = Substitution -> Maybe Substitution
forall a. a -> Maybe a
Just Substitution
sub }
loadSubstitutionE :: EditorM (Maybe Substitution)
loadSubstitutionE :: EditorM (Maybe Substitution)
loadSubstitutionE = VimState -> Maybe Substitution
vsLastSubstitution (VimState -> Maybe Substitution)
-> EditorM VimState -> EditorM (Maybe Substitution)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn