{-# 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
/= :: EOLStickiness -> EOLStickiness -> Bool
$c/= :: EOLStickiness -> EOLStickiness -> Bool
== :: EOLStickiness -> EOLStickiness -> Bool
$c== :: 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 (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 :: Maybe Int
vsCount = Int -> Maybe Int
forall a. a -> Maybe a
Just Int
d }
    mutate vs :: VimState
vs@(VimState {vsCount :: VimState -> Maybe Int
vsCount = Just Int
count}) =
      VimState
vs { vsCount :: Maybe Int
vsCount = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
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) -> [Char] -> [VimBinding]
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 (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 ([Char], Int, Int) -> YiM ()
gotoTag Tag
tag Int
0 Maybe ([Char], 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
              VimState
currentState <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
              case VimState -> Maybe Int
vsCount VimState
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 (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
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 (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 ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
forall a.
(Eq a, IsString a) =>
a -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
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
      VimState
currentState <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
      case VimState -> Maybe RepeatableAction
vsRepeatableAction VimState
currentState of
          Maybe RepeatableAction
Nothing -> () -> EditorM ()
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
      RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
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 (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 (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
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 (m :: * -> *) a. Monad m => a -> m a
return ()) BufferM ()
moveToEol
           EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM RepeatToken -> EditorM ())
-> EditorM RepeatToken -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimOperator -> Int -> StyledRegion -> EditorM RepeatToken
operatorApplyToRegionE VimOperator
opDelete Int
1 (StyledRegion -> EditorM RepeatToken)
-> StyledRegion -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ RegionStyle -> Region -> StyledRegion
StyledRegion RegionStyle
Exclusive Region
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
           Int
count <- EditorM Int
getCountE
           BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
               Int -> (Char -> Char) -> BufferM ()
transformCharactersInLineN Int
count Char -> Char
switchCaseChar
               BufferM ()
leftOnEol
        , VimState -> VimState
resetCount)
    , (EventString
"J", do
        Int
count <- (Int -> Int) -> EditorM Int -> EditorM Int
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
        BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
            (StyledRegion RegionStyle
s Region
r) <- case EventString -> MatchResult Move
stringToMove EventString
"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
_ -> [Char] -> BufferM StyledRegion
forall a. HasCallStack => [Char] -> a
error [Char]
"can't happen"
            BufferM Int -> BufferM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (BufferM Int -> BufferM ()) -> BufferM Int -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> BufferM Int
lineMoveRel (Int -> BufferM Int) -> Int -> BufferM Int
forall a b. (a -> b) -> a -> b
$ Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
            BufferM ()
moveToEol
            Region -> BufferM ()
joinLinesB (Region -> BufferM ()) -> BufferM Region -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Region -> RegionStyle -> BufferM Region
convertRegionToStyleB Region
r RegionStyle
s
       , VimState -> VimState
resetCount)
    ]

pasteBefore :: EditorM ()
pasteBefore :: EditorM ()
pasteBefore = do
    -- TODO: use count
    Maybe Register
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 Maybe Register
register of
        Maybe Register
Nothing -> () -> EditorM ()
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
    Maybe Register
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 Maybe Register
register of
        Maybe Register
Nothing -> () -> EditorM ()
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
            Bool
eof <- BufferM Bool
atEof
            Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
eof (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Char -> BufferM ()
insertB Char
'\n'
            BufferM ()
rightB
            YiString -> RegionStyle -> BufferM ()
insertRopeWithStyleB (YiString -> YiString
addNewLineIfNecessary YiString
rope) RegionStyle
LineWise
            Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
eof (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ BufferM () -> BufferM ()
forall a. BufferM a -> BufferM a
savingPointB (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ do
                Point
newSize <- BufferM Point
sizeB
                Point -> BufferM ()
moveTo (Point
newSize Point -> Point -> Point
forall a. Num a => a -> a -> a
- Point
1)
                Char
curChar <- BufferM Char
readB
                Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Char
curChar Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n') (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> BufferM ()
deleteN Int
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 (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 (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 (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 (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 (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 (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 (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 (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
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 (m :: * -> *) a. Monad m => a -> m a
return ()) BufferM ()
moveToEol
           EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM RepeatToken -> EditorM ())
-> EditorM RepeatToken -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimOperator -> Int -> StyledRegion -> EditorM RepeatToken
operatorApplyToRegionE VimOperator
opChange Int
1 (StyledRegion -> EditorM RepeatToken)
-> StyledRegion -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ RegionStyle -> Region -> StyledRegion
StyledRegion RegionStyle
Exclusive Region
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
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
           EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM RepeatToken -> EditorM ())
-> EditorM RepeatToken -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimOperator -> Int -> StyledRegion -> EditorM RepeatToken
operatorApplyToRegionE VimOperator
opDelete Int
1 (StyledRegion -> EditorM RepeatToken)
-> StyledRegion -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ RegionStyle -> Region -> StyledRegion
StyledRegion RegionStyle
Exclusive Region
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 (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 (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 (m :: * -> *) a. Monad m => a -> m a
return (), VimState -> VimState
resetCount)
    , (Char -> Event
ctrlCh Char
'c', () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return (), VimState -> VimState
resetCount)

    -- Yanking
    , ( Char -> Event
char Char
'Y'
      , do Region
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 (m :: * -> *) a. Monad m => a -> m a
return ()) BufferM ()
moveToEol
           EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM RepeatToken -> EditorM ())
-> EditorM RepeatToken -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimOperator -> Int -> StyledRegion -> EditorM RepeatToken
operatorApplyToRegionE VimOperator
opYank Int
1 (StyledRegion -> EditorM RepeatToken)
-> StyledRegion -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ RegionStyle -> Region -> StyledRegion
StyledRegion RegionStyle
Exclusive Region
region
      , VimState -> VimState
forall a. a -> a
id
      )

    -- Search
    , (Char -> Event
char Char
'*', EditorM ()
addVimJumpHereE EditorM () -> EditorM () -> EditorM ()
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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (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 (m :: * -> *) a. Monad m => a -> m a
return (), VimState -> VimState
forall a. a -> a
id)
    , (Char -> Event
char Char
'+', () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return (), VimState -> VimState
forall a. a -> a
id)
    , (Key -> Event
spec Key
KEnter, () -> EditorM ()
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 (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 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 forall syntax. Mode syntax -> BufferM ()
modeGotoDeclaration, VimState -> VimState
resetCount)
    , (EventString
"g&", EditorM (Maybe Substitution)
loadSubstitutionE EditorM (Maybe Substitution)
-> (Maybe Substitution -> EditorM ()) -> EditorM ()
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 (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 (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 (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 (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 (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 (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 (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 (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 (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 ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
forall (m :: * -> *).
MonadEditor m =>
[Char] -> VimState -> MatchResult (m RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: [Char] -> VimState -> MatchResult (m RepeatToken)
f [Char]
_ 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 [Char]
"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
$ [Char] -> BufferM ()
setNamedMarkHereB [Char
c]
              RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Drop
          f [Char]
_ VimState
_ = MatchResult (m RepeatToken)
forall a. MatchResult a
NoMatch

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

  let search :: SearchExp -> EditorM ()
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 Bool
wholeWord
  then case [SearchOption] -> [Char] -> Either [Char] SearchExp
makeSearchOptsM [] ([Char] -> Either [Char] SearchExp)
-> [Char] -> Either [Char] SearchExp
forall a b. (a -> b) -> a -> b
$ [Char]
"\\<" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> YiString -> [Char]
R.toString YiString
word [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
"\\>" of
          Right SearchExp
re -> SearchExp -> EditorM ()
search SearchExp
re
          Left [Char]
_ -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  else SearchExp -> EditorM ()
search (SearchExp -> EditorM ()) -> SearchExp -> EditorM ()
forall a b. (a -> b) -> a -> b
$ YiString -> SearchExp
makeSimpleSearch YiString
word

searchBinding :: VimBinding
searchBinding :: VimBinding
searchBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: [Char] -> VimState -> MatchResult (EditorM RepeatToken)
f [Char]
evs (VimState { vsMode :: VimState -> VimMode
vsMode = VimMode
Normal }) | [Char]
evs [Char] -> [[Char]] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char] -> [[Char]]
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
                  VimMode
state <- (VimState -> VimMode) -> EditorM VimState -> EditorM VimMode
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 :: Direction
dir = if [Char]
evs [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"/" then Direction
Forward else Direction
Backward
                  VimMode -> EditorM ()
switchModeE (VimMode -> EditorM ()) -> VimMode -> EditorM ()
forall a b. (a -> b) -> a -> b
$ VimMode -> Direction -> VimMode
Search VimMode
state Direction
dir
                  Direction -> EditorM ()
isearchInitE Direction
dir
                  EditorM ()
historyStart
                  Text -> EditorM ()
historyPrefixSet Text
T.empty
                  RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
          f [Char]
_ 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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Just SearchExp
regex -> do
      Direction
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
      Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> ([Char] -> Text) -> [Char] -> EditorM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack ([Char] -> EditorM ()) -> [Char] -> EditorM ()
forall a b. (a -> b) -> a -> b
$ (if Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Forward then Char
'/' else Char
'?') Char -> [Char] -> [Char]
forall a. a -> [a] -> [a]
: SearchExp -> [Char]
seInput SearchExp
regex
      EditorM () -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Maybe [Char] -> [SearchOption] -> Direction -> EditorM ()
doVimSearch Maybe [Char]
forall a. Maybe a
Nothing [] Direction
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
    Maybe GotoCharCommand
prevCommand <- (VimState -> Maybe GotoCharCommand)
-> EditorM VimState -> EditorM (Maybe GotoCharCommand)
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
    Int
count <- EditorM Int
getCountE
    BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ case Maybe GotoCharCommand
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
            Point
p0 <- BufferM Point
pointB
            Int -> BufferM () -> BufferM ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ (Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ do
                BufferM ()
move
                Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (RegionStyle
style RegionStyle -> RegionStyle -> Bool
forall a. Eq a => a -> a -> Bool
== RegionStyle
Exclusive) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ TextUnit -> Direction -> BufferM ()
moveB TextUnit
Character Direction
newDir
            Point
p1 <- BufferM Point
pointB
            BufferM ()
move
            Point
p2 <- BufferM Point
pointB
            Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Point
p1 Point -> Point -> Bool
forall a. Eq a => a -> a -> Bool
== Point
p2) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
moveTo Point
p0
        Maybe GotoCharCommand
Nothing -> () -> BufferM ()
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 (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
    YiString
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
        Point
p0 <- BufferM Point
pointB
        (if Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Forward then Int -> BufferM ()
moveXorEol else Int -> BufferM ()
moveXorSol) Int
count
        Point
p1 <- BufferM Point
pointB
        let region :: Region
region = Point -> Point -> Region
mkRegion Point
p0 Point
p1
        YiString
rope <- Region -> BufferM YiString
readRegionB Region
region
        Region -> BufferM ()
deleteRegionB (Region -> BufferM ()) -> Region -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Point -> Point -> Region
mkRegion Point
p0 Point
p1
        Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (EOLStickiness
stickiness EOLStickiness -> EOLStickiness -> Bool
forall a. Eq a => a -> a -> Bool
== EOLStickiness
NonSticky) BufferM ()
leftOnEol
        YiString -> BufferM YiString
forall (m :: * -> *) a. Monad m => a -> m a
return YiString
rope
    Char
regName <- (VimState -> Char) -> EditorM VimState -> EditorM Char
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimState -> Char
vsActiveRegister EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
    Char -> RegionStyle -> YiString -> EditorM ()
setRegisterE Char
regName RegionStyle
Inclusive YiString
r

tabTraversalBinding :: VimBinding
tabTraversalBinding :: VimBinding
tabTraversalBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: [Char] -> VimState -> MatchResult (EditorM RepeatToken)
f [Char]
"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 -> [Char] -> 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
              Int
count <- EditorM Int
getCountE
              Int -> EditorM () -> EditorM ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ Int
count (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'T' then EditorM ()
previousTabE else EditorM ()
nextTabE
              EditorM ()
resetCountE
              RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Drop
          f [Char]
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

openFileUnderCursor :: Maybe (EditorM ()) -> YiM ()
openFileUnderCursor :: Maybe (EditorM ()) -> YiM ()
openFileUnderCursor Maybe (EditorM ())
editorAction = do
  [Char]
fileName <- (YiString -> [Char]) -> YiM YiString -> YiM [Char]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap YiString -> [Char]
R.toString (YiM YiString -> YiM [Char])
-> (BufferM YiString -> YiM YiString)
-> BufferM YiString
-> YiM [Char]
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 [Char]) -> BufferM YiString -> YiM [Char]
forall a b. (a -> b) -> a -> b
$ TextUnit -> BufferM YiString
readUnitB TextUnit
unitViWORD
  Bool
fileExists <- IO Bool -> YiM Bool
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io (IO Bool -> YiM Bool) -> IO Bool -> YiM Bool
forall a b. (a -> b) -> a -> b
$ [Char] -> IO Bool
doesFileExist ([Char] -> IO Bool) -> IO [Char] -> IO Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< [Char] -> IO [Char]
expandTilda [Char]
fileName
  if Bool
fileExists then do
      (EditorM () -> YiM ()) -> Maybe (EditorM ()) -> YiM ()
forall (m :: * -> *) x. Monad m => (x -> m ()) -> Maybe x -> m ()
maybeM EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor Maybe (EditorM ())
editorAction
      [Char] -> YiM ()
openNewFile ([Char] -> YiM ()) -> [Char] -> YiM ()
forall a b. (a -> b) -> a -> b
$ [Char]
fileName
  else
      EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> YiM ())
-> ([Char] -> EditorM ()) -> [Char] -> YiM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> EditorM ()
forall (m :: * -> *) a. MonadFail m => [Char] -> m a
fail ([Char] -> YiM ()) -> [Char] -> YiM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Can't find file \"" [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
fileName [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
"\""

recordMacroBinding :: VimBinding
recordMacroBinding :: VimBinding
recordMacroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: [Char] -> VimState -> MatchResult (EditorM RepeatToken)
f [Char]
"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 :: Maybe (Char, EventString)
vsCurrentMacroRecording = (Char, EventString) -> Maybe (Char, EventString)
forall a. a -> Maybe a
Just (Char
c, EventString
forall a. Monoid a => a
mempty) }
                    RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Finish
          f [Char]
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

finishRecordingMacroBinding :: VimBinding
finishRecordingMacroBinding :: VimBinding
finishRecordingMacroBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
forall a.
(Eq a, IsString a) =>
a -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
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 :: Maybe (Char, EventString)
vsCurrentMacroRecording = Maybe (Char, EventString)
forall a. Maybe a
Nothing
                          , vsRegisterMap :: HashMap Char Register
vsRegisterMap = Char -> Register -> HashMap Char Register -> HashMap Char Register
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
insert Char
macroName Register
reg (VimState -> HashMap Char Register
vsRegisterMap VimState
s)
                          }
                      RepeatToken -> EditorM RepeatToken
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 ([Char] -> VimState -> MatchResult (EditorM RepeatToken)
f ([Char] -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> [Char])
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: [Char] -> VimState -> MatchResult (EditorM RepeatToken)
f [Char]
"@" (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 :: HashMap Char Register
vsRegisterMap = Char -> Register -> HashMap Char Register -> HashMap Char Register
forall k v.
(Eq k, Hashable k) =>
k -> v -> HashMap k v -> HashMap k v
insert Char
'@' Register
reg (VimState -> HashMap Char Register
vsRegisterMap VimState
s) }
                      RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Finish
                  Maybe Register
Nothing -> RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Drop
          f [Char]
_ 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