    {-# LANGUAGE LambdaCase        #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# OPTIONS_HADDOCK show-extensions #-}

    -- |
    -- Module      :  Yi.Keymap.Vim.NormalMap
    -- License     :  GPL-2
    -- Maintainer  :  yi-devel@googlegroups.com
    -- Stability   :  experimental
    -- Portability :  portable

    module Yi.Keymap.Vim.NormalMap (defNormalMap) where

    import           Prelude                    hiding (lookup)

    import           Lens.Micro.Platform        (use, (.=))
    import           Control.Monad              (replicateM_, unless, void, when)
    import           Data.Char                  (ord)
    import           Data.HashMap.Strict        (lookup, insert)
    import           Data.List                  (group)
    import           Data.Maybe                 (fromMaybe)
    import           Data.Monoid                ((<>))
    import qualified Data.Text                  as T (drop, empty, pack, replicate, unpack)
    import           System.Directory           (doesFileExist)
    import           System.FriendlyPath        (expandTilda)
    import           Yi.Buffer                  hiding (Insert)
    import           Yi.Core                    (closeWindow, quitEditor)
    import           Yi.Editor
    import           Yi.Event                   (Event (Event), Key (KASCII, KEnter, KEsc, KTab), Modifier (MCtrl))
    import           Yi.File                    (fwriteE, openNewFile)
    import           Yi.History                 (historyPrefixSet, historyStart)
    import           Yi.Keymap                  (YiM)
    import           Yi.Keymap.Keys             (char, ctrlCh, spec)
    import           Yi.Keymap.Vim.Common
    import           Yi.Keymap.Vim.Eval         (scheduleActionStringForEval)
    import           Yi.Keymap.Vim.Motion       (CountedMove (CountedMove), regionOfMoveB, stringToMove)
    import           Yi.Keymap.Vim.Operator     (VimOperator (..), opChange, opDelete, opYank)
    import           Yi.Keymap.Vim.Search       (doVimSearch)
    import           Yi.Keymap.Vim.StateUtils
    import           Yi.Keymap.Vim.StyledRegion (StyledRegion (StyledRegion), transformCharactersInLineN)
    import           Yi.Keymap.Vim.Substitution (repeatSubstitutionE, repeatSubstitutionFlaglessE)
    import           Yi.Keymap.Vim.Tag          (gotoTag, popTag)
    import           Yi.Keymap.Vim.Utils
    import           Yi.MiniBuffer              (spawnMinibufferE)
    import           Yi.Misc                    (printFileInfoE)
    import           Yi.Monad                   (maybeM, whenM)
    import           Yi.Regex                   (makeSearchOptsM, seInput)
    import qualified Yi.Rope                    as R (fromText, null, toString, toText)
    import           Yi.Search                  (getRegexE, isearchInitE, makeSimpleSearch, setRegexE)
    import           Yi.String                  (showT)
    import           Yi.Tag                     (Tag (..))
    import           Yi.Utils                   (io)

    data EOLStickiness = Sticky | NonSticky deriving EOLStickiness -> EOLStickiness -> Bool
    (EOLStickiness -> EOLStickiness -> Bool)
    -> (EOLStickiness -> EOLStickiness -> Bool) -> Eq EOLStickiness
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: EOLStickiness -> EOLStickiness -> Bool
    == :: EOLStickiness -> EOLStickiness -> Bool
    $c/= :: EOLStickiness -> EOLStickiness -> Bool
    /= :: EOLStickiness -> EOLStickiness -> Bool
    Eq

    mkDigitBinding :: Char -> VimBinding
    mkDigitBinding :: Char -> VimBinding
    mkDigitBinding Char
    c = VimMode
    -> RepeatToken
    -> (Event, EditorM (), VimState -> VimState)
    -> VimBinding
    mkBindingE VimMode
    Normal RepeatToken
    Continue (Char -> Event
    char Char
    c, () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    mutate)
      where
        mutate :: VimState -> VimState
    mutate vs :: VimState
    vs@(VimState {vsCount :: VimState -> Maybe Int
    vsCount = Maybe Int
    Nothing}) = VimState
    vs { vsCount = Just d }
        mutate vs :: VimState
    vs@(VimState {vsCount :: VimState -> Maybe Int
    vsCount = Just Int
    count}) =
          VimState
    vs { vsCount = Just $ count * 10 + d }
        d :: Int
    d = Char -> Int
    ord Char
    c Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Char -> Int
    ord Char
    '0'

    defNormalMap :: [VimOperator] -> [VimBinding]
    defNormalMap :: [VimOperator] -> [VimBinding]
    defNormalMap [VimOperator]
    operators =
        [VimBinding
    recordMacroBinding, VimBinding
    finishRecordingMacroBinding, VimBinding
    playMacroBinding] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding
    zeroBinding, VimBinding
    repeatBinding, VimBinding
    motionBinding, VimBinding
    searchBinding] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding
    chooseRegisterBinding, VimBinding
    setMarkBinding] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        (Char -> VimBinding) -> String -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> VimBinding
    mkDigitBinding [Char
    '1' .. Char
    '9'] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimOperator] -> [VimBinding]
    operatorBindings [VimOperator]
    operators [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding]
    finishingBingings [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding]
    continuingBindings [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding]
    nonrepeatableBindings [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding]
    jumpBindings [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding]
    fileEditBindings [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding
    tabTraversalBinding] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <>
        [VimBinding
    tagJumpBinding, VimBinding
    tagPopBinding]

    tagJumpBinding :: VimBinding
    tagJumpBinding :: VimBinding
    tagJumpBinding = VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
    mkBindingY VimMode
    Normal (Key -> [Modifier] -> Event
    Event (Char -> Key
    KASCII Char
    ']') [Modifier
    MCtrl], YiM ()
    f, VimState -> VimState
    forall a. a -> a
    id)
       where f :: YiM ()
    f = BufferM YiString -> YiM YiString
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM YiString
    readCurrentWordB YiM YiString -> (YiString -> YiM ()) -> YiM ()
    forall a b. YiM a -> (a -> YiM b) -> YiM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Tag -> YiM ()
    g (Tag -> YiM ()) -> (YiString -> Tag) -> YiString -> YiM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Tag
    Tag (Text -> Tag) -> (YiString -> Text) -> YiString -> Tag
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . YiString -> Text
    R.toText
             g :: Tag -> YiM ()
    g Tag
    tag = Tag -> Int -> Maybe (String, Int, Int) -> YiM ()
    gotoTag Tag
    tag Int
    0 Maybe (String, Int, Int)
    forall a. Maybe a
    Nothing

    tagPopBinding :: VimBinding
    tagPopBinding :: VimBinding
    tagPopBinding = VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
    mkBindingY VimMode
    Normal (Key -> [Modifier] -> Event
    Event (Char -> Key
    KASCII Char
    't') [Modifier
    MCtrl], YiM ()
    f, VimState -> VimState
    forall a. a -> a
    id)
       where f :: YiM ()
    f = YiM ()
    popTag

    motionBinding :: VimBinding
    motionBinding :: VimBinding
    motionBinding = RepeatToken -> (VimMode -> Bool) -> VimBinding
    mkMotionBinding RepeatToken
    Drop ((VimMode -> Bool) -> VimBinding)
    -> (VimMode -> Bool) -> VimBinding
    forall a b. (a -> b) -> a -> b
    $
        \VimMode
    m -> case VimMode
    m of
            VimMode
    Normal -> Bool
    True
            VimMode
    _ -> Bool
    False

    chooseRegisterBinding :: VimBinding
    chooseRegisterBinding :: VimBinding
    chooseRegisterBinding = (VimState -> Bool) -> VimBinding
    mkChooseRegisterBinding ((VimMode -> VimMode -> Bool
    forall a. Eq a => a -> a -> Bool
    == VimMode
    Normal) (VimMode -> Bool) -> (VimState -> VimMode) -> VimState -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimState -> VimMode
    vsMode)

    zeroBinding :: VimBinding
    zeroBinding :: VimBinding
    zeroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
    forall {a}.
    (IsString a, Eq a) =>
    a -> VimState -> MatchResult (EditorM RepeatToken)
    f
        where f :: a -> VimState -> MatchResult (EditorM RepeatToken)
    f a
    "0" (VimState {vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal}) = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                  currentState <- EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
                  case vsCount currentState of
                      Just Int
    c -> do
                          Int -> EditorM ()
    setCountE (Int
    10 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    c)
                          RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Continue
                      Maybe Int
    Nothing -> do
                          BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    moveToSol
                          EditorM ()
    resetCountE
                          BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ (Bool -> Identity Bool) -> FBuffer -> Identity FBuffer
    forall c. HasAttributes c => Lens' c Bool
    Lens' FBuffer Bool
    stickyEolA ((Bool -> Identity Bool) -> FBuffer -> Identity FBuffer)
    -> Bool -> BufferM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= Bool
    False
                          RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Drop
              f a
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    repeatBinding :: VimBinding
    repeatBinding :: VimBinding
    repeatBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    forall {a}.
    (Eq a, IsString a) =>
    a -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
      where
        f :: a -> VimState -> MatchResult (EditorM RepeatToken)
    f a
    "." (VimState {vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal}) = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
          currentState <- EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
          case vsRepeatableAction currentState of
              Maybe RepeatableAction
    Nothing -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
              Just (RepeatableAction Int
    prevCount (Ev Text
    actionString)) -> do
                  let count :: Text
    count = Int -> Text
    forall a. Show a => a -> Text
    showT (Int -> Text) -> Int -> Text
    forall a b. (a -> b) -> a -> b
    $ Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe Int
    prevCount (VimState -> Maybe Int
    vsCount VimState
    currentState)
                  EventString -> EditorM ()
    scheduleActionStringForEval (EventString -> EditorM ())
    -> (Text -> EventString) -> Text -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> EventString
    Ev (Text -> EditorM ()) -> Text -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ Text
    count Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    actionString
                  EditorM ()
    resetCountE
          return Drop
        f a
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    jumpBindings :: [VimBinding]
    jumpBindings :: [VimBinding]
    jumpBindings = ((Event, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(Event, EditorM (), VimState -> VimState)] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (Event, EditorM (), VimState -> VimState)
    -> VimBinding
    mkBindingE VimMode
    Normal RepeatToken
    Drop)
        [ (Char -> Event
    ctrlCh Char
    'o', EditorM ()
    jumpBackE, VimState -> VimState
    forall a. a -> a
    id)
        , (Key -> Event
    spec Key
    KTab, EditorM ()
    jumpForwardE, VimState -> VimState
    forall a. a -> a
    id)
        , (Char -> Event
    ctrlCh Char
    '^', EditorM ()
    controlCaret, VimState -> VimState
    resetCount)
        , (Char -> Event
    ctrlCh Char
    '6', EditorM ()
    controlCaret, VimState -> VimState
    resetCount)
        ]
      where
        controlCaret :: EditorM ()
    controlCaret = Int -> EditorM ()
    alternateBufferE (Int -> EditorM ()) -> (Int -> Int) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + (-Int
    1)) (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE

    finishingBingings :: [VimBinding]
    finishingBingings :: [VimBinding]
    finishingBingings = ((EventString, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(EventString, EditorM (), VimState -> VimState)]
    -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState)
    -> VimBinding
    mkStringBindingE VimMode
    Normal RepeatToken
    Finish)
        [ (EventString
    "x", Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE Direction
    Forward EOLStickiness
    NonSticky (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE, VimState -> VimState
    resetCount)
        , (EventString
    "<Del>", Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE Direction
    Forward EOLStickiness
    NonSticky (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE, VimState -> VimState
    resetCount)
        , (EventString
    "X", Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE Direction
    Backward EOLStickiness
    NonSticky (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE, VimState -> VimState
    resetCount)

        , (EventString
    "D",
            do region <- BufferM Region -> EditorM Region
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM Region -> EditorM Region)
    -> BufferM Region -> EditorM Region
    forall a b. (a -> b) -> a -> b
    $ BufferM () -> BufferM () -> BufferM Region
    forall a b. BufferM a -> BufferM b -> BufferM Region
    regionWithTwoMovesB (() -> BufferM ()
    forall a. a -> BufferM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) BufferM ()
    moveToEol
               void $ operatorApplyToRegionE opDelete 1 $ StyledRegion Exclusive region
            , VimState -> VimState
    forall a. a -> a
    id)

        -- Pasting
        , (EventString
    "p", EditorM ()
    pasteAfter, VimState -> VimState
    forall a. a -> a
    id)
        , (EventString
    "P", EditorM ()
    pasteBefore, VimState -> VimState
    forall a. a -> a
    id)

        -- Miscellaneous.
        , (EventString
    "~", do
               count <- EditorM Int
    getCountE
               withCurrentBuffer $ do
                   transformCharactersInLineN count switchCaseChar
                   leftOnEol
            , VimState -> VimState
    resetCount)
        , (EventString
    "J", do
            count <- (Int -> Int) -> EditorM Int -> EditorM Int
    forall a b. (a -> b) -> EditorM a -> EditorM b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Int -> Int -> Int) -> Int -> Int -> Int
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (-) Int
    1 (Int -> Int) -> (Int -> Int) -> Int -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    2) EditorM Int
    getCountE
            withCurrentBuffer $ do
                (StyledRegion s r) <- case stringToMove "j" of
                    WholeMatch Move
    m -> CountedMove -> BufferM StyledRegion
    regionOfMoveB (CountedMove -> BufferM StyledRegion)
    -> CountedMove -> BufferM StyledRegion
    forall a b. (a -> b) -> a -> b
    $ Maybe Int -> Move -> CountedMove
    CountedMove (Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    count) Move
    m
                    MatchResult Move
    _ -> String -> BufferM StyledRegion
    forall a. HasCallStack => String -> a
    error String
    "can't happen"
                void $ lineMoveRel $ count - 1
                moveToEol
                joinLinesB =<< convertRegionToStyleB r s
           , VimState -> VimState
    resetCount)
        ]

    pasteBefore :: EditorM ()
    pasteBefore :: EditorM ()
    pasteBefore = do
        -- TODO: use count
        register <- Char -> EditorM (Maybe Register)
    getRegisterE (Char -> EditorM (Maybe Register))
    -> (VimState -> Char) -> VimState -> EditorM (Maybe Register)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimState -> Char
    vsActiveRegister (VimState -> EditorM (Maybe Register))
    -> EditorM VimState -> EditorM (Maybe Register)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
        case register of
            Maybe Register
    Nothing -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            Just (Register RegionStyle
    LineWise YiString
    rope) -> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ Bool -> BufferM () -> BufferM ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (YiString -> Bool
    R.null YiString
    rope) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
    forall a b. (a -> b) -> a -> b
    $
                -- Beware of edge cases ahead
                YiString -> RegionStyle -> BufferM ()
    insertRopeWithStyleB (YiString -> YiString
    addNewLineIfNecessary YiString
    rope) RegionStyle
    LineWise
            Just (Register RegionStyle
    style YiString
    rope) -> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ YiString -> RegionStyle -> BufferM ()
    pasteInclusiveB YiString
    rope RegionStyle
    style

    pasteAfter :: EditorM ()
    pasteAfter :: EditorM ()
    pasteAfter = do
        -- TODO: use count
        register <- Char -> EditorM (Maybe Register)
    getRegisterE (Char -> EditorM (Maybe Register))
    -> (VimState -> Char) -> VimState -> EditorM (Maybe Register)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimState -> Char
    vsActiveRegister (VimState -> EditorM (Maybe Register))
    -> EditorM VimState -> EditorM (Maybe Register)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
        case register of
            Maybe Register
    Nothing -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            Just (Register RegionStyle
    LineWise YiString
    rope) -> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ do
                -- Beware of edge cases ahead
                BufferM ()
    moveToEol
                eof <- BufferM Bool
    atEof
                when eof $ insertB '\n'
                rightB
                insertRopeWithStyleB (addNewLineIfNecessary rope) LineWise
                when eof $ savingPointB $ do
                    newSize <- sizeB
                    moveTo (newSize - 1)
                    curChar <- readB
                    when (curChar == '\n') $ deleteN 1
            Just (Register RegionStyle
    style YiString
    rope) -> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ do
                BufferM Bool -> BufferM () -> BufferM ()
    forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
    whenM ((Bool -> Bool) -> BufferM Bool -> BufferM Bool
    forall a b. (a -> b) -> BufferM a -> BufferM b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Bool -> Bool
    not BufferM Bool
    atEol) BufferM ()
    rightB
                YiString -> RegionStyle -> BufferM ()
    pasteInclusiveB YiString
    rope RegionStyle
    style

    operatorBindings :: [VimOperator] -> [VimBinding]
    operatorBindings :: [VimOperator] -> [VimBinding]
    operatorBindings = (VimOperator -> VimBinding) -> [VimOperator] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap VimOperator -> VimBinding
    mkOperatorBinding
      where
        mkT :: OperatorName -> (EventString, m (), VimState -> VimState)
    mkT (Op Text
    o) = (Text -> EventString
    Ev Text
    o, () -> m ()
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> (OperatorName -> VimMode)
    -> OperatorName
    -> VimState
    -> VimState
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . OperatorName -> VimMode
    NormalOperatorPending (OperatorName -> VimState -> VimState)
    -> OperatorName -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Text -> OperatorName
    Op Text
    o)
        mkOperatorBinding :: VimOperator -> VimBinding
    mkOperatorBinding (VimOperator {operatorName :: VimOperator -> OperatorName
    operatorName = OperatorName
    opName}) =
          VimMode
    -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState)
    -> VimBinding
    mkStringBindingE VimMode
    Normal RepeatToken
    Continue ((EventString, EditorM (), VimState -> VimState) -> VimBinding)
    -> (EventString, EditorM (), VimState -> VimState) -> VimBinding
    forall a b. (a -> b) -> a -> b
    $ OperatorName -> (EventString, EditorM (), VimState -> VimState)
    forall {m :: * -> *}.
    Monad m =>
    OperatorName -> (EventString, m (), VimState -> VimState)
    mkT OperatorName
    opName

    continuingBindings :: [VimBinding]
    continuingBindings :: [VimBinding]
    continuingBindings = ((EventString, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(EventString, EditorM (), VimState -> VimState)]
    -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState)
    -> VimBinding
    mkStringBindingE VimMode
    Normal RepeatToken
    Continue)
        [ (EventString
    "r", () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimMode -> VimState -> VimState
    switchMode VimMode
    ReplaceSingleChar) -- TODO make it just a binding

        -- Transition to insert mode
        , (EventString
    "i", () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'i')
        , (EventString
    "<Ins>", () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'i')
        , (EventString
    "I", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    firstNonSpaceB, VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'I')
        , (EventString
    "a", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ Int -> BufferM ()
    moveXorEol Int
    1, VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'a')
        , (EventString
    "A", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    moveToEol, VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'A')
        , (EventString
    "o", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ do
              BufferM ()
    moveToEol
              BufferM ()
    newlineB
              BufferM ()
    indentAsTheMostIndentedNeighborLineB
            , VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'o')
        , (EventString
    "O", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ do
                         BufferM ()
    moveToSol
                         BufferM ()
    newlineB
                         BufferM ()
    leftB
                         BufferM ()
    indentAsNextB
            , VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'O')

        -- Transition to visual
        , (EventString
    "v", RegionStyle -> EditorM ()
    enableVisualE RegionStyle
    Inclusive, VimState -> VimState
    resetCount (VimState -> VimState)
    -> (VimState -> VimState) -> VimState -> VimState
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimMode -> VimState -> VimState
    switchMode (RegionStyle -> VimMode
    Visual RegionStyle
    Inclusive))
        , (EventString
    "V", RegionStyle -> EditorM ()
    enableVisualE RegionStyle
    LineWise, VimState -> VimState
    resetCount (VimState -> VimState)
    -> (VimState -> VimState) -> VimState -> VimState
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimMode -> VimState -> VimState
    switchMode (RegionStyle -> VimMode
    Visual RegionStyle
    LineWise))
        , (EventString
    "<C-v>", RegionStyle -> EditorM ()
    enableVisualE RegionStyle
    Block, VimState -> VimState
    resetCount (VimState -> VimState)
    -> (VimState -> VimState) -> VimState -> VimState
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . VimMode -> VimState -> VimState
    switchMode (RegionStyle -> VimMode
    Visual RegionStyle
    Block))
        ] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. [a] -> [a] -> [a]
    ++ ((Event, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(Event, EditorM (), VimState -> VimState)] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (Event, EditorM (), VimState -> VimState)
    -> VimBinding
    mkBindingE VimMode
    Normal RepeatToken
    Continue)
        [
        -- Changing
          (Char -> Event
    char Char
    'C',
            do region <- BufferM Region -> EditorM Region
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM Region -> EditorM Region)
    -> BufferM Region -> EditorM Region
    forall a b. (a -> b) -> a -> b
    $ BufferM () -> BufferM () -> BufferM Region
    forall a b. BufferM a -> BufferM b -> BufferM Region
    regionWithTwoMovesB (() -> BufferM ()
    forall a. a -> BufferM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) BufferM ()
    moveToEol
               void $ operatorApplyToRegionE opChange 1 $ StyledRegion Exclusive region
            , VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'C')
        , (Char -> Event
    char Char
    's', Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE Direction
    Forward EOLStickiness
    Sticky (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE, VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    's')
        , (Char -> Event
    char Char
    'S',
            do region <- BufferM Region -> EditorM Region
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM Region -> EditorM Region)
    -> BufferM Region -> EditorM Region
    forall a b. (a -> b) -> a -> b
    $ BufferM () -> BufferM () -> BufferM Region
    forall a b. BufferM a -> BufferM b -> BufferM Region
    regionWithTwoMovesB BufferM ()
    firstNonSpaceB BufferM ()
    moveToEol
               void $ operatorApplyToRegionE opDelete 1 $ StyledRegion Exclusive region
            , VimMode -> VimState -> VimState
    switchMode (VimMode -> VimState -> VimState)
    -> VimMode -> VimState -> VimState
    forall a b. (a -> b) -> a -> b
    $ Char -> VimMode
    Insert Char
    'S')

        -- Replacing
        , (Char -> Event
    char Char
    'R', () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimMode -> VimState -> VimState
    switchMode VimMode
    Replace)
        ]

    nonrepeatableBindings :: [VimBinding]
    nonrepeatableBindings :: [VimBinding]
    nonrepeatableBindings = ((Event, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(Event, EditorM (), VimState -> VimState)] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (Event, EditorM (), VimState -> VimState)
    -> VimBinding
    mkBindingE VimMode
    Normal RepeatToken
    Drop)
        [ (Key -> Event
    spec Key
    KEsc, () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    resetCount)
        , (Char -> Event
    ctrlCh Char
    'c', () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    resetCount)

        -- Yanking
        , ( Char -> Event
    char Char
    'Y'
          , do region <- BufferM Region -> EditorM Region
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM Region -> EditorM Region)
    -> BufferM Region -> EditorM Region
    forall a b. (a -> b) -> a -> b
    $ BufferM () -> BufferM () -> BufferM Region
    forall a b. BufferM a -> BufferM b -> BufferM Region
    regionWithTwoMovesB (() -> BufferM ()
    forall a. a -> BufferM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) BufferM ()
    moveToEol
               void $ operatorApplyToRegionE opYank 1 $ StyledRegion Exclusive region
          , VimState -> VimState
    forall a. a -> a
    id
          )

        -- Search
        , (Char -> Event
    char Char
    '*', EditorM ()
    addVimJumpHereE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Bool -> Direction -> EditorM ()
    searchWordE Bool
    True Direction
    Forward, VimState -> VimState
    resetCount)
        , (Char -> Event
    char Char
    '#', EditorM ()
    addVimJumpHereE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Bool -> Direction -> EditorM ()
    searchWordE Bool
    True Direction
    Backward, VimState -> VimState
    resetCount)
        , (Char -> Event
    char Char
    'n', EditorM ()
    addVimJumpHereE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> EditorM () -> EditorM ()
    withCount ((Direction -> Direction) -> EditorM ()
    continueSearching Direction -> Direction
    forall a. a -> a
    id), VimState -> VimState
    resetCount)
        , (Char -> Event
    char Char
    'N', EditorM ()
    addVimJumpHereE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> EditorM () -> EditorM ()
    withCount ((Direction -> Direction) -> EditorM ()
    continueSearching Direction -> Direction
    reverseDir), VimState -> VimState
    resetCount)
        , (Char -> Event
    char Char
    ';', (Direction -> Direction) -> EditorM ()
    repeatGotoCharE Direction -> Direction
    forall a. a -> a
    id, VimState -> VimState
    forall a. a -> a
    id)
        , (Char -> Event
    char Char
    ',', (Direction -> Direction) -> EditorM ()
    repeatGotoCharE Direction -> Direction
    reverseDir, VimState -> VimState
    forall a. a -> a
    id)

        -- Repeat
        , (Char -> Event
    char Char
    '&', EditorM (Maybe Substitution)
    loadSubstitutionE EditorM (Maybe Substitution)
    -> (Maybe Substitution -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= EditorM ()
    -> (Substitution -> EditorM ()) -> Maybe Substitution -> EditorM ()
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (() -> EditorM ()
    forall a. a -> EditorM a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()) Substitution -> EditorM ()
    repeatSubstitutionFlaglessE, VimState -> VimState
    forall a. a -> a
    id)

        -- Transition to ex
        , (Char -> Event
    char Char
    ':', do
            EditorM BufferRef -> EditorM ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Text -> KeymapEndo -> EditorM BufferRef
    spawnMinibufferE Text
    ":" KeymapEndo
    forall a. a -> a
    id)
            EditorM ()
    historyStart
            Text -> EditorM ()
    historyPrefixSet Text
    ""
          , VimMode -> VimState -> VimState
    switchMode VimMode
    Ex)

        -- Undo
        , (Char -> Event
    char Char
    'u', BufferM () -> EditorM ()
    withCountOnBuffer BufferM ()
    undoB EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    leftOnEol, VimState -> VimState
    forall a. a -> a
    id)
        , (Char -> Event
    char Char
    'U', BufferM () -> EditorM ()
    withCountOnBuffer BufferM ()
    undoB EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    leftOnEol, VimState -> VimState
    forall a. a -> a
    id) -- TODO
        , (Char -> Event
    ctrlCh Char
    'r', BufferM () -> EditorM ()
    withCountOnBuffer BufferM ()
    redoB EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    leftOnEol, VimState -> VimState
    forall a. a -> a
    id)

        -- scrolling
        ,(Char -> Event
    ctrlCh Char
    'b', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    upScreensB, VimState -> VimState
    forall a. a -> a
    id)
        ,(Char -> Event
    ctrlCh Char
    'f', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    downScreensB, VimState -> VimState
    forall a. a -> a
    id)
        ,(Char -> Event
    ctrlCh Char
    'u', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> Int) -> Int -> BufferM ()
    vimScrollByB (Int -> Int
    forall a. Num a => a -> a
    negate (Int -> Int) -> (Int -> Int) -> Int -> Int
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    2)), VimState -> VimState
    forall a. a -> a
    id)
        ,(Char -> Event
    ctrlCh Char
    'd', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Int -> Int) -> Int -> BufferM ()
    vimScrollByB (Int -> Int -> Int
    forall a. Integral a => a -> a -> a
    `div` Int
    2), VimState -> VimState
    forall a. a -> a
    id)
        ,(Char -> Event
    ctrlCh Char
    'y', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    vimScrollB (Int -> BufferM ()) -> (Int -> Int) -> Int -> BufferM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int
    forall a. Num a => a -> a
    negate, VimState -> VimState
    forall a. a -> a
    id)
        ,(Char -> Event
    ctrlCh Char
    'e', EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    vimScrollB, VimState -> VimState
    forall a. a -> a
    id)

        -- unsorted TODO
        , (Char -> Event
    char Char
    '-', () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    forall a. a -> a
    id)
        , (Char -> Event
    char Char
    '+', () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    forall a. a -> a
    id)
        , (Key -> Event
    spec Key
    KEnter, () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (), VimState -> VimState
    forall a. a -> a
    id)
        ] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <> ((EventString, EditorM (), VimState -> VimState) -> VimBinding)
    -> [(EventString, EditorM (), VimState -> VimState)]
    -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState)
    -> VimBinding
    mkStringBindingE VimMode
    Normal RepeatToken
    Drop)
        [ (EventString
    "g*", Bool -> Direction -> EditorM ()
    searchWordE Bool
    False Direction
    Forward, VimState -> VimState
    resetCount)
        , (EventString
    "g#", Bool -> Direction -> EditorM ()
    searchWordE Bool
    False Direction
    Backward, VimState -> VimState
    resetCount)
        , (EventString
    "gd", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ (forall syntax. Mode syntax -> BufferM ()) -> BufferM ()
    forall a. (forall syntax. Mode syntax -> BufferM a) -> BufferM a
    withModeB Mode syntax -> BufferM ()
    forall syntax. Mode syntax -> BufferM ()
    modeGotoDeclaration, VimState -> VimState
    resetCount)
        , (EventString
    "gD", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ (forall syntax. Mode syntax -> BufferM ()) -> BufferM ()
    forall a. (forall syntax. Mode syntax -> BufferM a) -> BufferM a
    withModeB Mode syntax -> BufferM ()
    forall syntax. Mode syntax -> BufferM ()
    modeGotoDeclaration, VimState -> VimState
    resetCount)
        , (EventString
    "g&", EditorM (Maybe Substitution)
    loadSubstitutionE EditorM (Maybe Substitution)
    -> (Maybe Substitution -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= EditorM ()
    -> (Substitution -> EditorM ()) -> Maybe Substitution -> EditorM ()
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (() -> EditorM ()
    forall a. a -> EditorM a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()) Substitution -> EditorM ()
    repeatSubstitutionE, VimState -> VimState
    forall a. a -> a
    id)
        , (EventString
    "<C-g>", EditorM ()
    printFileInfoE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>c", EditorM ()
    tryCloseE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>o", EditorM ()
    closeOtherE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>s", EditorM ()
    splitE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>w", EditorM ()
    nextWinE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w><Down>", EditorM ()
    nextWinE, VimState -> VimState
    resetCount) -- TODO: please implement downWinE
        , (EventString
    "<C-w><Right>", EditorM ()
    nextWinE, VimState -> VimState
    resetCount) -- TODO: please implement rightWinE
        , (EventString
    "<C-w><C-w>", EditorM ()
    nextWinE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>W", EditorM ()
    prevWinE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>p", EditorM ()
    prevWinE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w><Up>", EditorM ()
    prevWinE, VimState -> VimState
    resetCount) -- TODO: please implement upWinE
        , (EventString
    "<C-w><Left>", EditorM ()
    prevWinE, VimState -> VimState
    resetCount) -- TODO: please implement leftWinE
        , (EventString
    "<C-w>l", EditorM ()
    layoutManagersNextE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>L", EditorM ()
    layoutManagersPreviousE, VimState -> VimState
    resetCount)
        --, ("<C-w> ", layoutManagersNextE, resetCount)
        , (EventString
    "<C-w>v", EditorM ()
    layoutManagerNextVariantE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>V", EditorM ()
    layoutManagerPreviousVariantE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-a>", EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    incrementNextNumberByB, VimState -> VimState
    resetCount)
        , (EventString
    "<C-x>", EditorM Int
    getCountE EditorM Int -> (Int -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> (Int -> BufferM ()) -> Int -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> BufferM ()
    incrementNextNumberByB (Int -> BufferM ()) -> (Int -> Int) -> Int -> BufferM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Int
    forall a. Num a => a -> a
    negate, VimState -> VimState
    resetCount)

        -- z commands
        -- TODO Add prefix count
        , (EventString
    "zt", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    scrollCursorToTopB, VimState -> VimState
    resetCount)
        , (EventString
    "zb", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    scrollCursorToBottomB, VimState -> VimState
    resetCount)
        , (EventString
    "zz", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    scrollToCursorB, VimState -> VimState
    resetCount)
        {- -- TODO Horizantal scrolling
        , ("ze", withCurrentBuffer .., resetCount)
        , ("zs", withCurrentBuffer .., resetCount)
        , ("zH", withCurrentBuffer .., resetCount)
        , ("zL", withCurrentBuffer .., resetCount)
        , ("zh", withCurrentBuffer .., resetCount)
        , ("zl", withCurrentBuffer .., resetCount)
        -}
        , (EventString
    "z.", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ BufferM ()
    scrollToCursorB BufferM () -> BufferM () -> BufferM ()
    forall a b. BufferM a -> BufferM b -> BufferM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferM ()
    moveToSol, VimState -> VimState
    resetCount)
        , (EventString
    "z+", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    scrollToLineBelowWindowB, VimState -> VimState
    resetCount)
        , (EventString
    "z-", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ BufferM ()
    scrollCursorToBottomB BufferM () -> BufferM () -> BufferM ()
    forall a b. BufferM a -> BufferM b -> BufferM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferM ()
    moveToSol, VimState -> VimState
    resetCount)
        , (EventString
    "z^", BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    scrollToLineAboveWindowB, VimState -> VimState
    resetCount)
        {- -- TODO Code folding
        , ("zf", .., resetCount)
        , ("zc", .., resetCount)
        , ("zo", .., resetCount)
        , ("za", .., resetCount)
        , ("zC", .., resetCount)
        , ("zO", .., resetCount)
        , ("zA", .., resetCount)
        , ("zr", .., resetCount)
        , ("zR", .., resetCount)
        , ("zm", .., resetCount)
        , ("zM", .., resetCount)
        -}

        -- Z commands
        ] [VimBinding] -> [VimBinding] -> [VimBinding]
    forall a. Semigroup a => a -> a -> a
    <> ((EventString, YiM (), VimState -> VimState) -> VimBinding)
    -> [(EventString, YiM (), VimState -> VimState)] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> (EventString, YiM (), VimState -> VimState) -> VimBinding
    mkStringBindingY VimMode
    Normal)
        [ (EventString
    "ZQ", YiM ()
    quitEditor, VimState -> VimState
    forall a. a -> a
    id)
        -- TODO ZZ should replicate :x not :wq
        , (EventString
    "ZZ", YiM Bool
    fwriteE YiM Bool -> YiM () -> YiM ()
    forall a b. YiM a -> YiM b -> YiM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> YiM ()
    closeWindow, VimState -> VimState
    forall a. a -> a
    id)
        ]

    fileEditBindings :: [VimBinding]
    fileEditBindings :: [VimBinding]
    fileEditBindings =  ((EventString, YiM (), VimState -> VimState) -> VimBinding)
    -> [(EventString, YiM (), VimState -> VimState)] -> [VimBinding]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (VimMode
    -> (EventString, YiM (), VimState -> VimState) -> VimBinding
    mkStringBindingY VimMode
    Normal)
        [ (EventString
    "gf", Maybe (EditorM ()) -> YiM ()
    openFileUnderCursor Maybe (EditorM ())
    forall a. Maybe a
    Nothing, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>gf", Maybe (EditorM ()) -> YiM ()
    openFileUnderCursor (Maybe (EditorM ()) -> YiM ()) -> Maybe (EditorM ()) -> YiM ()
    forall a b. (a -> b) -> a -> b
    $ EditorM () -> Maybe (EditorM ())
    forall a. a -> Maybe a
    Just EditorM ()
    newTabE, VimState -> VimState
    resetCount)
        , (EventString
    "<C-w>f", Maybe (EditorM ()) -> YiM ()
    openFileUnderCursor (Maybe (EditorM ()) -> YiM ()) -> Maybe (EditorM ()) -> YiM ()
    forall a b. (a -> b) -> a -> b
    $ EditorM () -> Maybe (EditorM ())
    forall a. a -> Maybe a
    Just (EditorM ()
    splitE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> EditorM ()
    prevWinE), VimState -> VimState
    resetCount)
        ]

    setMarkBinding :: VimBinding
    setMarkBinding :: VimBinding
    setMarkBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    forall {m :: * -> *}.
    MonadEditor m =>
    String -> VimState -> MatchResult (m RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: String -> VimState -> MatchResult (m RepeatToken)
    f String
    _ VimState
    s | VimState -> VimMode
    vsMode VimState
    s VimMode -> VimMode -> Bool
    forall a. Eq a => a -> a -> Bool
    /= VimMode
    Normal = MatchResult (m RepeatToken)
    forall a. MatchResult a
    NoMatch
              f String
    "m" VimState
    _ = MatchResult (m RepeatToken)
    forall a. MatchResult a
    PartialMatch
              f (Char
    'm':Char
    c:[]) VimState
    _ = m RepeatToken -> MatchResult (m RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (m RepeatToken -> MatchResult (m RepeatToken))
    -> m RepeatToken -> MatchResult (m RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                  BufferM () -> m ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> m ()) -> BufferM () -> m ()
    forall a b. (a -> b) -> a -> b
    $ String -> BufferM ()
    setNamedMarkHereB [Char
    c]
                  RepeatToken -> m RepeatToken
    forall a. a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Drop
              f String
    _ VimState
    _ = MatchResult (m RepeatToken)
    forall a. MatchResult a
    NoMatch

    searchWordE :: Bool -> Direction -> EditorM ()
    searchWordE :: Bool -> Direction -> EditorM ()
    searchWordE Bool
    wholeWord Direction
    dir = do
      word <- BufferM YiString -> EditorM YiString
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM YiString
    readCurrentWordB

      let search SearchExp
    re = do
            SearchExp -> EditorM ()
    setRegexE SearchExp
    re
            (Direction -> Identity Direction) -> Editor -> Identity Editor
    Lens' Editor Direction
    searchDirectionA ((Direction -> Identity Direction) -> Editor -> Identity Editor)
    -> Direction -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= Direction
    dir
            EditorM () -> EditorM ()
    withCount (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ (Direction -> Direction) -> EditorM ()
    continueSearching (Direction -> Direction -> Direction
    forall a b. a -> b -> a
    const Direction
    dir)

      if wholeWord
      then case makeSearchOptsM [] $ "\\<" <> R.toString word <> "\\>" of
              Right SearchExp
    re -> SearchExp -> EditorM ()
    search SearchExp
    re
              Left String
    _ -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      else search $ makeSimpleSearch word

    searchBinding :: VimBinding
    searchBinding :: VimBinding
    searchBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
    f String
    evs (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal }) | String
    evs String -> [String] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` String -> [String]
    forall a. Eq a => [a] -> [[a]]
    group [Char
    '/', Char
    '?']
                = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                      state <- (VimState -> VimMode) -> EditorM VimState -> EditorM VimMode
    forall a b. (a -> b) -> EditorM a -> EditorM b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap VimState -> VimMode
    vsMode EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
                      let dir = if String
    evs String -> String -> Bool
    forall a. Eq a => a -> a -> Bool
    == String
    "/" then Direction
    Forward else Direction
    Backward
                      switchModeE $ Search state dir
                      isearchInitE dir
                      historyStart
                      historyPrefixSet T.empty
                      return Continue
              f String
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    continueSearching :: (Direction -> Direction) -> EditorM ()
    continueSearching :: (Direction -> Direction) -> EditorM ()
    continueSearching Direction -> Direction
    fdir =
      EditorM (Maybe SearchExp)
    getRegexE EditorM (Maybe SearchExp)
    -> (Maybe SearchExp -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
        Just SearchExp
    regex -> do
          dir <- Direction -> Direction
    fdir (Direction -> Direction) -> EditorM Direction -> EditorM Direction
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Getting Direction Editor Direction -> EditorM Direction
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Direction Editor Direction
    Lens' Editor Direction
    searchDirectionA
          printMsg . T.pack $ (if dir == Forward then '/' else '?') : seInput regex
          void $ doVimSearch Nothing [] dir
        Maybe SearchExp
    Nothing -> Text -> EditorM ()
    forall (m :: * -> *). MonadEditor m => Text -> m ()
    printMsg Text
    "No previous search pattern"

    repeatGotoCharE :: (Direction -> Direction) -> EditorM ()
    repeatGotoCharE :: (Direction -> Direction) -> EditorM ()
    repeatGotoCharE Direction -> Direction
    mutateDir = do
        prevCommand <- (VimState -> Maybe GotoCharCommand)
    -> EditorM VimState -> EditorM (Maybe GotoCharCommand)
    forall a b. (a -> b) -> EditorM a -> EditorM b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap VimState -> Maybe GotoCharCommand
    vsLastGotoCharCommand EditorM VimState
    forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn
        count <- getCountE
        withCurrentBuffer $ case prevCommand of
            Just (GotoCharCommand Char
    c Direction
    dir RegionStyle
    style) -> do
                let newDir :: Direction
    newDir = Direction -> Direction
    mutateDir Direction
    dir
                let move :: BufferM ()
    move = Char -> Direction -> RegionStyle -> Bool -> BufferM ()
    gotoCharacterB Char
    c Direction
    newDir RegionStyle
    style Bool
    True
                p0 <- BufferM Point
    pointB
                replicateM_ (count - 1) $ do
                    move
                    when (style == Exclusive) $ moveB Character newDir
                p1 <- pointB
                move
                p2 <- pointB
                when (p1 == p2) $ moveTo p0
            Maybe GotoCharCommand
    Nothing -> () -> BufferM ()
    forall a. a -> BufferM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

    enableVisualE :: RegionStyle -> EditorM ()
    enableVisualE :: RegionStyle -> EditorM ()
    enableVisualE RegionStyle
    style = BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ do
        RegionStyle -> BufferM ()
    putRegionStyle RegionStyle
    style
        (Bool -> Identity Bool) -> FBuffer -> Identity FBuffer
    Lens' FBuffer Bool
    rectangleSelectionA ((Bool -> Identity Bool) -> FBuffer -> Identity FBuffer)
    -> Bool -> BufferM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    .= (RegionStyle
    Block RegionStyle -> RegionStyle -> Bool
    forall a. Eq a => a -> a -> Bool
    == RegionStyle
    style)
        Bool -> BufferM ()
    setVisibleSelection Bool
    True
        BufferM Point
    pointB BufferM Point -> (Point -> BufferM ()) -> BufferM ()
    forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Point -> BufferM ()
    setSelectionMarkPointB

    cutCharE :: Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE :: Direction -> EOLStickiness -> Int -> EditorM ()
    cutCharE Direction
    dir EOLStickiness
    stickiness Int
    count = do
        r <- BufferM YiString -> EditorM YiString
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM YiString -> EditorM YiString)
    -> BufferM YiString -> EditorM YiString
    forall a b. (a -> b) -> a -> b
    $ do
            p0 <- BufferM Point
    pointB
            (if dir == Forward then moveXorEol else moveXorSol) count
            p1 <- pointB
            let region = Point -> Point -> Region
    mkRegion Point
    p0 Point
    p1
            rope <- readRegionB region
            deleteRegionB $ mkRegion p0 p1
            when (stickiness == NonSticky) leftOnEol
            return rope
        regName <- fmap vsActiveRegister getEditorDyn
        setRegisterE regName Inclusive r

    tabTraversalBinding :: VimBinding
    tabTraversalBinding :: VimBinding
    tabTraversalBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
    f String
    "g" (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal }) = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    PartialMatch
              f (Char
    'g':Char
    c:[]) (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal }) | Char
    c Char -> String -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Char
    't', Char
    'T'] = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                  count <- EditorM Int
    getCountE
                  replicateM_ count $ if c == 'T' then previousTabE else nextTabE
                  resetCountE
                  return Drop
              f String
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    openFileUnderCursor :: Maybe (EditorM ()) -> YiM ()
    openFileUnderCursor :: Maybe (EditorM ()) -> YiM ()
    openFileUnderCursor Maybe (EditorM ())
    editorAction = do
      fileName <- (YiString -> String) -> YiM YiString -> YiM String
    forall a b. (a -> b) -> YiM a -> YiM b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap YiString -> String
    R.toString (YiM YiString -> YiM String)
    -> (BufferM YiString -> YiM YiString)
    -> BufferM YiString
    -> YiM String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . BufferM YiString -> YiM YiString
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM YiString -> YiM String) -> BufferM YiString -> YiM String
    forall a b. (a -> b) -> a -> b
    $ TextUnit -> BufferM YiString
    readUnitB TextUnit
    unitViWORD
      fileExists <- io $ doesFileExist =<< expandTilda fileName
      if fileExists then do
          maybeM withEditor editorAction
          openNewFile $ fileName
      else
          withEditor . fail $ "Can't find file \"" <> fileName <> "\""

    recordMacroBinding :: VimBinding
    recordMacroBinding :: VimBinding
    recordMacroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
    f String
    "q" (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal
                              , vsCurrentMacroRecording :: VimState -> Maybe (Char, EventString)
    vsCurrentMacroRecording = Maybe (Char, EventString)
    Nothing })
                    = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    PartialMatch
              f [Char
    'q', Char
    c] (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal })
                  = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                        (VimState -> VimState) -> EditorM ()
    modifyStateE ((VimState -> VimState) -> EditorM ())
    -> (VimState -> VimState) -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ \VimState
    s ->
                            VimState
    s { vsCurrentMacroRecording = Just (c, mempty) }
                        RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Finish
              f String
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    finishRecordingMacroBinding :: VimBinding
    finishRecordingMacroBinding :: VimBinding
    finishRecordingMacroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    forall {a}.
    (Eq a, IsString a) =>
    a -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: a -> VimState -> MatchResult (EditorM RepeatToken)
    f a
    "q" (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal
                              , vsCurrentMacroRecording :: VimState -> Maybe (Char, EventString)
    vsCurrentMacroRecording = Just (Char
    macroName, Ev Text
    macroBody) })
                    = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                          let reg :: Register
    reg = RegionStyle -> YiString -> Register
    Register RegionStyle
    Exclusive (Text -> YiString
    R.fromText (Int -> Text -> Text
    T.drop Int
    2 Text
    macroBody))
                          (VimState -> VimState) -> EditorM ()
    modifyStateE ((VimState -> VimState) -> EditorM ())
    -> (VimState -> VimState) -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ \VimState
    s -> VimState
    s
                              { vsCurrentMacroRecording = Nothing
                              , vsRegisterMap = insert macroName reg (vsRegisterMap s)
                              }
                          RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Finish
              f a
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    playMacroBinding :: VimBinding
    playMacroBinding :: VimBinding
    playMacroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
    -> VimBinding
    VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
    f (String -> VimState -> MatchResult (EditorM RepeatToken))
    -> (EventString -> String)
    -> EventString
    -> VimState
    -> MatchResult (EditorM RepeatToken)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> String
    T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EventString -> Text
    _unEv)
        where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
    f String
    "@" (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal }) = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    PartialMatch
              f [Char
    '@', Char
    c] (VimState { vsMode :: VimState -> VimMode
    vsMode = VimMode
    Normal
                                   , vsRegisterMap :: VimState -> HashMap Char Register
    vsRegisterMap = HashMap Char Register
    registers
                                   , vsCount :: VimState -> Maybe Int
    vsCount = Maybe Int
    mbCount }) = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a. a -> MatchResult a
    WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
    -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
    forall a b. (a -> b) -> a -> b
    $ do
                  EditorM ()
    resetCountE
                  case Char -> HashMap Char Register -> Maybe Register
    forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
    lookup Char
    c HashMap Char Register
    registers of
                      Just reg :: Register
    reg@(Register RegionStyle
    _ YiString
    evs) -> do
                          let count :: Int
    count = Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe Int
    1 Maybe Int
    mbCount
                              mkAct :: YiString -> EventString
    mkAct = Text -> EventString
    Ev (Text -> EventString)
    -> (YiString -> Text) -> YiString -> EventString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text -> Text
    T.replicate Int
    count (Text -> Text) -> (YiString -> Text) -> YiString -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . YiString -> Text
    R.toText
                          EventString -> EditorM ()
    scheduleActionStringForEval (EventString -> EditorM ())
    -> (YiString -> EventString) -> YiString -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . YiString -> EventString
    mkAct (YiString -> EditorM ()) -> YiString -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ YiString
    evs
                          (VimState -> VimState) -> EditorM ()
    modifyStateE ((VimState -> VimState) -> EditorM ())
    -> (VimState -> VimState) -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ \VimState
    s ->
                              VimState
    s { vsRegisterMap = insert '@' reg (vsRegisterMap s) }
                          RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Finish
                      Maybe Register
    Nothing -> RepeatToken -> EditorM RepeatToken
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return RepeatToken
    Drop
              f String
    _ VimState
    _ = MatchResult (EditorM RepeatToken)
    forall a. MatchResult a
    NoMatch

    -- TODO: withCount name implies that parameter has type (Int -> EditorM ())
    --       Is there a better name for this function?
    withCount :: EditorM () -> EditorM ()
    withCount :: EditorM () -> EditorM ()
    withCount EditorM ()
    action = (Int -> EditorM () -> EditorM ())
    -> EditorM () -> Int -> EditorM ()
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Int -> EditorM () -> EditorM ()
    forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
    replicateM_ EditorM ()
    action (Int -> EditorM ()) -> EditorM Int -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< EditorM Int
    getCountE

    withCountOnBuffer :: BufferM () -> EditorM ()
    withCountOnBuffer :: BufferM () -> EditorM ()
    withCountOnBuffer BufferM ()
    action = EditorM () -> EditorM ()
    withCount (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM ()
    action