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

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

module Yi.Keymap.Vim.Utils
  ( mkBindingE
  , mkBindingY
  , mkStringBindingE
  , mkStringBindingY
  , splitCountedCommand
  , selectBinding
  , selectPureBinding
  , matchFromBool
  , mkMotionBinding
  , mkChooseRegisterBinding
  , pasteInclusiveB
  , addNewLineIfNecessary
  , indentBlockRegionB
  , addVimJumpHereE
  , exportRegisterToClipboard
  , pasteFromClipboard
  ) where

import           Lens.Micro.Platform               ((.=), use)
import           Control.Monad            (forM_, void, when)
import           Data.Char                (isSpace)
import           Data.Foldable            (asum)
import           Data.List                (group)
import qualified Data.Text                as T (unpack)
import           Safe                     (headDef)
import           Yi.Buffer                hiding (Insert)
import           Yi.Editor
import           Yi.Event                 (Event)
import           Yi.Keymap                (YiM)
import           Yi.Keymap.Vim.Common
import           Yi.Keymap.Vim.EventUtils (eventToEventString, splitCountedCommand)
import           Yi.Keymap.Vim.MatchResult
import           Yi.Keymap.Vim.Motion     (Move (Move), stringToMove)
import           Yi.Keymap.Vim.StateUtils (getMaybeCountE, modifyStateE,
                                           resetCountE, getRegisterE)
import           Yi.Monad                 (whenM)
import           Yi.Rope                  (YiString, countNewLines, last)
import qualified Yi.Rope                  as R (replicateChar, snoc, toString, fromString)
import           Yi.Utils                 (io)
import           System.Hclip             (getClipboard, setClipboard)

-- 'mkBindingE' and 'mkBindingY' are helper functions for bindings
-- where VimState mutation is not dependent on action performed
-- and prerequisite has form (mode == ... && event == ...)

mkStringBindingE :: VimMode -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState) -> VimBinding
mkStringBindingE :: VimMode
-> RepeatToken
-> (EventString, EditorM (), VimState -> VimState)
-> VimBinding
mkStringBindingE VimMode
mode RepeatToken
rtoken (EventString
eventString, EditorM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
_ VimState
vs | VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
/= VimMode
mode = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch
          f EventString
evs VimState
_ = EditorM ()
-> (VimState -> VimState) -> RepeatToken -> EditorM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction EditorM ()
action VimState -> VimState
mutate RepeatToken
rtoken EditorM RepeatToken
-> MatchResult () -> MatchResult (EditorM RepeatToken)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                    EventString
evs EventString -> EventString -> MatchResult ()
`matchesString` EventString
eventString

mkStringBindingY :: VimMode
    -> (EventString, YiM (), VimState -> VimState) -> VimBinding
mkStringBindingY :: VimMode
-> (EventString, YiM (), VimState -> VimState) -> VimBinding
mkStringBindingY VimMode
mode (EventString
eventString, YiM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (YiM RepeatToken))
-> VimBinding
VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (YiM RepeatToken)
f EventString
_ VimState
vs | VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
/= VimMode
mode = MatchResult (YiM RepeatToken)
forall a. MatchResult a
NoMatch
          f EventString
evs VimState
_ = YiM () -> (VimState -> VimState) -> RepeatToken -> YiM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction YiM ()
action VimState -> VimState
mutate RepeatToken
Drop YiM RepeatToken -> MatchResult () -> MatchResult (YiM RepeatToken)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                    EventString
evs EventString -> EventString -> MatchResult ()
`matchesString` EventString
eventString

mkBindingE :: VimMode -> RepeatToken -> (Event, EditorM (), VimState -> VimState) -> VimBinding
mkBindingE :: VimMode
-> RepeatToken
-> (Event, EditorM (), VimState -> VimState)
-> VimBinding
mkBindingE VimMode
mode RepeatToken
rtoken (Event
event, EditorM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs VimState
vs = EditorM ()
-> (VimState -> VimState) -> RepeatToken -> EditorM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction EditorM ()
action VimState -> VimState
mutate RepeatToken
rtoken EditorM RepeatToken
-> MatchResult () -> MatchResult (EditorM RepeatToken)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                     Bool -> MatchResult ()
matchFromBool (VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
== VimMode
mode Bool -> Bool -> Bool
&& EventString
evs EventString -> EventString -> Bool
forall a. Eq a => a -> a -> Bool
== Event -> EventString
eventToEventString Event
event)

mkBindingY :: VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
mkBindingY :: VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
mkBindingY VimMode
mode (Event
event, YiM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (YiM RepeatToken))
-> VimBinding
VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (YiM RepeatToken)
f EventString
evs VimState
vs = YiM () -> (VimState -> VimState) -> RepeatToken -> YiM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction YiM ()
action VimState -> VimState
mutate RepeatToken
Drop YiM RepeatToken -> MatchResult () -> MatchResult (YiM RepeatToken)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                     Bool -> MatchResult ()
matchFromBool (VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
== VimMode
mode Bool -> Bool -> Bool
&& EventString
evs EventString -> EventString -> Bool
forall a. Eq a => a -> a -> Bool
== Event -> EventString
eventToEventString Event
event)

combineAction :: MonadEditor m => m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction :: m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction m ()
action VimState -> VimState
mutateState RepeatToken
rtoken = do
    m ()
action
    EditorM () -> m ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> m ()) -> EditorM () -> m ()
forall a b. (a -> b) -> a -> b
$ (VimState -> VimState) -> EditorM ()
modifyStateE VimState -> VimState
mutateState
    RepeatToken -> m RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
rtoken

-- | All impure bindings will be ignored.
selectPureBinding :: EventString -> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding :: EventString
-> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding EventString
evs VimState
state = [MatchResult (EditorM RepeatToken)]
-> MatchResult (EditorM RepeatToken)
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([MatchResult (EditorM RepeatToken)]
 -> MatchResult (EditorM RepeatToken))
-> ([VimBinding] -> [MatchResult (EditorM RepeatToken)])
-> [VimBinding]
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VimBinding -> MatchResult (EditorM RepeatToken))
-> [VimBinding] -> [MatchResult (EditorM RepeatToken)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimBinding -> MatchResult (EditorM RepeatToken)
try
    where try :: VimBinding -> MatchResult (EditorM RepeatToken)
try (VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher) = EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher EventString
evs VimState
state
          try (VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
_) = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

selectBinding :: EventString -> VimState -> [VimBinding] -> MatchResult (YiM RepeatToken)
selectBinding :: EventString
-> VimState -> [VimBinding] -> MatchResult (YiM RepeatToken)
selectBinding EventString
input VimState
state = [MatchResult (YiM RepeatToken)] -> MatchResult (YiM RepeatToken)
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([MatchResult (YiM RepeatToken)] -> MatchResult (YiM RepeatToken))
-> ([VimBinding] -> [MatchResult (YiM RepeatToken)])
-> [VimBinding]
-> MatchResult (YiM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VimBinding -> MatchResult (YiM RepeatToken))
-> [VimBinding] -> [MatchResult (YiM RepeatToken)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimBinding -> MatchResult (YiM RepeatToken)
try
    where try :: VimBinding -> MatchResult (YiM RepeatToken)
try (VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
matcher) = EventString -> VimState -> MatchResult (YiM RepeatToken)
matcher EventString
input VimState
state
          try (VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher) = (EditorM RepeatToken -> YiM RepeatToken)
-> MatchResult (EditorM RepeatToken)
-> MatchResult (YiM RepeatToken)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap EditorM RepeatToken -> YiM RepeatToken
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (MatchResult (EditorM RepeatToken)
 -> MatchResult (YiM RepeatToken))
-> MatchResult (EditorM RepeatToken)
-> MatchResult (YiM RepeatToken)
forall a b. (a -> b) -> a -> b
$ EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher EventString
input VimState
state

setUnjumpMarks :: Point -> BufferM ()
setUnjumpMarks :: Point -> BufferM ()
setUnjumpMarks Point
p = do
    Point
solP <- Point -> BufferM Point
solPointB Point
p
    [(Point, Char)]
lineStream <- Direction -> Point -> BufferM [(Point, Char)]
indexedStreamB Direction
Forward Point
solP
    let fstNonBlank :: Point
fstNonBlank =
            Point -> [Point] -> Point
forall a. a -> [a] -> a
headDef Point
solP [ Point
p' | (Point
p', Char
ch) <- [(Point, Char)]
lineStream, Bool -> Bool
not (Char -> Bool
isSpace Char
ch) Bool -> Bool -> Bool
|| Char
ch Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n' ]
    (ASetter FBuffer FBuffer Point Point -> Point -> BufferM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Point
p)           (ASetter FBuffer FBuffer Point Point -> BufferM ())
-> (Mark -> ASetter FBuffer FBuffer Point Point)
-> Mark
-> BufferM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mark -> ASetter FBuffer FBuffer Point Point
Mark -> Lens' FBuffer Point
markPointA (Mark -> BufferM ()) -> BufferM Mark -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe String -> BufferM Mark
getMarkB (String -> Maybe String
forall a. a -> Maybe a
Just String
"`")
    (ASetter FBuffer FBuffer Point Point -> Point -> BufferM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Point
fstNonBlank) (ASetter FBuffer FBuffer Point Point -> BufferM ())
-> (Mark -> ASetter FBuffer FBuffer Point Point)
-> Mark
-> BufferM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mark -> ASetter FBuffer FBuffer Point Point
Mark -> Lens' FBuffer Point
markPointA (Mark -> BufferM ()) -> BufferM Mark -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe String -> BufferM Mark
getMarkB (String -> Maybe String
forall a. a -> Maybe a
Just String
"'")

addVimJumpAtE :: Point -> EditorM ()
addVimJumpAtE :: Point -> EditorM ()
addVimJumpAtE Point
p = do
    BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
setUnjumpMarks Point
p
    Point -> EditorM ()
addJumpAtE Point
p

addVimJumpHereE :: EditorM ()
addVimJumpHereE :: EditorM ()
addVimJumpHereE = do
    BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
setUnjumpMarks (Point -> BufferM ()) -> BufferM Point -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BufferM Point
pointB
    EditorM ()
addJumpHereE

mkMotionBinding :: RepeatToken -> (VimMode -> Bool) -> VimBinding
mkMotionBinding :: RepeatToken -> (VimMode -> Bool) -> VimBinding
mkMotionBinding RepeatToken
token VimMode -> Bool
condition = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
  where
    -- TODO: stringToMove and go both to EventString
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs VimState
state | VimMode -> Bool
condition (VimState -> VimMode
vsMode VimState
state) =
        (Move -> EditorM RepeatToken)
-> MatchResult Move -> MatchResult (EditorM RepeatToken)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Move -> EditorM RepeatToken
go (String -> Move -> EditorM RepeatToken)
-> (EventString -> String)
-> EventString
-> Move
-> EditorM RepeatToken
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv (EventString -> Move -> EditorM RepeatToken)
-> EventString -> Move -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ EventString
evs) (EventString -> MatchResult Move
stringToMove EventString
evs)
    f EventString
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

    go :: String -> Move -> EditorM RepeatToken
    go :: String -> Move -> EditorM RepeatToken
go String
evs (Move RegionStyle
_style Bool
isJump Maybe Int -> BufferM ()
move) = do
        Maybe Int
count <- EditorM (Maybe Int)
getMaybeCountE
        Point
prevPoint <- 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
            Point
p <- BufferM Point
pointB
            Maybe Int -> BufferM ()
move Maybe Int
count
            BufferM ()
leftOnEol
            Point -> BufferM Point
forall (m :: * -> *) a. Monad m => a -> m a
return Point
p
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isJump (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> EditorM ()
addVimJumpAtE Point
prevPoint
        EditorM ()
resetCountE

        Bool
sticky <- BufferM Bool -> EditorM Bool
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Bool -> EditorM Bool) -> BufferM Bool -> EditorM Bool
forall a b. (a -> b) -> a -> b
$ Getting Bool FBuffer Bool -> BufferM Bool
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting Bool FBuffer Bool
forall c. HasAttributes c => Lens' c Bool
stickyEolA

        -- moving with j/k after $ sticks cursor to the right edge
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
evs String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"$") (EditorM () -> EditorM ())
-> (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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
True
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
evs String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String -> [String]
forall a. Eq a => [a] -> [[a]]
group String
"jk" Bool -> Bool -> Bool
&& Bool
sticky) (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
$ BufferM ()
moveToEol BufferM () -> BufferM () -> BufferM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> BufferM ()
moveXorSol Int
1
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String
evs String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` String -> [String]
forall a. Eq a => [a] -> [[a]]
group String
"jk$") (EditorM () -> EditorM ())
-> (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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

        let m :: Char
m = String -> Char
forall a. [a] -> a
head String
evs
        Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Char
m Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (Char
'f' Char -> String -> String
forall a. a -> [a] -> [a]
: String
"FtT")) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
            let c :: Char
c = String -> Char
forall a. [a] -> a
Prelude.last String
evs
                (Direction
dir, RegionStyle
style) =
                    case Char
m of
                        Char
'f' -> (Direction
Forward, RegionStyle
Inclusive)
                        Char
't' -> (Direction
Forward, RegionStyle
Exclusive)
                        Char
'F' -> (Direction
Backward, RegionStyle
Inclusive)
                        Char
'T' -> (Direction
Backward, RegionStyle
Exclusive)
                        Char
_ -> String -> (Direction, RegionStyle)
forall a. HasCallStack => String -> a
error String
"can't happen"
                command :: GotoCharCommand
command = Char -> Direction -> RegionStyle -> GotoCharCommand
GotoCharCommand Char
c Direction
dir RegionStyle
style
            (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s -> VimState
s { vsLastGotoCharCommand :: Maybe GotoCharCommand
vsLastGotoCharCommand = GotoCharCommand -> Maybe GotoCharCommand
forall a. a -> Maybe a
Just GotoCharCommand
command}

        RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
token

mkChooseRegisterBinding :: (VimState -> Bool) -> VimBinding
mkChooseRegisterBinding :: (VimState -> Bool) -> VimBinding
mkChooseRegisterBinding VimState -> Bool
statePredicate = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
f (String -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> String)
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
f String
"\"" VimState
s | VimState -> Bool
statePredicate VimState
s = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
PartialMatch
          f [Char
'"', Char
c] VimState
s | VimState -> Bool
statePredicate VimState
s = 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' { vsActiveRegister :: Char
vsActiveRegister = Char
c }
              RepeatToken -> EditorM RepeatToken
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
          f String
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

indentBlockRegionB :: Int -> Region -> BufferM ()
indentBlockRegionB :: Int -> Region -> BufferM ()
indentBlockRegionB Int
count Region
reg = do
  IndentSettings
indentSettings <- BufferM IndentSettings
indentSettingsB
  (Point
start, [Int]
lengths) <- Region -> BufferM (Point, [Int])
shapeOfBlockRegionB Region
reg
  Point -> BufferM ()
moveTo Point
start
  [(Int, Int)] -> ((Int, Int) -> BufferM ()) -> BufferM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ([Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] [Int]
lengths) (((Int, Int) -> BufferM ()) -> BufferM ())
-> ((Int, Int) -> BufferM ()) -> BufferM ()
forall a b. (a -> b) -> a -> b
$ \(Int
i, Int
_) -> do
      BufferM Bool -> BufferM () -> BufferM ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (Bool -> Bool
not (Bool -> Bool) -> BufferM Bool -> BufferM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferM Bool
atEol) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ do
        let w :: Int
w = IndentSettings -> Int
shiftWidth IndentSettings
indentSettings
        if Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
        then YiString -> BufferM ()
insertN (YiString -> BufferM ()) -> YiString -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> Char -> YiString
R.replicateChar (Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w) Char
' '
        else Int -> BufferM ()
forall t. (Eq t, Num t) => t -> BufferM ()
go (Int -> Int
forall a. Num a => a -> a
abs Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w)
      Point -> BufferM ()
moveTo Point
start
      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
i
  Point -> BufferM ()
moveTo Point
start
  where
      go :: t -> BufferM ()
go t
0 = () -> BufferM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      go t
n = do
          Char
c <- BufferM Char
readB
          Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ') (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$
              Int -> BufferM ()
deleteN Int
1 BufferM () -> BufferM () -> BufferM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> t -> BufferM ()
go (t
n t -> t -> t
forall a. Num a => a -> a -> a
- t
1)


pasteInclusiveB :: YiString -> RegionStyle -> BufferM ()
pasteInclusiveB :: YiString -> RegionStyle -> BufferM ()
pasteInclusiveB YiString
rope RegionStyle
style = do
  Point
p0 <- BufferM Point
pointB
  YiString -> RegionStyle -> BufferM ()
insertRopeWithStyleB YiString
rope RegionStyle
style
  if YiString -> Int
countNewLines YiString
rope Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 Bool -> Bool -> Bool
&& RegionStyle
style RegionStyle -> [RegionStyle] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ RegionStyle
Exclusive, RegionStyle
Inclusive ]
    then BufferM ()
leftB
    else Point -> BufferM ()
moveTo Point
p0

trailingNewline :: YiString -> Bool
trailingNewline :: YiString -> Bool
trailingNewline YiString
t = case YiString -> Maybe Char
Yi.Rope.last YiString
t of
  Just Char
'\n' -> Bool
True
  Maybe Char
_         -> Bool
False

addNewLineIfNecessary :: YiString -> YiString
addNewLineIfNecessary :: YiString -> YiString
addNewLineIfNecessary YiString
rope =
  if YiString -> Bool
trailingNewline YiString
rope then YiString
rope else YiString
rope YiString -> Char -> YiString
`R.snoc` Char
'\n'

pasteFromClipboard :: YiM ()
pasteFromClipboard :: YiM ()
pasteFromClipboard = do
  YiString
text <- (String -> YiString) -> YiM String -> YiM YiString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> YiString
R.fromString (YiM String -> YiM YiString) -> YiM String -> YiM YiString
forall a b. (a -> b) -> a -> b
$ IO String -> YiM String
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io IO String
getClipboard
  BufferM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> YiM ()) -> BufferM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ YiString -> RegionStyle -> BufferM ()
insertRopeWithStyleB YiString
text RegionStyle
Inclusive

exportRegisterToClipboard :: RegisterName -> YiM ()
exportRegisterToClipboard :: Char -> YiM ()
exportRegisterToClipboard Char
name = do
  Maybe Register
mbr <- EditorM (Maybe Register) -> YiM (Maybe Register)
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM (Maybe Register) -> YiM (Maybe Register))
-> EditorM (Maybe Register) -> YiM (Maybe Register)
forall a b. (a -> b) -> a -> b
$ Char -> EditorM (Maybe Register)
getRegisterE Char
name
  IO () -> YiM ()
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io (IO () -> YiM ()) -> (String -> IO ()) -> String -> YiM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ()
setClipboard (String -> YiM ()) -> String -> YiM ()
forall a b. (a -> b) -> a -> b
$ String -> (Register -> String) -> Maybe Register -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" (YiString -> String
R.toString (YiString -> String)
-> (Register -> YiString) -> Register -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Register -> YiString
regContent) Maybe Register
mbr