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

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

module Yi.Keymap.Vim.InsertMap (defInsertMap) where

import           Prelude                  hiding (head)

import           Lens.Micro.Platform               (use)
import           Control.Monad            (forM, liftM2, replicateM_, void, when)
import           Data.Char                (isDigit)
import           Data.List.NonEmpty       (NonEmpty (..), head, toList)
import           Data.Monoid              ((<>))
import qualified Data.Text                as T (pack, unpack)
import qualified Yi.Buffer                as B (bdeleteB, deleteB, deleteRegionB, insertB, insertN)
import           Yi.Buffer                as BA hiding (Insert)
import           Yi.Editor                (EditorM, getEditorDyn, withCurrentBuffer)
import           Yi.Event                 (Event)
import           Yi.Keymap.Vim.Common
import           Yi.Keymap.Vim.Digraph    (charFromDigraph, DigraphTbl)
import           Yi.Keymap.Vim.EventUtils (eventToEventString, parseEvents)
import           Yi.Keymap.Vim.Motion     (Move (Move), stringToMove)
import           Yi.Keymap.Vim.StateUtils
import           Yi.Keymap.Vim.Utils      (selectBinding, selectPureBinding)
import           Yi.Monad                 (whenM)
import qualified Yi.Rope                  as R (fromString, fromText)
import           Yi.TextCompletion        (CompletionScope (..), completeWordB)

defInsertMap :: DigraphTbl -> [VimBinding]
defInsertMap :: DigraphTbl -> [VimBinding]
defInsertMap DigraphTbl
digraphs =
    [VimBinding
rawPrintable] [VimBinding] -> [VimBinding] -> [VimBinding]
forall a. Semigroup a => a -> a -> a
<> DigraphTbl -> [VimBinding]
specials DigraphTbl
digraphs [VimBinding] -> [VimBinding] -> [VimBinding]
forall a. Semigroup a => a -> a -> a
<> [VimBinding
printable]

specials :: DigraphTbl -> [VimBinding]
specials :: DigraphTbl -> [VimBinding]
specials DigraphTbl
digraphs =
    [DigraphTbl -> VimBinding
exitBinding DigraphTbl
digraphs, VimBinding
pasteRegisterBinding, DigraphTbl -> VimBinding
digraphBinding DigraphTbl
digraphs
    , VimBinding
oneshotNormalBinding, VimBinding
completionBinding, VimBinding
cursorBinding]

exitBinding :: DigraphTbl -> VimBinding
exitBinding :: DigraphTbl -> VimBinding
exitBinding DigraphTbl
digraphs = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
  where
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs (VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_) })
      | EventString
evs EventString -> [EventString] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [EventString
"<Esc>", EventString
"<C-c>"]
      = 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
        (Insert Char
starter) <- (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
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
            [Event]
inputEvents <- (VimState -> [Event]) -> EditorM VimState -> EditorM [Event]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (EventString -> [Event]
parseEvents (EventString -> [Event])
-> (VimState -> EventString) -> VimState -> [Event]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. VimState -> EventString
vsOngoingInsertEvents) EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
            Int -> EditorM () -> EditorM ()
forall (m :: * -> *) a. Applicative m => Int -> m a -> m ()
replicateM_ (Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
                Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Char
starter Char -> [Char] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'O', Char
'o']) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Char -> BufferM ()
insertB Char
'\n'
                DigraphTbl -> [Event] -> EditorM ()
replay DigraphTbl
digraphs [Event]
inputEvents
        (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsOngoingInsertEvents :: EventString
vsOngoingInsertEvents = EventString
forall a. Monoid a => a
mempty }
        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 ()
moveXorSol Int
1
        (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsSecondaryCursors :: [Point]
vsSecondaryCursors = [Point]
forall a. Monoid a => a
mempty }
        EditorM ()
resetCountE
        VimMode -> EditorM ()
switchModeE VimMode
Normal
        BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ BufferM Bool -> BufferM () -> BufferM ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM BufferM Bool
isCurrentLineAllWhiteSpaceB (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ BufferM ()
moveToSol BufferM () -> BufferM () -> BufferM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BufferM ()
deleteToEol
        RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Finish
    f EventString
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

rawPrintable :: VimBinding
rawPrintable :: VimBinding
rawPrintable = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
  where
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs s :: VimState
s@(VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_)})
          | VimState -> Bool
vsPaste VimState
s Bool -> Bool -> Bool
&& EventString
evs EventString -> [EventString] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [EventString
"<Esc>", EventString
"<C-c>"]
              = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
forall a. a -> MatchResult a
WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
-> (BufferM RepeatToken -> EditorM RepeatToken)
-> BufferM RepeatToken
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BufferM RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM RepeatToken -> MatchResult (EditorM RepeatToken))
-> BufferM RepeatToken -> MatchResult (EditorM RepeatToken)
forall a b. (a -> b) -> a -> b
$ do
            case EventString
evs of
              EventString
"<lt>"       -> Char -> BufferM ()
insertB Char
'<'
              EventString
"<CR>"       -> BufferM ()
newlineB
              EventString
"<Tab>"      -> Char -> BufferM ()
insertB Char
'\t'
              EventString
"<BS>"       -> BufferM ()
bdeleteB
              EventString
"<C-h>"      -> BufferM ()
bdeleteB
              EventString
"<Del>"      -> TextUnit -> Direction -> BufferM ()
deleteB TextUnit
Character Direction
Forward
              EventString
"<Home>"     -> BufferM ()
moveToSol
              EventString
"<End>"      -> BufferM ()
moveToEol
              EventString
"<PageUp>"   -> Int -> BufferM ()
scrollScreensB (-Int
1)
              EventString
"<PageDown>" -> Int -> BufferM ()
scrollScreensB   Int
1
              EventString
c -> YiString -> BufferM ()
insertN (Text -> YiString
R.fromText (Text -> YiString) -> Text -> YiString
forall a b. (a -> b) -> a -> b
$ EventString -> Text
_unEv EventString
c)
            RepeatToken -> BufferM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
    f EventString
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

replay :: DigraphTbl -> [Event] -> EditorM ()
replay :: DigraphTbl -> [Event] -> EditorM ()
replay DigraphTbl
_ [] = () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
replay DigraphTbl
digraphs (Event
e1:[Event]
es1) = do
    VimState
state <- EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
    let recurse :: [Event] -> EditorM ()
recurse = DigraphTbl -> [Event] -> EditorM ()
replay DigraphTbl
digraphs
        evs1 :: EventString
evs1 = Event -> EventString
eventToEventString Event
e1
        bindingMatch1 :: MatchResult (EditorM RepeatToken)
bindingMatch1 = EventString
-> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding EventString
evs1 VimState
state (DigraphTbl -> [VimBinding]
defInsertMap DigraphTbl
digraphs)
    case MatchResult (EditorM RepeatToken)
bindingMatch1 of
        WholeMatch EditorM RepeatToken
action -> EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void EditorM RepeatToken
action EditorM () -> EditorM () -> EditorM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Event] -> EditorM ()
recurse [Event]
es1
        MatchResult (EditorM RepeatToken)
PartialMatch -> case [Event]
es1 of
            [] -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            (Event
e2:[Event]
es2) -> do
                let evs2 :: EventString
evs2 = EventString
evs1 EventString -> EventString -> EventString
forall a. Semigroup a => a -> a -> a
<> Event -> EventString
eventToEventString Event
e2
                    bindingMatch2 :: MatchResult (EditorM RepeatToken)
bindingMatch2 = EventString
-> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding EventString
evs2 VimState
state (DigraphTbl -> [VimBinding]
defInsertMap DigraphTbl
digraphs)
                case MatchResult (EditorM RepeatToken)
bindingMatch2 of
                    WholeMatch EditorM RepeatToken
action -> EditorM RepeatToken -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void EditorM RepeatToken
action EditorM () -> EditorM () -> EditorM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Event] -> EditorM ()
recurse [Event]
es2
                    MatchResult (EditorM RepeatToken)
_ -> [Event] -> EditorM ()
recurse [Event]
es2
        MatchResult (EditorM RepeatToken)
_ -> [Event] -> EditorM ()
recurse [Event]
es1

oneshotNormalBinding :: VimBinding
oneshotNormalBinding :: VimBinding
oneshotNormalBinding = (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]
"<C-o>" (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ }) = MatchResult (m RepeatToken)
forall a. MatchResult a
PartialMatch
    f (Char
'<':Char
'C':Char
'-':Char
'o':Char
'>':[Char]
evs) (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ }) =
        [Char] -> m RepeatToken
forall (m :: * -> *). MonadEditor m => [Char] -> m RepeatToken
action [Char]
evs m RepeatToken -> MatchResult Move -> MatchResult (m RepeatToken)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ EventString -> MatchResult Move
stringToMove (Text -> EventString
Ev (Text -> EventString) -> ([Char] -> Text) -> [Char] -> EventString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack ([Char] -> EventString) -> [Char] -> EventString
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isDigit [Char]
evs)
    f [Char]
_ VimState
_ = MatchResult (m RepeatToken)
forall a. MatchResult a
NoMatch
    action :: [Char] -> m RepeatToken
action [Char]
evs = do
        let ([Char]
countString, [Char]
motionCmd) = (Char -> Bool) -> [Char] -> ([Char], [Char])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit [Char]
evs
            WholeMatch (Move RegionStyle
_style Bool
_isJump Maybe Int -> BufferM ()
move) = EventString -> MatchResult Move
stringToMove (EventString -> MatchResult Move)
-> ([Char] -> EventString) -> [Char] -> MatchResult Move
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> EventString
Ev (Text -> EventString) -> ([Char] -> Text) -> [Char] -> EventString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Text
T.pack ([Char] -> MatchResult Move) -> [Char] -> MatchResult Move
forall a b. (a -> b) -> a -> b
$ [Char]
motionCmd
        BufferM () -> m ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> m ()) -> BufferM () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe Int -> BufferM ()
move (if [Char] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
countString then Maybe Int
forall a. Maybe a
Nothing else Int -> Maybe Int
forall a. a -> Maybe a
Just ([Char] -> Int
forall a. Read a => [Char] -> a
read [Char]
countString))
        RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue

pasteRegisterBinding :: VimBinding
pasteRegisterBinding :: VimBinding
pasteRegisterBinding = (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]
"<C-r>" (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ }) = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
PartialMatch
          f (Char
'<':Char
'C':Char
'-':Char
'r':Char
'>':Char
regName:[]) (VimState { vsMode :: VimState -> VimMode
vsMode = Insert 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
                  Maybe Register
mr <- Char -> EditorM (Maybe Register)
getRegisterE Char
regName
                  case Maybe Register
mr of
                    Maybe Register
Nothing -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                    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 ()
insertRopeWithStyleB YiString
rope RegionStyle
Inclusive
                  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

digraphBinding :: DigraphTbl -> VimBinding
digraphBinding :: DigraphTbl -> VimBinding
digraphBinding DigraphTbl
digraphs = (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
'<':Char
'C':Char
'-':Char
'k':Char
'>':Char
c1:Char
c2:[]) (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ })
            = 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
                  m () -> (Char -> m ()) -> Maybe Char -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (BufferM () -> m ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> m ()) -> (Char -> BufferM ()) -> Char -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> BufferM ()
insertB) (Maybe Char -> m ()) -> Maybe Char -> m ()
forall a b. (a -> b) -> a -> b
$ DigraphTbl -> Char -> Char -> Maybe Char
charFromDigraph DigraphTbl
digraphs Char
c1 Char
c2
                  RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
          f (Char
'<':Char
'C':Char
'-':Char
'k':Char
'>':Char
_c1:[]) (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ }) = MatchResult (m RepeatToken)
forall a. MatchResult a
PartialMatch
          f [Char]
"<C-k>" (VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ }) = MatchResult (m RepeatToken)
forall a. MatchResult a
PartialMatch
          f [Char]
_ VimState
_ = MatchResult (m RepeatToken)
forall a. MatchResult a
NoMatch

printable :: VimBinding
printable :: VimBinding
printable = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs state :: VimState
state@(VimState { vsMode :: VimState -> VimMode
vsMode = Insert Char
_ } ) =
              case EventString
-> VimState -> [VimBinding] -> MatchResult (YiM RepeatToken)
selectBinding EventString
evs VimState
state (DigraphTbl -> [VimBinding]
specials DigraphTbl
forall a. HasCallStack => a
undefined) of
                  MatchResult (YiM RepeatToken)
NoMatch -> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
forall a. a -> MatchResult a
WholeMatch (EventString -> EditorM RepeatToken
printableAction EventString
evs)
                  MatchResult (YiM RepeatToken)
_ -> MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch
          f EventString
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

printableAction :: EventString -> EditorM RepeatToken
printableAction :: EventString -> EditorM RepeatToken
printableAction EventString
evs = do
    EventString -> EditorM ()
saveInsertEventStringE EventString
evs
    Point
currentCursor <- BufferM Point -> EditorM Point
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Point
pointB
    IndentSettings Bool
et Int
_ Int
sw <- BufferM IndentSettings -> EditorM IndentSettings
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM IndentSettings
indentSettingsB
    [Point]
secondaryCursors <- (VimState -> [Point]) -> EditorM VimState -> EditorM [Point]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimState -> [Point]
vsSecondaryCursors EditorM VimState
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
    let allCursors :: NonEmpty Point
allCursors = Point
currentCursor Point -> [Point] -> NonEmpty Point
forall a. a -> [a] -> NonEmpty a
:| [Point]
secondaryCursors
    NonEmpty Mark
marks <- BufferM (NonEmpty Mark) -> EditorM (NonEmpty Mark)
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM (NonEmpty Mark) -> EditorM (NonEmpty Mark))
-> BufferM (NonEmpty Mark) -> EditorM (NonEmpty Mark)
forall a b. (a -> b) -> a -> b
$ NonEmpty Point
-> (Point -> BufferM Mark) -> BufferM (NonEmpty Mark)
forall (m :: * -> *) a b.
Monad m =>
NonEmpty a -> (a -> m b) -> m (NonEmpty b)
forM' NonEmpty Point
allCursors ((Point -> BufferM Mark) -> BufferM (NonEmpty Mark))
-> (Point -> BufferM Mark) -> BufferM (NonEmpty Mark)
forall a b. (a -> b) -> a -> b
$ \Point
cursor -> do
        Point -> BufferM ()
moveTo Point
cursor
        Maybe [Char] -> BufferM Mark
getMarkB Maybe [Char]
forall a. Maybe a
Nothing

    -- Using autoindenting with multiple cursors
    -- is just too broken.
    let (Char -> BufferM ()
insertB', YiString -> BufferM ()
insertN', TextUnit -> Direction -> BufferM ()
deleteB', BufferM ()
bdeleteB', Region -> BufferM ()
deleteRegionB') =
            if [Point] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Point]
secondaryCursors
            then (Char -> BufferM ()
BA.insertB, YiString -> BufferM ()
BA.insertN, TextUnit -> Direction -> BufferM ()
BA.deleteB,
                BufferM ()
BA.bdeleteB, Region -> BufferM ()
BA.deleteRegionB)
            else (Char -> BufferM ()
B.insertB, YiString -> BufferM ()
B.insertN, TextUnit -> Direction -> BufferM ()
B.deleteB,
                BufferM ()
B.bdeleteB, Region -> BufferM ()
B.deleteRegionB)

    let bufAction :: BufferM ()
bufAction = case Text -> [Char]
T.unpack (Text -> [Char]) -> (EventString -> Text) -> EventString -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv (EventString -> [Char]) -> EventString -> [Char]
forall a b. (a -> b) -> a -> b
$ EventString
evs of
          (Char
c:[]) -> Char -> BufferM ()
insertB' Char
c
          [Char]
"<CR>" -> do
              Bool
isOldLineEmpty <- BufferM Bool
isCurrentLineEmptyB
              Bool
shouldTrimOldLine <- BufferM Bool
isCurrentLineAllWhiteSpaceB
              if Bool
isOldLineEmpty
              then BufferM ()
newlineB
              else if Bool
shouldTrimOldLine
              then BufferM () -> BufferM ()
forall a. BufferM a -> BufferM a
savingPointB (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ do
                  BufferM ()
moveToSol
                  BufferM ()
newlineB
              else do
                  BufferM ()
newlineB
                  BufferM ()
indentAsTheMostIndentedNeighborLineB
              BufferM ()
firstNonSpaceB
          [Char]
"<Tab>" -> do
              if Bool
et
              then YiString -> BufferM ()
insertN' (YiString -> BufferM ())
-> ([Char] -> YiString) -> [Char] -> BufferM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> YiString
R.fromString ([Char] -> BufferM ()) -> [Char] -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> Char -> [Char]
forall a. Int -> a -> [a]
replicate Int
sw Char
' '
              else Char -> BufferM ()
insertB' Char
'\t'
          [Char]
"<C-t>"      -> (Int -> Int) -> BufferM ()
modifyIndentB (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
sw)
          [Char]
"<C-d>"      -> (Int -> Int) -> BufferM ()
modifyIndentB (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 (Int -> Int) -> (Int -> Int) -> Int -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Int
forall a. Num a => a -> a -> a
subtract Int
sw)
          [Char]
"<C-e>"      -> BufferM ()
insertCharWithBelowB
          [Char]
"<C-y>"      -> BufferM ()
insertCharWithAboveB
          [Char]
"<BS>"       -> BufferM ()
bdeleteB'
          [Char]
"<C-h>"      -> BufferM ()
bdeleteB'
          [Char]
"<Home>"     -> BufferM ()
moveToSol
          [Char]
"<End>"      -> BufferM ()
moveToEol BufferM () -> BufferM () -> BufferM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BufferM ()
leftOnEol
          [Char]
"<PageUp>"   -> Int -> BufferM ()
scrollScreensB (-Int
1)
          [Char]
"<PageDown>" -> Int -> BufferM ()
scrollScreensB   Int
1
          [Char]
"<Del>"      -> TextUnit -> Direction -> BufferM ()
deleteB' TextUnit
Character Direction
Forward
          [Char]
"<C-w>"      -> Region -> BufferM ()
deleteRegionB' (Region -> BufferM ()) -> BufferM Region -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< TextUnit -> Direction -> BufferM Region
regionOfPartNonEmptyB TextUnit
unitViWordOnLine Direction
Backward
          [Char]
"<C-u>"      -> BufferM ()
bdeleteLineB
          [Char]
"<lt>"       -> Char -> BufferM ()
insertB' Char
'<'
          [Char]
evs'         -> [Char] -> BufferM ()
forall a. HasCallStack => [Char] -> a
error ([Char] -> BufferM ()) -> [Char] -> BufferM ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Unhandled event " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
evs' [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" in insert mode"

    [Point]
updatedCursors <- BufferM [Point] -> EditorM [Point]
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM [Point] -> EditorM [Point])
-> BufferM [Point] -> EditorM [Point]
forall a b. (a -> b) -> a -> b
$ do
        NonEmpty Point
updatedCursors <- NonEmpty Mark
-> (Mark -> BufferM Point) -> BufferM (NonEmpty Point)
forall (m :: * -> *) a b.
Monad m =>
NonEmpty a -> (a -> m b) -> m (NonEmpty b)
forM' NonEmpty Mark
marks ((Mark -> BufferM Point) -> BufferM (NonEmpty Point))
-> (Mark -> BufferM Point) -> BufferM (NonEmpty Point)
forall a b. (a -> b) -> a -> b
$ \Mark
mark -> do
            Point -> BufferM ()
moveTo (Point -> BufferM ()) -> BufferM Point -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Getting Point FBuffer Point -> BufferM Point
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Mark -> Lens' FBuffer Point
markPointA Mark
mark)
            BufferM ()
bufAction
            BufferM Point
pointB
        (Mark -> BufferM ()) -> [Mark] -> BufferM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Mark -> BufferM ()
deleteMarkB ([Mark] -> BufferM ()) -> [Mark] -> BufferM ()
forall a b. (a -> b) -> a -> b
$ NonEmpty Mark -> [Mark]
forall a. NonEmpty a -> [a]
toList NonEmpty Mark
marks
        Point -> BufferM ()
moveTo (Point -> BufferM ()) -> Point -> BufferM ()
forall a b. (a -> b) -> a -> b
$ NonEmpty Point -> Point
forall a. NonEmpty a -> a
head NonEmpty Point
updatedCursors
        [Point] -> BufferM [Point]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Point] -> BufferM [Point]) -> [Point] -> BufferM [Point]
forall a b. (a -> b) -> a -> b
$ NonEmpty Point -> [Point]
forall a. NonEmpty a -> [a]
toList NonEmpty Point
updatedCursors
    (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsSecondaryCursors :: [Point]
vsSecondaryCursors = Int -> [Point] -> [Point]
forall a. Int -> [a] -> [a]
drop Int
1 [Point]
updatedCursors }
    RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
  where
    forM' :: Monad m => NonEmpty a -> (a -> m b) -> m (NonEmpty b)
    forM' :: NonEmpty a -> (a -> m b) -> m (NonEmpty b)
forM' (a
x :| [a]
xs) a -> m b
f = (b -> [b] -> NonEmpty b) -> m b -> m [b] -> m (NonEmpty b)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 b -> [b] -> NonEmpty b
forall a. a -> [a] -> NonEmpty a
(:|) (a -> m b
f a
x) ([a] -> (a -> m b) -> m [b]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [a]
xs a -> m b
f)

completionBinding :: VimBinding
completionBinding :: VimBinding
completionBinding = (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
evs (VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_) })
            | a
evs a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [a
"<C-n>", a
"<C-p>"]
            = 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 _direction :: Direction
_direction = if a
evs a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
"<C-n>" then Direction
Forward else Direction
Backward
                  CompletionScope -> EditorM ()
completeWordB CompletionScope
FromAllBuffers
                  RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
          f a
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

cursorBinding :: VimBinding
cursorBinding :: VimBinding
cursorBinding = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
forall (m :: * -> *).
MonadEditor m =>
EventString -> VimState -> MatchResult (m RepeatToken)
f
    where
    f :: EventString -> VimState -> MatchResult (m RepeatToken)
f EventString
"<C-b>" (VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_) })
        = 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
$ Int -> BufferM ()
moveXorSol Int
1
            RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
    f EventString
"<C-f>" (VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_) })
        = 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
$ Int -> BufferM ()
moveXorEol Int
1
            RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
    f EventString
evs (VimState { vsMode :: VimState -> VimMode
vsMode = (Insert Char
_) })
        | EventString
evs EventString -> [EventString] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [EventString
"<Up>", EventString
"<Left>", EventString
"<Down>", EventString
"<Right>"]
        = 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
              let WholeMatch (Move RegionStyle
_style Bool
_isJump Maybe Int -> BufferM ()
move) = EventString -> MatchResult Move
stringToMove EventString
evs
              BufferM () -> m ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> m ()) -> BufferM () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe Int -> BufferM ()
move Maybe Int
forall a. Maybe a
Nothing
              RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
    f EventString
_ VimState
_ = MatchResult (m RepeatToken)
forall a. MatchResult a
NoMatch