Skip to content

Commit

Permalink
Version 2.20
Browse files Browse the repository at this point in the history
- ENH: gpp also handles multi-line pastes. A number (after the corresponding column) is incremented in every line. If there are no increments this way, fall back to replacement of the first occurrence.
- ENH: Add gPp / gPP mappings to paste with all numbers incremented / decremented.
- ENH: Add g]p / g]P mappings to paste linewise with adjusted indent. Thanks to Gary Fixler for the suggestion.
  • Loading branch information
Ingo Karkat authored and vim-scripts committed Apr 1, 2013
1 parent 55e6b05 commit 035ee5d
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 31 deletions.
10 changes: 10 additions & 0 deletions README
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ USAGE
pushing existing text further to the right) [count] pushing existing text further to the right) [count]
times. times.


["x]g]p, ["x]g[P or Paste linewise (even if yanked text is not a complete
["x]g]P or line) [count] times like glp, but adjust the indent
["x]g[p to the current line (like ]p) .

["x]g,p, ["x]g,P Paste characterwise, with each line delimited by ", " ["x]g,p, ["x]g,P Paste characterwise, with each line delimited by ", "
instead of the newline (and indent). instead of the newline (and indent).


Expand All @@ -57,6 +61,12 @@ USAGE
Do this [count] times, with each paste further Do this [count] times, with each paste further
incremented / decremented. incremented / decremented.


["x]gPp, ["x]gPP Paste with the all numbers incremented / decremented
by 1.
Do this [count] times, with each paste further
incremented / decremented.


CTRL-R CTRL-C {0-9a-z"%#*+/:.-} CTRL-R CTRL-C {0-9a-z"%#*+/:.-}
Insert the contents of a register characterwise Insert the contents of a register characterwise
(newline characters and indent are flattened to (newline characters and indent are flattened to
Expand Down
67 changes: 48 additions & 19 deletions autoload/UnconditionalPaste.vim
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
" "
" DEPENDENCIES: " DEPENDENCIES:


" Copyright: (C) 2006-2012 Ingo Karkat " Copyright: (C) 2006-2013 Ingo Karkat
" The VIM LICENSE applies to this script; see ':help copyright'. " The VIM LICENSE applies to this script; see ':help copyright'.
" "
" Maintainer: Ingo Karkat <ingo@karkat.de> " Maintainer: Ingo Karkat <ingo@karkat.de>
" Source: Based on vimtip #1199 by cory, " Source: Based on vimtip #1199 by cory,
" http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste " http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste
" "
" REVISION DATE REMARKS " REVISION DATE REMARKS
" 2.20.021 18-Mar-2013 ENH: Add gPp / gPP mappings to paste with all
" numbers incremented / decremented.
" 2.20.020 15-Mar-2013 ENH: gpp also handles multi-line pastes. A
" number (after the corresponding column) is
" incremented in every line. If there are no
" increments this way, fall back to replacement of
" the first occurrence.
" 2.10.019 21-Dec-2012 FIX: For characterwise pastes with a [count], " 2.10.019 21-Dec-2012 FIX: For characterwise pastes with a [count],
" the multiplied pastes must be joined with the " the multiplied pastes must be joined with the
" desired separator, not just plainly " desired separator, not just plainly
Expand Down Expand Up @@ -110,24 +117,44 @@ function! s:Unjoin( text, separatorPattern )
" pasting. For consistency, do the same for a single leading separator. " pasting. For consistency, do the same for a single leading separator.
return (l:text =~# '^\n' ? l:text[1:] : l:text) return (l:text =~# '^\n' ? l:text[1:] : l:text)
endfunction endfunction
function! s:Increment( text, vcol, offset ) function! s:IncrementLine( line, vcol, replacement )
let l:replacement = '\=submatch(0) + ' . a:offset

if a:vcol == -1 || a:vcol == 0 && col('.') + 1 == col('$') if a:vcol == -1 || a:vcol == 0 && col('.') + 1 == col('$')
return [-1, substitute(a:text, '\d\+\ze\D*$', l:replacement, '')] " Increment the last number.
return [-1, substitute(a:line, '\d\+\ze\D*$', a:replacement, '')]
endif endif


let l:text = a:text let l:text = a:line
let l:vcol = (a:vcol == 0 ? virtcol('.') : a:vcol) let l:vcol = (a:vcol == 0 ? virtcol('.') : a:vcol)
if l:vcol > 1 if l:vcol > 1
let l:text = substitute(a:text, '\d*\%>' . (l:vcol - 1) . 'v\d\+', l:replacement, '') return [l:vcol, substitute(a:line, '\d*\%>' . (l:vcol - 1) . 'v\d\+', a:replacement, '')]
endif
if l:text ==# a:text
return [1, substitute(a:text, '\d\+', l:replacement, '')]
else else
return [l:vcol, l:text] return [1, substitute(a:line, '\d\+', a:replacement, '')]
endif endif
endfunction endfunction
function! s:SingleIncrement( text, vcol, offset )
let l:replacement = '\=submatch(0) + ' . a:offset

let l:didIncrement = 0
let l:vcol = 0
let l:result = []
for l:line in split(a:text, "\n", 1)
let [l:vcol, l:incrementedLine] = s:IncrementLine(l:line, a:vcol, l:replacement)
let l:didIncrement = l:didIncrement || (l:line !=# l:incrementedLine)
call add(l:result, l:incrementedLine)
endfor

if ! l:didIncrement
" Fall back to incrementing the first number.
let l:vcol = 0
let l:result = map(split(a:text, "\n", 1), 'substitute(v:val, "\\d\\+", l:replacement, "")')
endif

return [l:vcol, join(l:result, "\n")]
endfunction
function! s:GlobalIncrement( text, vcol, offset )
let l:replacement = '\=submatch(0) + ' . a:offset
return [0, substitute(a:text, '\d\+', l:replacement, 'g')]
endfunction


function! UnconditionalPaste#GetCount() function! UnconditionalPaste#GetCount()
return s:count return s:count
Expand Down Expand Up @@ -215,24 +242,26 @@ function! UnconditionalPaste#Paste( regName, how, ... )
endif endif
elseif a:how ==# 'l' && l:regType[0] ==# "\<C-v>" elseif a:how ==# 'l' && l:regType[0] ==# "\<C-v>"
let l:pasteContent = s:StripTrailingWhitespace(l:regContent) let l:pasteContent = s:StripTrailingWhitespace(l:regContent)
elseif a:how ==# 'p' || a:how ==# '.p' elseif a:how ==? 'p' || a:how ==? '.p'
let l:pasteType = l:regType " Keep the original paste type. let l:pasteType = l:regType " Keep the original paste type.
let l:offset = (a:1 ==# 'p' ? 1 : -1) let l:offset = (a:1 ==# 'p' ? 1 : -1)
if a:how ==# 'p' if a:how ==? 'p'
let l:baseCount = 1 let l:baseCount = 1
let l:vcol = 0 let l:vcol = 0
elseif a:how ==# '.p' elseif a:how ==? '.p'
" Continue increasing with the last used (saved) offset, and at " Continue increasing with the last used (saved) offset, and
" the same number position (after the first paste, the cursor " (for 'p') at the same number position (after the first paste,
" will have jumped to the beginning of the pasted text). " the cursor will have jumped to the beginning of the pasted
" text).
let l:baseCount = s:lastCount + 1 let l:baseCount = s:lastCount + 1
let l:vcol = s:lastVcol let l:vcol = s:lastVcol
else else
throw 'ASSERT: Invalid how: ' . string(a:how) throw 'ASSERT: Invalid how: ' . string(a:how)
endif endif
let s:lastCount = l:baseCount let s:lastCount = l:baseCount


let [s:lastVcol, l:pasteContent] = s:Increment(l:regContent, l:vcol, l:offset * l:baseCount) let l:IncrementFunc = (a:how ==# 'p' || a:how ==# '.p' ? 's:SingleIncrement' : 's:GlobalIncrement')
let [s:lastVcol, l:pasteContent] = call(l:IncrementFunc, [l:regContent, l:vcol, l:offset * l:baseCount])
if l:pasteContent ==# l:regContent if l:pasteContent ==# l:regContent
" No number was found in the register; this is probably not what " No number was found in the register; this is probably not what
" the user intended (maybe wrong register?), so don't just " the user intended (maybe wrong register?), so don't just
Expand All @@ -245,7 +274,7 @@ function! UnconditionalPaste#Paste( regName, how, ... )
" To increment each multiplied paste one more, we need to " To increment each multiplied paste one more, we need to
" process the multiplication on our own. " process the multiplication on our own.
let l:numbers = (l:offset > 0 ? range(l:baseCount, l:baseCount + l:count - 1) : range(-1 * (l:baseCount + l:count - 1), -1 * l:baseCount)) let l:numbers = (l:offset > 0 ? range(l:baseCount, l:baseCount + l:count - 1) : range(-1 * (l:baseCount + l:count - 1), -1 * l:baseCount))
let l:pasteContent = join(map(l:numbers, 's:Increment(l:regContent, l:vcol, v:val)[1]'), (l:regType[0] ==# "\<C-v>" ? "\n" : '')) let l:pasteContent = join(map(l:numbers, l:IncrementFunc . '(l:regContent, l:vcol, v:val)[1]'), (l:regType[0] ==# "\<C-v>" ? "\n" : ''))
let s:lastCount = l:baseCount + l:count - 1 let s:lastCount = l:baseCount + l:count - 1
let l:count = 0 let l:count = 0
endif endif
Expand Down
27 changes: 25 additions & 2 deletions doc/UnconditionalPaste.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ USAGE *UnconditionalPaste-usage*
pushing existing text further to the right) [count] pushing existing text further to the right) [count]
times. times.


*g]p* *g[P* *g]P* *g[p*
["x]g]p, ["x]g[P or Paste linewise (even if yanked text is not a complete
["x]g]P or line) [count] times like |glp|, but adjust the indent
["x]g[p to the current line (like |]p|) .

*g,p* *g,P* *g,p* *g,P*
["x]g,p, ["x]g,P Paste characterwise, with each line delimited by ", " ["x]g,p, ["x]g,P Paste characterwise, with each line delimited by ", "
instead of the newline (and indent). instead of the newline (and indent).
Expand All @@ -75,6 +80,11 @@ USAGE *UnconditionalPaste-usage*
no such match, or the last number, if the cursor is at no such match, or the last number, if the cursor is at
the end of the line) incremented / decremented by 1. the end of the line) incremented / decremented by 1.
Do this [count] times, with each paste further Do this [count] times, with each paste further
incremented / decremented.
*gPp* *gPP*
["x]gPp, ["x]gPP Paste with the all numbers incremented / decremented
by 1.
Do this [count] times, with each paste further
incremented / decremented. incremented / decremented.




Expand Down Expand Up @@ -148,6 +158,8 @@ script (e.g. in your |vimrc|): >
nmap <Leader>pl <Plug>UnconditionalPasteLineAfter nmap <Leader>pl <Plug>UnconditionalPasteLineAfter
nmap <Leader>Pb <Plug>UnconditionalPasteBlockBefore nmap <Leader>Pb <Plug>UnconditionalPasteBlockBefore
nmap <Leader>pb <Plug>UnconditionalPasteBlockAfter nmap <Leader>pb <Plug>UnconditionalPasteBlockAfter
nmap <Leader>Pi <Plug>UnconditionalPasteIndentedBefore
nmap <Leader>pi <Plug>UnconditionalPasteIndentedAfter
nmap <Leader>P, <Plug>UnconditionalPasteCommaBefore nmap <Leader>P, <Plug>UnconditionalPasteCommaBefore
nmap <Leader>p, <Plug>UnconditionalPasteCommaAfter nmap <Leader>p, <Plug>UnconditionalPasteCommaAfter
nmap <Leader>Pq <Plug>UnconditionalPasteQueriedBefore nmap <Leader>Pq <Plug>UnconditionalPasteQueriedBefore
Expand All @@ -160,6 +172,8 @@ script (e.g. in your |vimrc|): >
nmap <Leader>pU <Plug>UnconditionalPasteRecallUnjoinAfter nmap <Leader>pU <Plug>UnconditionalPasteRecallUnjoinAfter
nmap <Leader>Pp <Plug>UnconditionalPastePlusBefore nmap <Leader>Pp <Plug>UnconditionalPastePlusBefore
nmap <Leader>pp <Plug>UnconditionalPastePlusAfter nmap <Leader>pp <Plug>UnconditionalPastePlusAfter
nmap <Leader>PP <Plug>UnconditionalPasteGPlusBefore
nmap <Leader>pP <Plug>UnconditionalPasteGPlusAfter
imap <C-G>c <Plug>UnconditionalPasteChar imap <C-G>c <Plug>UnconditionalPasteChar
imap <C-G>, <Plug>UnconditionalPasteComma imap <C-G>, <Plug>UnconditionalPasteComma
Expand All @@ -180,6 +194,15 @@ IDEAS *UnconditionalPaste-ideas*
============================================================================== ==============================================================================
HISTORY *UnconditionalPaste-history* HISTORY *UnconditionalPaste-history*


2.20 18-Mar-2013
- ENH: gpp also handles multi-line pastes. A number (after the corresponding
column) is incremented in every line. If there are no increments this way,
fall back to replacement of the first occurrence.
- ENH: Add gPp / gPP mappings to paste with all numbers incremented /
decremented.
- ENH: Add g]p / g]P mappings to paste linewise with adjusted indent. Thanks
to Gary Fixler for the suggestion.

2.10 22-Dec-2012 2.10 22-Dec-2012
- ENH: Add gpp / gpP mappings to paste with one number (which depending on the - ENH: Add gpp / gpP mappings to paste with one number (which depending on the
current cursor position) incremented / decremented. current cursor position) incremented / decremented.
Expand Down Expand Up @@ -235,8 +258,8 @@ Published, prompted by a related question on reddit.
Started development, based on vimtip #1199 by cory. Started development, based on vimtip #1199 by cory.


============================================================================== ==============================================================================
Copyright: (C) 2006-2012 Ingo Karkat Copyright: (C) 2006-2013 Ingo Karkat
The VIM LICENSE applies to this script; see |copyright|. The VIM LICENSE applies to this plugin; see |copyright|.


Maintainer: Ingo Karkat <ingo@karkat.de> Maintainer: Ingo Karkat <ingo@karkat.de>
============================================================================== ==============================================================================
Expand Down
46 changes: 36 additions & 10 deletions plugin/UnconditionalPaste.vim
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
" http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste " http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste
" "
" REVISION DATE REMARKS " REVISION DATE REMARKS
" 2.20.020 18-Mar-2013 ENH: Add g]p / g]P mappings to paste linewise
" with adjusted indent. Thanks to Gary Fixler for
" the suggestion.
" 2.20.019 18-Mar-2013 ENH: Add gPp / gPP mappings to paste with all
" numbers incremented / decremented.
" 2.10.018 22-Dec-2012 FIX: Do not re-query on repeat of the mapping. " 2.10.018 22-Dec-2012 FIX: Do not re-query on repeat of the mapping.
" This wasn't updated for the Query mapping and " This wasn't updated for the Query mapping and
" not implemented at all for the Unjoin mapping. " not implemented at all for the Unjoin mapping.
Expand Down Expand Up @@ -112,25 +117,47 @@ function! s:CreateMappings()
for [l:pasteName, pasteType] in for [l:pasteName, pasteType] in
\ [ \ [
\ ['Char', 'c'], ['Line', 'l'], ['Block', 'b'], ['Comma', ','], \ ['Char', 'c'], ['Line', 'l'], ['Block', 'b'], ['Comma', ','],
\ ['Indented', 'l'],
\ ['Queried', 'q'], ['RecallQueried', 'Q'], \ ['Queried', 'q'], ['RecallQueried', 'Q'],
\ ['Unjoin', 'u'], ['RecallUnjoin', 'U'], \ ['Unjoin', 'u'], ['RecallUnjoin', 'U'],
\ ['Plus', 'p'], ['PlusRepeat', '.p'] \ ['Plus', 'p'], ['PlusRepeat', '.p'],
\ ['GPlus', 'P'], ['GPlusRepeat', '.P']
\ ] \ ]
for [l:direction, l:pasteCmd] in [['After', 'p'], ['Before', 'P']] for [l:direction, l:pasteCmd] in [['After', 'p'], ['Before', 'P']]
let l:mappingName = 'UnconditionalPaste' . l:pasteName . l:direction let l:mappingName = 'UnconditionalPaste' . l:pasteName . l:direction
let l:plugMappingName = '<Plug>' . l:mappingName let l:plugMappingName = '<Plug>' . l:mappingName


" Do not create default mappings for the special paste repeats.
let l:pasteMappingDefaultKeys = (len(l:pasteType) == 1 ? l:pasteType . l:pasteCmd : '')


if l:pasteName ==# 'Indented'
" This is a variant of forced linewise paste (glp) that uses ]p
" instead of p for pasting.
let l:pasteMappingDefaultKeys = ']' . l:pasteCmd
let l:pasteCmd = ']' . l:pasteCmd

" Define additional variations like with the built-in ]P.
if ! hasmapto('<Plug>UnconditionalPasteIndentBefore', 'n')
nmap g]P <Plug>UnconditionalPasteIndentedBefore
nmap g[P <Plug>UnconditionalPasteIndentedBefore
nmap g[p <Plug>UnconditionalPasteIndentedBefore
endif
endif
if l:pasteType ==# 'q' || l:pasteType ==# 'u' if l:pasteType ==# 'q' || l:pasteType ==# 'u'
" On repeat of one of the mappings that query, we want to skip " On repeat of one of the mappings that query, we want to skip
" the query and recall the last queried separator instead. " the query and recall the last queried separator instead.
let l:mappingName = 'UnconditionalPasteRecall' . l:pasteName . l:direction let l:mappingName = 'UnconditionalPasteRecall' . l:pasteName . l:direction
elseif l:pasteType ==# 'p' elseif l:pasteType ==? 'p'
" On repeat of the UnconditionalPastePlus mapping, we want to " On repeat of the UnconditionalPastePlus /
" continue increasing with the last used (saved) offset, and at " UnconditionalPasteGPlus mappings, we want to continue
" the same number position (after the first paste, the cursor " increasing with the last used (saved) offset, and at the same
" will have jumped to the beginning of the pasted text). " number position (after the first paste, the cursor will have
" jumped to the beginning of the pasted text).
let l:mappingName = 'UnconditionalPaste' . l:pasteName . 'Repeat' . l:direction let l:mappingName = 'UnconditionalPaste' . l:pasteName . 'Repeat' . l:direction
endif endif


execute printf('nnoremap <silent> %s :<C-u>' . execute printf('nnoremap <silent> %s :<C-u>' .
\ 'execute ''silent! call repeat#setreg("\<lt>Plug>%s", v:register)''<Bar>' . \ 'execute ''silent! call repeat#setreg("\<lt>Plug>%s", v:register)''<Bar>' .
\ 'if v:register ==# "="<Bar>' . \ 'if v:register ==# "="<Bar>' .
Expand All @@ -145,10 +172,9 @@ function! s:CreateMappings()
\ string(l:pasteCmd), \ string(l:pasteCmd),
\ l:mappingName \ l:mappingName
\) \)
if ! hasmapto(l:plugMappingName, 'n') && len(l:pasteType) == 1 if ! hasmapto(l:plugMappingName, 'n') && ! empty(l:pasteMappingDefaultKeys)
execute printf('nmap g%s%s %s', execute printf('nmap g%s %s',
\ l:pasteType, \ l:pasteMappingDefaultKeys,
\ l:pasteCmd,
\ l:plugMappingName \ l:plugMappingName
\) \)
endif endif
Expand Down

0 comments on commit 035ee5d

Please sign in to comment.