Skip to content

Commit 153d062

Browse files
author
Jaro Reinders
committed
Merge branch 'visual-block-paste' of https://github.com/stites/yi
2 parents 9dfe0e8 + 96cfb06 commit 153d062

File tree

9 files changed

+198
-29
lines changed

9 files changed

+198
-29
lines changed

yi-keymap-vim/src/Yi/Keymap/Vim/VisualMap.hs

+62-29
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
module Yi.Keymap.Vim.VisualMap ( defVisualMap ) where
1515

16-
import Lens.Micro.Platform ((.=))
17-
import Control.Monad (forM_, void)
16+
import Lens.Micro.Platform ((.=))
17+
import Control.Monad (forM_, void, when)
1818
import Data.Char (ord)
1919
import Data.List (group)
2020
import Data.Maybe (fromJust, fromMaybe)
@@ -27,10 +27,10 @@ import Yi.Keymap.Vim.StateUtils
2727
import Yi.Keymap.Vim.StyledRegion (StyledRegion (StyledRegion), transformCharactersInRegionB)
2828
import Yi.Keymap.Vim.Tag (gotoTag)
2929
import Yi.Keymap.Vim.TextObject
30-
import Yi.Keymap.Vim.Utils (matchFromBool, mkChooseRegisterBinding, mkMotionBinding, addNewLineIfNecessary)
30+
import Yi.Keymap.Vim.Utils (matchFromBool, mkChooseRegisterBinding, mkMotionBinding, addNewLineIfNecessary, pasteInclusiveB)
3131
import Yi.MiniBuffer (spawnMinibufferE)
3232
import Yi.Monad (whenM)
33-
import qualified Yi.Rope as R (toText)
33+
import qualified Yi.Rope as R (toText, countNewLines)
3434
import Yi.Tag (Tag (Tag))
3535
import Yi.Utils (SemiNum ((-~)))
3636

@@ -230,39 +230,72 @@ replaceBinding = VimBindingE (f . T.unpack . _unEv)
230230
region <- withCurrentBuffer regionOfSelectionB
231231
withCurrentBuffer $ transformCharactersInRegionB (StyledRegion style region)
232232
(\x -> if x == '\n' then x else c)
233-
escAction
233+
void escAction
234234
return Finish
235235
_ -> NoMatch
236236
f _ _ = NoMatch
237237

238+
239+
data VisualPaste
240+
= PasteBefore
241+
| ReplaceSelection
242+
deriving (Eq, Ord, Show)
243+
238244
pasteBinding :: VimBinding
239245
pasteBinding = VimBindingE (f . T.unpack . _unEv)
240246
where
241-
f "p" (VimState { vsMode = (Visual style) }) = WholeMatch $ do
247+
f "P" VimState { vsMode = (Visual style) } = pasteMatch style PasteBefore
248+
f "p" VimState { vsMode = (Visual style) } = pasteMatch style ReplaceSelection
249+
f _ _ = NoMatch
250+
251+
pasteMatch :: RegionStyle -> VisualPaste -> MatchResult (EditorM RepeatToken)
252+
pasteMatch style p = WholeMatch $ do
242253
register <- getRegisterE . vsActiveRegister =<< getEditorDyn
243-
case (register, style) of
244-
(Just (Register _style rope), LineWise) -> withCurrentBuffer $ do
245-
region <- regionOfSelectionB
246-
_ <- deleteRegionWithStyleB region LineWise
247-
insertRopeWithStyleB (addNewLineIfNecessary rope) LineWise
248-
(Just (Register Block rope), Block) -> withCurrentBuffer $ do
249-
here <- pointB
250-
there <- getSelectionMarkPointB
251-
(here', there') <- flipRectangleB here there
252-
reg <- regionOfSelectionB
253-
void $ deleteRegionWithStyleB reg Block
254-
moveTo (minimum [here, there, here', there'])
255-
insertRopeWithStyleB rope Block
256-
(Just (Register _ _), Block) ->
257-
printMsg "Pasting non-block string into a block selection is not implemented"
258-
(Just (Register _style rope), _) -> withCurrentBuffer $ do
259-
region <- regionOfSelectionB
260-
region' <- convertRegionToStyleB region Inclusive
261-
replaceRegionB region' rope
262-
_ -> pure ()
263-
escAction
254+
maybe (pure ()) (paste style p) register
255+
void escAction
264256
return Finish
265-
f _ _ = NoMatch
257+
258+
paste :: RegionStyle -> VisualPaste -> Register -> EditorM ()
259+
paste LineWise = linePaste
260+
paste Block = blockPaste
261+
paste Inclusive = otherPaste
262+
paste Exclusive = otherPaste
263+
264+
linePaste :: VisualPaste -> Register -> EditorM ()
265+
linePaste p (Register _style rope) = withCurrentBuffer $ do
266+
region <- regionOfSelectionB
267+
when (p == ReplaceSelection) . void $ deleteRegionWithStyleB region LineWise
268+
insertRopeWithStyleB (addNewLineIfNecessary rope) LineWise
269+
270+
blockPaste :: VisualPaste -> Register -> EditorM ()
271+
blockPaste p (Register _style rope) = withCurrentBuffer $ do
272+
here <- pointB
273+
there <- getSelectionMarkPointB
274+
(here', there') <- flipRectangleB here there
275+
reg <- regionOfSelectionB
276+
moveTo (minimum [here, there, here', there'])
277+
when (p == ReplaceSelection) . void $ deleteRegionWithStyleB reg Block
278+
if R.countNewLines rope == 0
279+
then actionOnLeft reg $ maybe (pure ()) (\_ -> insertRopeWithStyleB rope _style)
280+
else pasteInclusiveB rope _style
281+
where
282+
-- Taken from deleteRegionWithStyleB
283+
actionOnLeft :: Region -> (Maybe Point -> BufferM ()) -> BufferM ()
284+
actionOnLeft reg action = savingPointB $ do
285+
(start, lengths) <- shapeOfBlockRegionB reg
286+
moveTo start
287+
forM_ (zip [0..] lengths) $ \(i, l) -> do
288+
p' <- pointB
289+
moveTo start
290+
void $ lineMoveRel i
291+
action (if l == 0 then Nothing else Just p')
292+
293+
otherPaste :: VisualPaste -> Register -> EditorM ()
294+
otherPaste _ (Register _style rope) = withCurrentBuffer $ do
295+
region <- regionOfSelectionB
296+
region' <- convertRegionToStyleB region Inclusive
297+
replaceRegionB region' rope
298+
266299

267300
switchEdgeBinding :: VimBinding
268301
switchEdgeBinding = VimBindingE (f . T.unpack . _unEv)
@@ -305,7 +338,7 @@ tagJumpBinding = VimBindingY (f . T.unpack . _unEv)
305338
= WholeMatch $ do
306339
tag <- Tag . R.toText <$> withCurrentBuffer
307340
(regionOfSelectionB >>= readRegionB)
308-
withEditor escAction
341+
void $ withEditor escAction
309342
gotoTag tag 0 Nothing
310343
return Finish
311344
f _ _ = NoMatch
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Input
2+
(1,1)
3+
foo
4+
bar
5+
6+
baz
7+
-- Output
8+
(1,1)
9+
foofoo
10+
foobar
11+
12+
foobaz
13+
-- Events
14+
yw<C-v>jjjP<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Input
2+
(4,1)
3+
123456
4+
123456
5+
123456
6+
foo
7+
bar
8+
9+
baz
10+
-- Output
11+
(1,1)
12+
foo123456
13+
bar123456
14+
123456
15+
bazfoo
16+
bar
17+
18+
baz
19+
-- Events
20+
<C-v>jjjey<C-v>kkkP<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Input
2+
(4,1)
3+
123456
4+
123456
5+
123456
6+
foo
7+
bar
8+
9+
baz
10+
-- Output
11+
(1,1)
12+
foo123456
13+
bar123456
14+
123456
15+
foo
16+
bar
17+
18+
baz
19+
-- Events
20+
<C-v>jey<C-v>kkkP<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Input
2+
(1,1)
3+
foo
4+
bar
5+
6+
baz
7+
-- Output
8+
(1,1)
9+
foofoo
10+
barbar
11+
12+
bazbaz
13+
-- Events
14+
<C-v>jjjey<C-v>jjjP<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Input
2+
(1,1)
3+
foo
4+
bar
5+
6+
baz
7+
-- Output
8+
(1,1)
9+
foooo
10+
fooar
11+
12+
fooaz
13+
-- Events
14+
yw<C-v>jjjp<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Input
2+
(4,1)
3+
123456
4+
123456
5+
123456
6+
foo
7+
bar
8+
9+
baz
10+
-- Output
11+
(1,1)
12+
foo23456
13+
bar23456
14+
23456
15+
bazoo
16+
bar
17+
18+
baz
19+
-- Events
20+
<C-v>jjjey<C-v>kkkp<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-- Input
2+
(4,1)
3+
123456
4+
123456
5+
123456
6+
foo
7+
bar
8+
9+
baz
10+
-- Output
11+
(1,1)
12+
foo23456
13+
bar23456
14+
23456
15+
oo
16+
bar
17+
18+
baz
19+
-- Events
20+
<C-v>jey<C-v>kkkp<Esc>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Input
2+
(1,1)
3+
foo
4+
bar
5+
6+
baz
7+
-- Output
8+
(1,1)
9+
foooo
10+
barar
11+
12+
bazaz
13+
-- Events
14+
<C-v>jjjey<C-v>jjjp<Esc>

0 commit comments

Comments
 (0)