1
0
Fork 0
mirror of synced 2024-12-21 22:41:06 -05:00

Added yankstack, a replacement for YankRing

This commit is contained in:
amix 2016-05-14 13:00:06 +01:00
parent f343b66088
commit 347b3bea0e
10 changed files with 954 additions and 0 deletions

View file

@ -0,0 +1,2 @@
.rvmrc
doc/tags

View file

@ -0,0 +1,4 @@
source 'https://rubygems.org'
gem "vimbot", :git => "git@github.com:maxbrunsfeld/vimbot.git"
gem "rspec"

View file

@ -0,0 +1,25 @@
GIT
remote: git@github.com:maxbrunsfeld/vimbot.git
revision: 489cb3283a89d3e7891d9d9765188179c764317b
specs:
vimbot (0.0.1)
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.1.3)
rspec (2.8.0)
rspec-core (~> 2.8.0)
rspec-expectations (~> 2.8.0)
rspec-mocks (~> 2.8.0)
rspec-core (2.8.0)
rspec-expectations (2.8.0)
diff-lcs (~> 1.1.2)
rspec-mocks (2.8.0)
PLATFORMS
ruby
DEPENDENCIES
rspec
vimbot!

View file

@ -0,0 +1,134 @@
yankstack.vim
=============
Author: Max Brunsfeld <http://www.github.com/maxbrunsfeld>
[Yankstack.vim](https://github.com/maxbrunsfeld/vim-yankstack) is a
lightweight implementation of the Emacs 'kill ring' for Vim. It allows you to
yank and delete things without worrying about losing the text that you yanked
previously. It effectively turns your default register into a stack, and lets
you cycle through the items in the stack after doing a paste.
This plugin is intended to be a simpler alternative to the
[yankring](https://github.com/chrismetcalf/vim-yankring) plugin. It has a fairly
complete [test suite](https://github.com/maxbrunsfeld/vim-yankstack/blob/master/spec/yankstack/yankstack_spec.rb)
based on [rspec](https://www.relishapp.com/rspec)
and [vimbot](https://github.com/maxbrunsfeld/vimbot).
## Installation ##
I recommend loading your plugins with
[vundle](https://github.com/gmarik/vundle) or
[pathogen](https://github.com/tpope/vim-pathogen).
## Key Mappings ##
By default, yankstack adds only 2 key bindings, in normal and visual modes:
- ```meta-p``` - cycle *backward* through your history of yanks
- ```meta-shift-p``` - cycle *forwards* through your history of yanks
After pasting some text using ```p``` or ```P```, you can cycle through your
yank history using these commands. Typing either of these keys *without* pasting first
will do a normal paste (the same as typing `p`). This also works in insert mode.
### the 'meta' key
If you're using MacVim, and you want to use
this plugin's default key bindings (or any bindings involving the `option`
key), you must ```:set macmeta```. On Linux, you may have issues with the meta key if your terminal is running in 7bit mode.
Instructions for dealing with this can be found on the [wiki](https://github.com/maxbrunsfeld/vim-yankstack/wiki/Linux-terminal-configurations-for-correct-meta-key-handling)
## Commands ##
You can see the contents of the yank-stack using the ```:Yanks``` command.
Its output is similar to the ```:registers``` command.
## Configuration ##
Yankstack defines two plugin mappings that you can map to keys of your choosing.
The same mappings work in normal and insert modes.
- ```<Plug>yankstack_substitute_older_paste``` - cycle backwards through your history of yanks
- ```<Plug>yankstack_substitute_newer_paste``` - cycle forwards through your history of yanks
For example, if you wanted to define some mappings based on your 'leader' key,
you could do this:
```
nmap <leader>p <Plug>yankstack_substitute_older_paste
nmap <leader>P <Plug>yankstack_substitute_newer_paste
```
Also, if you want to load yankstack without the default key mappings, just
``` let g:yankstack_map_keys = 0 ```
in your .vimrc file.
## Compatibility ##
Yankstack works by mapping the yank and paste keys to functions that do some
book-keeping before calling through to the normal yank/paste keys. You may want
to define your own mappings of the yank and paste keys. For example, I like to
map the ```Y``` key to ```y$```, so that it behaves the same as ```D``` and
```C```. The yankstack mappings need to happen **before** you define any such
mappings of your own. To achieve this, just call ```yankstack#setup()``` in
your vimrc, before defining your mappings:
```
call yankstack#setup()
nmap Y y$
" other mappings involving y, d, c, etc
```
You can also prevent certain keys from being remapped by setting the `g:yankstack_yank_keys`
to the keys of your choosing. For example, if you only want Yankstack to remap `y` and `d`:
```
let g:yankstack_yank_keys = ['y', 'd']
```
## Contributing, Feedback ##
I'd enjoy hearing anybody's feedback on yankstack, and welcome any contribution.
Check it out on [github](https://github.com/maxbrunsfeld/vim-yankstack)!
## Changelog ##
### 1.0.6 (2014-08-04)
- Allow customization of the list of keys to be remapped.
### 1.0.5 (2012-07-19)
- Fix bug where on certain versions of vim, the first time you tried
to cycle through your yanks after doing a normal paste, an extra
paste was created.
### 1.0.4 (2012-07-01)
- Make it so that yankstack-cycling keys cause a normal paste if they are
used without pasting first. Fix stack-cycling in insert-mode.
### 1.0.3 (2012-05-04):
- Fix bug when overwriting text in select mode. This was causing
problems for snipMate users.
### 1.0.2 (2012-4-20):
- Add test coverage using rspec and [vimbot](https://github.com/maxbrunsfeld/vimbot)!
- Perfect the behavior of the yankstack when pasting over text in visual
mode
- Fix bug where 's' and 'S' didn't push to the yankstack
### 1.0.1 (2012-2-11):
- Change default key bindings, update readme, add link to github page.
### 1.0.1 (2011-12-08):
- Fix bug when displaying empty yanks.
### 1.0.0 (2011-12-04):
- Remove unnecessary dependency on the undotree() function. Plugin should
now work on any recent version of vim.
## License ##
Copyright (c) Max Brunsfeld. Distributed under the same terms as Vim itself.
See the vim license.
vim:tw=78:ts=8:ft=help:norl:

View file

@ -0,0 +1,197 @@
" yankstack.vim - keep track of your history of yanked/killed text
"
" Maintainer: Max Brunsfeld <https://github.com/maxbrunsfeld>
" Version: 1.0.6
" Todo:
"
let s:yankstack_tail = []
let g:yankstack_size = 30
let s:last_paste = { 'changedtick': -1, 'key': '', 'mode': 'n', 'count': 1, 'register': '' }
if !exists('g:yankstack_yank_keys')
let g:yankstack_yank_keys = ['c', 'C', 'd', 'D', 's', 'S', 'x', 'X', 'y', 'Y']
endif
function! s:yank_with_key(key)
call s:before_yank()
return a:key
endfunction
function! s:paste_with_key(key, mode, register, count)
return s:paste_from_yankstack(a:key, a:mode, a:register, a:count, 1)
endfunction
function! s:paste_from_yankstack(key, mode, register, count, is_new)
let keys = a:count . a:key
let keys = (a:register == s:default_register()) ? keys : ('"' . a:register . keys)
let s:last_paste = { 'key': a:key, 'mode': a:mode, 'register': a:register, 'count': a:count, 'changedtick': -1 }
call feedkeys("\<Plug>yankstack_after_paste", "m")
if a:mode == 'n'
exec 'normal!' keys
elseif a:mode == 'v'
if a:is_new
call s:before_yank()
call feedkeys("\<Plug>yankstack_substitute_older_paste", "t")
exec 'normal! gv' . keys
else
let head = s:get_yankstack_head()
exec 'normal! gv' . keys
call s:set_yankstack_head(head)
endif
" In insert mode, this function's return value is used in an
" expression mapping. In other modes, it is called for its
" side effects only.
elseif a:mode == 'i'
return keys
endif
silent! call repeat#setreg(a:register)
silent! call repeat#set(a:key, a:count)
endfunction
function! s:substitute_paste(offset, current_mode)
if s:last_change_was_paste()
silent undo
call s:yankstack_rotate(a:offset)
return s:paste_from_yankstack(s:last_paste.key, s:last_paste.mode, s:last_paste.register, s:last_paste.count, 0)
else
return s:paste_from_yankstack(s:default_paste_key(a:current_mode), a:current_mode, v:register, '', 1)
endif
endfunction
function! s:before_yank()
let head = s:get_yankstack_head()
if !empty(head.text) && (empty(s:yankstack_tail) || (head != s:yankstack_tail[0]))
call insert(s:yankstack_tail, head)
let s:yankstack_tail = s:yankstack_tail[: g:yankstack_size-1]
endif
endfunction
function! s:yankstack_rotate(offset)
if empty(s:yankstack_tail) | return | endif
let offset_left = a:offset
while offset_left != 0
let head = s:get_yankstack_head()
if offset_left > 0
let entry = remove(s:yankstack_tail, 0)
call add(s:yankstack_tail, head)
let offset_left -= 1
elseif offset_left < 0
let entry = remove(s:yankstack_tail, -1)
call insert(s:yankstack_tail, head)
let offset_left += 1
endif
call s:set_yankstack_head(entry)
endwhile
endfunction
function! s:get_yankstack_head()
let reg = s:default_register()
return { 'text': getreg(reg), 'type': getregtype(reg) }
endfunction
function! s:set_yankstack_head(entry)
let reg = s:default_register()
call setreg(reg, a:entry.text, a:entry.type)
endfunction
function! s:after_paste()
let s:last_paste.changedtick = b:changedtick
endfunction
function! s:last_change_was_paste()
return b:changedtick == s:last_paste.changedtick
endfunction
function! s:default_register()
let clipboard_flags = split(&clipboard, ',')
if index(clipboard_flags, 'unnamedplus') >= 0
return "+"
elseif index(clipboard_flags, 'unnamed') >= 0
return "*"
else
return "\""
endif
endfunction
function! s:default_paste_key(mode)
if a:mode == 'i'
return "\<C-g>u\<C-r>" . s:default_register()
else
return "p"
endif
endfunction
function! g:Yankstack()
return [s:get_yankstack_head()] + s:yankstack_tail
endfunction
command! -nargs=0 Yanks call s:show_yanks()
function! s:show_yanks()
echohl WarningMsg | echo "--- Yanks ---" | echohl None
let i = 0
for yank in g:Yankstack()
call s:show_yank(yank, i)
let i += 1
endfor
endfunction
function! s:show_yank(yank, index)
let index = printf("%-4d", a:index)
let lines = split(a:yank.text, '\n')
let line = empty(lines) ? '' : lines[0]
let line = substitute(line, '\t', repeat(' ', &tabstop), 'g')
if len(line) > 80 || len(lines) > 1
let line = line[: 80] . '…'
endif
echohl Directory | echo index
echohl None | echon line
echohl None
endfunction
function! yankstack#setup()
if exists('g:yankstack_did_setup') | return | endif
let g:yankstack_did_setup = 1
let paste_keys = ['p', 'P', 'gp', 'gP']
let word_characters = split("qwertyuiopasdfghjklzxcvbnm1234567890_", '\zs')
for key in g:yankstack_yank_keys
exec 'nnoremap <silent> <expr>' key '<SID>yank_with_key("' . key . '")'
exec 'xnoremap <silent> <expr>' key '<SID>yank_with_key("' . key . '")'
endfor
for key in paste_keys
exec 'nnoremap <silent>' key ':<C-u>call <SID>paste_with_key("' . key . '", "n", v:register, v:count1)<CR>'
exec 'xnoremap <silent>' key ':<C-u>call <SID>paste_with_key("' . key . '", "v", v:register, v:count1)<CR>'
endfor
for key in word_characters
exec 'smap <expr>' key '<SID>yank_with_key("' . key . '")'
endfor
endfunction
nnoremap <silent> <Plug>yankstack_substitute_older_paste :<C-u>call <SID>substitute_paste(v:count1, 'n')<CR>
nnoremap <silent> <Plug>yankstack_substitute_newer_paste :<C-u>call <SID>substitute_paste(-v:count1, 'n')<CR>
xnoremap <silent> <Plug>yankstack_substitute_older_paste :<C-u>call <SID>substitute_paste(v:count1, 'v')<CR>
xnoremap <silent> <Plug>yankstack_substitute_newer_paste :<C-u>call <SID>substitute_paste(-v:count1, 'v')<CR>
inoremap <silent> <Plug>yankstack_substitute_older_paste <C-r>=<SID>substitute_paste(v:count1, 'i')<CR>
inoremap <silent> <Plug>yankstack_substitute_newer_paste <C-r>=<SID>substitute_paste(-v:count1, 'i')<CR>
nnoremap <silent> <Plug>yankstack_after_paste :call <SID>after_paste()<CR>
xnoremap <silent> <Plug>yankstack_after_paste :<C-u>call <SID>after_paste()<CR>
inoremap <silent> <Plug>yankstack_after_paste <C-o>:call <SID>after_paste()<CR>
if !exists('g:yankstack_map_keys') || g:yankstack_map_keys
nmap <M-p> <Plug>yankstack_substitute_older_paste
xmap <M-p> <Plug>yankstack_substitute_older_paste
imap <M-p> <Plug>yankstack_substitute_older_paste
nmap <M-P> <Plug>yankstack_substitute_newer_paste
xmap <M-P> <Plug>yankstack_substitute_newer_paste
imap <M-P> <Plug>yankstack_substitute_newer_paste
endif

View file

@ -0,0 +1,124 @@
*yankstack.txt* Plugin for storing and cycling through yanked text strings.
Author: Max Brunsfeld <http://www.github.com/maxbrunsfeld>
|yankstack-introduction| Introduction
|yankstack-installation| Installation
|yankstack-initialization| Initialization
|yankstack-commands| Commands
|yankstack-configuration| Configuration
|yankstack-changelog| Changelog
INTRODUCTION *yankstack-introduction*
[Yankstack.vim](https://github.com/maxbrunsfeld/vim-yankstack) is a
lightweight implementation of the Emacs 'kill ring' for Vim. It allows you to
yank and delete things without worrying about losing the text that you yanked
previously. It effectively turns your default register into a stack, and lets
you cycle through the items in the stack after doing a paste.
This plugin is intended to be a simpler alternative to the {Yankring} plugin
(https://github.com/chrismetcalf/vim-yankring).
INSTALLATION *yankstack-installation*
I recommend loading your plugins with {Pathogen}
(https://github.com/tpope/vim-pathogen), so you can just clone this repo into
your "bundle" directory.
KEY MAPPINGS *yankstack-mappings*
By default, yankstack adds only 2 key mappings, in normal and visual modes:
Mapping Action ~
meta-p cycle backward through your history of yanks
meta-shift-p cycle forwards through your history of yanks
After pasting some text using |p| or |P|, you can cycle through your
yank history using these commands.
Typing either of these keys without pasting first will do a normal paste
(the same as typing `p`). This also works in insert mode.
A note about the meta key - if you're using MacVim, and you want to use
this plugin's default key bindings (or any bindings involving the `option`
key), you must :set |macmeta|.
COMMANDS *yankstack-commands*
You can see the contents of the yank-stack using the :Yanks command.
Its output is similar to the |registers| command. >
:Yanks (lists the contents of the yank-stack)
CONFIGURATION *yankstack-configuration*
If you want to load yankstack without defining any of the default key
mappings, just add >
let g:yankstack_map_keys = 0
to your |.vimrc| file.
Yankstack defines three plugin mappings that you can map to keys of your
choosing. The same mappings work in normal and insert modes.
Mapping Name Action ~
<Plug>yankstack_substitute_older_paste cycle BACKWARDs through your history of yanks
<Plug>yankstack_substitute_newer_paste cycle FORWARDS through your history of yanks
For example, if you wanted to define some mappings based on your |leader| key, you could do this: >
nmap <leader>p <Plug>yankstack_substitute_older_paste
nmap <leader>P <Plug>yankstack_substitute_newer_paste
COMPATIBILITY *yankstack-compatibility*
Yankstack works by mapping the yank and paste keys to functions that do some
book-keeping before calling through to the normal yank/paste keys. You may
want to define your own mappings of the yank and paste keys. For example, I
like to map the |Y| key to "y$", so that it behaves the same as |D| and |C|.
The yankstack mappings need to happen **BEFORE** you define any such
mappings of your own. To achieve this, just call 'yankstack#setup()'in your
|vimrc|, before defining your mappings: >
call yankstack#setup()
nmap Y y$
CHANGELOG *yankstack-changelog*
1.0.5 (2012-07-19)
- Fix bug where on certain versions of vim, the first time you tried
to cycle through your yanks after doing a normal paste, an extra
paste was created.
1.0.4 (2012-07-01)
- Make it so that yankstack-cycling keys cause a normal paste if they are
used without pasting first. Fix stack-cycling in insert-mode.
1.0.3 (2012-05-04):
- Fix bug when overwriting text in select mode. This was causing
problems for snipMate users.
1.0.2 (2012-4-20):
- Add test coverage using rspec and [vimbot](https://github.com/maxbrunsfeld/vimbot)!
- Perfect the behavior of the yankstack when pasting over text in visual
mode
- Fix bug where 's' and 'S' didn't push to the yankstack
1.0.1 (2012-02-11):
- Change default key bindings, update readme, add link to github page.
1.0.1 (2011-12-08):
- Fix bug when displaying empty yanks.
1.0 (2011-12-04):
- Remove unnecessary dependency on the undotree() function. Plugin should
now work on any recent version of vim.
*yankstack-license*
Copyright (c) Max Brunsfeld. Distributed under the same terms as Vim itself.
See |license|.
vim:tw=78:ts=8:ft=help:norl:

View file

@ -0,0 +1 @@
call yankstack#setup()

View file

@ -0,0 +1,115 @@
" repeat.vim - Let the repeat command repeat plugin maps
" Maintainer: Tim Pope
" Version: 1.1
" GetLatestVimScripts: 2136 1 :AutoInstall: repeat.vim
" Installation:
" Place in either ~/.vim/plugin/repeat.vim (to load at start up) or
" ~/.vim/autoload/repeat.vim (to load automatically as needed).
"
" License:
" Copyright (c) Tim Pope. Distributed under the same terms as Vim itself.
" See :help license
"
" Developers:
" Basic usage is as follows:
"
" silent! call repeat#set("\<Plug>MappingToRepeatCommand",3)
"
" The first argument is the mapping that will be invoked when the |.| key is
" pressed. Typically, it will be the same as the mapping the user invoked.
" This sequence will be stuffed into the input queue literally. Thus you must
" encode special keys by prefixing them with a backslash inside double quotes.
"
" The second argument is the default count. This is the number that will be
" prefixed to the mapping if no explicit numeric argument was given. The
" value of the v:count variable is usually correct and it will be used if the
" second parameter is omitted. If your mapping doesn't accept a numeric
" argument and you never want to receive one, pass a value of -1.
"
" Make sure to call the repeat#set function _after_ making changes to the
" file.
"
" For mappings that use a register and want the same register used on
" repetition, use:
"
" silent! call repeat#setreg("\<Plug>MappingToRepeatCommand", v:register)
"
" This function can (and probably needs to be) called before making changes to
" the file (as those typically clear v:register). Therefore, the call sequence
" in your mapping will look like this:
"
" nnoremap <silent> <Plug>MyMap
" \ :<C-U>execute 'silent! call repeat#setreg("\<lt>Plug>MyMap", v:register)'<Bar>
" \ call <SID>MyFunction(v:register, ...)<Bar>
" \ silent! call repeat#set("\<lt>Plug>MyMap")<CR>
if exists("g:loaded_repeat") || &cp || v:version < 700
finish
endif
let g:loaded_repeat = 1
let g:repeat_tick = -1
let g:repeat_reg = ['', '']
" Special function to avoid spurious repeats in a related, naturally repeating
" mapping when your repeatable mapping doesn't increase b:changedtick.
function! repeat#invalidate()
let g:repeat_tick = -1
endfunction
function! repeat#set(sequence,...)
let g:repeat_sequence = a:sequence
let g:repeat_count = a:0 ? a:1 : v:count
let g:repeat_tick = b:changedtick
endfunction
function! repeat#setreg(sequence,register)
let g:repeat_reg = [a:sequence, a:register]
endfunction
function! repeat#run(count)
if g:repeat_tick == b:changedtick
let r = ''
if g:repeat_reg[0] ==# g:repeat_sequence && !empty(g:repeat_reg[1])
if g:repeat_reg[1] ==# '='
" This causes a re-evaluation of the expression on repeat, which
" is what we want.
let r = '"=' . getreg('=', 1) . "\<CR>"
else
let r = '"' . g:repeat_reg[1]
endif
endif
let c = g:repeat_count
let s = g:repeat_sequence
let cnt = c == -1 ? "" : (a:count ? a:count : (c ? c : ''))
call feedkeys(r . cnt, 'n')
call feedkeys(s)
else
call feedkeys((a:count ? a:count : '') . '.', 'n')
endif
endfunction
function! repeat#wrap(command,count)
let preserve = (g:repeat_tick == b:changedtick)
exe 'norm! '.(a:count ? a:count : '').a:command . (&foldopen =~# 'undo' ? 'zv' : '')
if preserve
let g:repeat_tick = b:changedtick
endif
endfunction
nnoremap <silent> . :<C-U>call repeat#run(v:count)<CR>
nnoremap <silent> u :<C-U>call repeat#wrap('u',v:count)<CR>
if maparg('U','n') ==# ''
nnoremap <silent> U :<C-U>call repeat#wrap('U',v:count)<CR>
endif
nnoremap <silent> <C-R> :<C-U>call repeat#wrap("\<Lt>C-R>",v:count)<CR>
augroup repeatPlugin
autocmd!
autocmd BufLeave,BufWritePre,BufReadPre * let g:repeat_tick = (g:repeat_tick == b:changedtick || g:repeat_tick == 0) ? 0 : -1
autocmd BufEnter,BufWritePost * if g:repeat_tick == 0|let g:repeat_tick = b:changedtick|endif
augroup END
" vim:set ft=vim et sw=4 sts=4:

View file

@ -0,0 +1,9 @@
require "vimbot"
PLUGIN_ROOT = File.expand_path("../..", __FILE__)
VIM_REPEAT_PATH = File.expand_path("spec/fixtures/repeat.vim", PLUGIN_ROOT)
RSpec.configure do |c|
c.alias_it_should_behave_like_to :it_has_behavior, 'has behavior:'
end

View file

@ -0,0 +1,343 @@
require "spec_helper"
describe "Yankstack" do
let(:vim) { Vimbot::Driver.new }
before(:all) do
vim.start
vim.set "visualbell"
vim.set "noerrorbells"
vim.set "macmeta"
vim.set "runtimepath+=#{PLUGIN_ROOT}"
vim.runtime "plugin/yankstack.vim"
vim.source VIM_REPEAT_PATH
end
after(:all) { vim.stop }
before(:each) { vim.clear_buffer }
shared_examples "yanking and pasting" do
let(:yank_keys) { "yw" }
before do
vim.insert "first_line<CR>", "second_line<CR>", "third_line<CR>", "fourth_line"
vim.normal "gg"
vim.normal yank_keys, 'j', yank_keys, 'j', yank_keys, 'j', yank_keys
end
it "pushes every yanked string to the :Yanks stack" do
yank_entries[0].should match /0\s+fourth_line/
yank_entries[1].should match /1\s+third_line/
yank_entries[2].should match /2\s+second_line/
yank_entries[3].should match /3\s+first_line/
end
describe "yanking with different keys" do
before do
vim.normal "A", "<CR>", "line to delete", "<Esc>", "^"
end
keys_that_change_register = [
'cc', 'C',
'dd', 'D',
's', 'S',
'x', 'X',
'yy', 'Y'
]
keys_that_change_register.each do |key|
it "pushes to the stack when deleting text with '#{key}'" do
vim.normal key
yank_entries[1].should match /1\s+fourth_line/
end
end
it "pushes to the stack when overwriting text in select mode" do
vim.type "V"
vim.type "<c-g>", "this overwrites the last line"
yank_entries[0].should include "line to delete"
yank_entries[1].should include "fourth_line"
end
end
context "in normal mode" do
before { vim.normal "o", "<Esc>" }
describe "pasting a string with 'p'" do
before { vim.normal "p" }
it "pastes the most recently yanked string" do
vim.line_number.should == 5
vim.line.should == "fourth_line"
end
describe "pressing the repeat key with '.'" do
it "pastes again" do
pending unless File.exists?(VIM_REPEAT_PATH)
vim.type "."
vim.line.should == "fourth_linefourth_line"
end
end
describe "typing the 'cycle paste' key" do
before { vim.normal "<M-p>" }
it "replaces the pasted string with the previously yanked text" do
vim.line.should == "third_line"
end
it "rotates the previously yanked text to the top of the yank stack" do
yank_entries[0].should include 'third_line'
yank_entries[1].should include 'second_line'
yank_entries[2].should include 'first_line'
yank_entries[-1].should include 'fourth_line'
end
it "rotates through the yanks when pressed multiple times" do
vim.normal "<M-p>"
vim.line.should == "second_line"
vim.normal "<M-p>"
vim.line.should == "first_line"
vim.normal "<M-P>"
vim.line.should == "second_line"
vim.normal "<M-P>"
vim.line.should == "third_line"
vim.normal "<M-P>"
vim.line.should == "fourth_line"
end
end
end
describe "typing the `substitute_older_paste` key without pasting first" do
before { vim.type "<M-p>" }
it "pastes the most recently yanked string" do
vim.line_number.should == 5
vim.line.should == "fourth_line"
end
describe "typing the 'cycle paste' key" do
before { vim.normal "<M-p>" }
it "replaces the pasted text with the previously yanked text" do
vim.line.should == "third_line"
end
end
end
describe "typing the `substitute_newer_paste` key without pasting first" do
before { vim.type "<M-P>" }
it "pastes the most recently yanked string" do
vim.line_number.should == 5
vim.line.should == "fourth_line"
end
describe "typing the 'cycle paste' key" do
before { vim.normal "<M-p>" }
it "replaces the pasted text with the previously yanked text" do
vim.line.should == "third_line"
end
end
end
it "allows pasting from a non-default register" do
reg = 'a'
vim.normal "gg"
vim.normal %("#{reg}y$)
vim.normal "G"
vim.normal %("#{reg}p)
vim.line.should == "first_line"
end
it "allows pasting with a count" do
vim.normal "3p"
vim.line_number.should == 5
vim.line.should == "fourth_line" * 3
end
end
context "in visual mode, with text highlighted" do
before do
vim.normal "A<CR>", "line to overwrite"
vim.normal "V"
end
describe "pasting a string with 'p'" do
before do
vim.type "p"
end
it "overwrites the selection with the most recently yanked string" do
vim.line.should == "fourth_line"
end
it "moves the the overwritten text to the bottom of the stack" do
yank_entries[0].should include "fourth_line"
yank_entries[1].should include "third_line"
yank_entries[2].should include "second_line"
yank_entries[-1].should include "line to overwrite"
end
describe "typing the 'cycle older paste' key" do
before { vim.normal "<M-p>" }
it "replaces the pasted text with the previously yanked text" do
vim.line.should == "third_line"
end
it "moves the previously yanked text to the top of the stack" do
yank_entries[0].should include "third_line"
yank_entries[1].should include "second_line"
yank_entries[2].should include "first_line"
yank_entries[-2].should include "line to overwrite"
yank_entries[-1].should include "fourth_line"
end
describe "typing the 'cycle newer paste' key" do
before { vim.normal "<M-P>" }
it "replaces the pasted text with the previously yanked text" do
vim.line.should == "fourth_line"
end
it "moves the previously yanked text to the top of the stack" do
yank_entries[0].should include "fourth_line"
yank_entries[1].should include "third_line"
yank_entries[2].should include "second_line"
yank_entries[3].should include "first_line"
yank_entries[-1].should include "line to overwrite"
end
end
end
end
describe "typing the `substitute_older_paste` key without pasting first" do
before { vim.type "<M-p>" }
it "overwrites the selection with the most recently yanked string" do
vim.line_number.should == 5
vim.line.should == "fourth_line"
end
end
describe "typing the `substitute_newer_paste` key without pasting first" do
before { vim.type "<M-P>" }
it "overwrites the selection with the most recently yanked string" do
vim.line_number.should == 5
vim.line.should == "fourth_line"
end
end
it "allows pasting with a count" do
vim.type "3p"
vim.line_number.should == 5
vim.line.should == "fourth_line"
vim.normal 'j'
vim.line_number.should == 6
vim.line.should == "fourth_line"
vim.normal 'j'
vim.line_number.should == 7
vim.line.should == "fourth_line"
end
end
context "in insert mode" do
before do
vim.normal "A<Cr>", "()", "<Left>"
vim.type "<M-p>"
end
describe "typing the `substitute_older_paste` after a character-wise yank" do
it "pastes the most recently yanked text after the cursor" do
vim.line_number.should == 5
vim.line.should == "(fourth_line)"
end
it "stays in insert mode, with the cursor at the end of the pasted text" do
vim.should be_in_insert_mode
vim.column_number.should == "(fourth_line".length + 1
end
describe "typing the `substitute_older_paste` key again" do
before { vim.type "<M-p>" }
it "replaces the pasted text with the previously yanked text" do
vim.line_number.should == 5
vim.line.should == "(third_line)"
end
it "stays in insert mode, with the cursor at the end of the pasted text" do
vim.should be_in_insert_mode
vim.column_number.should == "(third_line".length+1
end
it "rotates the previously yanked text to the top of the yank stack" do
yank_entries[0].should include 'third_line'
yank_entries[1].should include 'second_line'
yank_entries[2].should include 'first_line'
yank_entries[-1].should include 'fourth_line'
end
it "rotates through the yanks when pressed multiple times" do
vim.type "<M-p>"
vim.line_number.should == 5
vim.line.should == "(second_line)"
vim.type "<M-p>"
vim.line_number.should == 5
vim.line.should == "(first_line)"
vim.type "<M-P>"
vim.line_number.should == 5
vim.line.should == "(second_line)"
vim.type "<M-P>"
vim.line_number.should == 5
vim.line.should == "(third_line)"
vim.type "<M-P>"
vim.line_number.should == 5
vim.line.should == "(fourth_line)"
end
end
end
describe "typing `substitute_older_paste` after a line-wise yank" do
let(:yank_keys) { "yy" }
xit "pastes and puts the cursor after the pasted text" do
vim.line_number.should == 6
vim.line.should == ")"
vim.type "<Up>"
vim.line.should == "(fourth_line"
end
end
end
end
describe "when using the normal default register" do
it_has_behavior "yanking and pasting"
end
describe "when using the system clipboard as the default register" do
before { vim.set "clipboard", "unnamed" }
it_has_behavior "yanking and pasting"
end
def yank_entries
@yank_entries ||= vim.command("Yanks").split("\n")[1..-1]
end
end