Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Version 2.00

- ENH: Add g,p / gqp / gQp mappings to paste lines flattened with comma, queried, or recalled last used delimiter.
- ENH: Add gup / gUp mappings to paste unjoined register with queried or recalled last used delimiter pattern.
- ENH: Add CTRL-R CTRL-C mapping to insert register contents characterwise (flattened) from insert mode, and similar insert mode mappings for the other new mappings.
- CHG: Flatten all whitespace and newlines before, after, and around lines when pasting characterwise or joined.
  • Loading branch information...
commit cc5f809b3d76f55c0e808aa8c0dd2e6f4f18bdc0 1 parent 3181826
Ingo Karkat authored committed
View
102 autoload/UnconditionalPaste.vim
@@ -11,6 +11,19 @@
" http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste
"
" REVISION DATE REMARKS
+" 2.00.018 07-Dec-2012 FIX: Differentiate between pasteType and a:how
+" argument, as setregtype() only understands the
+" former.
+" 2.00.017 06-Dec-2012 CHG: Flatten all whitespace and newlines before,
+" after, and around lines when pasting
+" characterwise or joined.
+" 2.00.016 05-Dec-2012 ENH: Add mappings to insert register contents
+" characterwise (flattened) from insert mode.
+" ENH: Add mappings to paste lines flattened with
+" comma, queried, or recalled last used delimiter.
+" ENH: Add mappings to paste unjoined register
+" with queried or recalled last used delimiter
+" pattern.
" 1.22.015 04-Dec-2012 Split off functions into autoload script.
" 1.22.014 28-Nov-2012 BUG: When repeat.vim is not installed, the
" mappings do nothing. Need to :execute the
@@ -65,16 +78,24 @@ function! UnconditionalPaste#HandleExprReg( exprResult )
let s:exprResult = a:exprResult
endfunction
-function! s:Flatten( text )
- " Remove newline characters at the end of the text, convert all other
- " newlines to a single space.
- return substitute(substitute(a:text, '\n\+$', '', 'g'), '\n\+', ' ', 'g')
+function! s:Flatten( text, separator )
+ " Remove newlines and whitespace at the begin and end of the text, convert
+ " all other newlines (plus leading and trailing whitespace) to the passed
+ " separator.
+ return substitute(substitute(a:text, '^\s*\%(\n\s*\)*\|\s*\%(\n\s*\)*$', '', 'g'), '\s*\%(\n\s*\)\+', a:separator, 'g')
endfunction
function! s:StripTrailingWhitespace( text )
return substitute(a:text, '\s\+\ze\(\n\|$\)', '', 'g')
endfunction
+function! s:Unjoin( text, separatorPattern )
+ let l:text = substitute(a:text, a:separatorPattern, '\n', 'g')
-function! UnconditionalPaste#Paste( regName, pasteType, pasteCmd )
+ " A (single!) trailing separator is automatically swallowed by the linewise
+ " pasting. For consistency, do the same for a single leading separator.
+ return (l:text =~# '^\n' ? l:text[1:] : l:text)
+endfunction
+
+function! UnconditionalPaste#Paste( regName, how, ... )
let l:regType = getregtype(a:regName)
let l:regContent = getreg(a:regName, 1) " Expression evaluation inside function context may cause errors, therefore get unevaluated expression when a:regName ==# '='.
@@ -97,19 +118,65 @@ function! UnconditionalPaste#Paste( regName, pasteType, pasteCmd )
try
let l:pasteContent = l:regContent
- if a:pasteType ==# 'c'
+ let l:pasteType = 'l'
+
+ if a:how ==# 'b'
+ let l:pasteType = 'b'
+ elseif a:how =~# '^[c,qQ]$'
+ let l:pasteType = 'c'
+
if l:regType[0] ==# "\<C-v>"
- let l:pasteContent = s:Flatten(s:StripTrailingWhitespace(l:regContent))
+ let l:pasteContent = s:StripTrailingWhitespace(l:regContent)
+ else
+ let l:pasteContent = l:regContent
+ endif
+
+ if a:how ==# 'c'
+ let l:separator = ' '
+ elseif a:how ==# ','
+ let l:separator = ', '
+ elseif a:how ==# 'q'
+ let l:separator = input('Enter separator string: ')
+ if empty(l:separator)
+ execute "normal! \<C-\>\<C-n>\<Esc>" | " Beep.
+ return ''
+ endif
+ let g:UnconditionalPaste_JoinSeparator = l:separator
+ elseif a:how ==# 'Q'
+ let l:separator = g:UnconditionalPaste_JoinSeparator
else
- let l:pasteContent = s:Flatten(l:regContent)
+ throw 'ASSERT: Invalid how: ' . string(a:how)
endif
- elseif a:pasteType ==# 'l' && l:regType[0] ==# "\<C-v>"
+ let l:pasteContent = s:Flatten(l:pasteContent, l:separator)
+ elseif a:how ==? 'u'
+ if a:how ==# 'u'
+ let l:separatorPattern = input('Enter separator pattern: ')
+ if empty(l:separatorPattern)
+ execute "normal! \<C-\>\<C-n>\<Esc>" | " Beep.
+ return ''
+ endif
+ let g:UnconditionalPaste_UnjoinSeparatorPattern = l:separatorPattern
+ endif
+
+ let l:pasteContent = s:Unjoin(l:pasteContent, g:UnconditionalPaste_UnjoinSeparatorPattern)
+ if l:pasteContent ==# l:regContent
+ " No unjoining took place; this is probably not what the user
+ " intended (maybe wrong register?), so don't just insert the
+ " contents unchanged, but rather alert the user.
+ execute "normal! \<C-\>\<C-n>\<Esc>" | " Beep.
+ return ''
+ endif
+ elseif a:how ==# 'l' && l:regType[0] ==# "\<C-v>"
let l:pasteContent = s:StripTrailingWhitespace(l:regContent)
endif
- call setreg(l:regName, l:pasteContent, a:pasteType)
- execute 'normal! "' . l:regName . (v:count ? v:count : '') . a:pasteCmd
- call setreg(l:regName, l:regContent, l:regType)
+ if a:0
+ call setreg(l:regName, l:pasteContent, l:pasteType)
+ execute 'normal! "' . l:regName . (v:count ? v:count : '') . a:1
+ call setreg(l:regName, l:regContent, l:regType)
+ else
+ return l:pasteContent
+ endif
catch /^Vim\%((\a\+)\)\=:E/
" v:exception contains what is normally in v:errmsg, but with extra
" exception source info prepended, which we cut away.
@@ -124,5 +191,16 @@ function! UnconditionalPaste#Paste( regName, pasteType, pasteCmd )
endif
endtry
endfunction
+function! UnconditionalPaste#Insert( regName, how )
+ if a:regName !~? '[0-9a-z"%#*+:.-]'
+ " Note the lack of "="; we don't support the expression register here,
+ " because we would need to do the querying and evaluation all by
+ " ourselves.
+ execute "normal! \<C-\>\<C-n>\<Esc>" | " Beep.
+ return ''
+ endif
+
+ return UnconditionalPaste#Paste(a:regName, a:how)
+endfunction
" vim: set ts=8 sts=4 sw=4 noexpandtab ff=unix fdm=syntax :
View
120 doc/UnconditionalPaste.txt
@@ -17,24 +17,85 @@ DESCRIPTION *UnconditionalPaste-description*
If you're like me, you occasionally do a linewise yank, and then want to
insert that yanked text in the middle of some other line (or vice versa).
The mappings defined by this plugin will allow you to do a character-, line-,
-or block-wise paste no matter how you yanked the text.
+or block-wise paste no matter how you yanked the text, both from normal and
+insert mode.
+
+Often, the register contents aren't quite in the form you need them. Maybe you
+need to convert yanked lines to comma-separated arguments, maybe join the
+lines with another separator, maybe the reverse: un-joining a single line on
+some pattern to yield multiple lines. Though you can do the manipulation after
+pasting, this plugin offers shortcut mappings for these actions, which are
+especially helpful when you need to repeat the paste multiple times.
SOURCE *
Based on vimtip #1199 by cory,
http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste
+RELATED WORKS *
+
+- whitespaste.vim (vimscript #4351) automatically removes blank lines around
+ linewise contents, and condenses inner lines to a single one. By default, it
+ remaps p / P, but this can be changed.
+
==============================================================================
USAGE *UnconditionalPaste-usage*
- *gcp* *gcP* *glp* *glP* *gbp* *gbP*
-["x]gcp Paste characterwise (newline characters are flattened
-["x]gcP to spaces) [count] times.
-["x]glp Paste linewise (even if yanked text is not a complete
-["x]glP line) [count] times.
-["x]gbp Paste blockwise (inserting multiple lines in-place,
-["x]gbP pushing existing text further to the right) [count]
+ *gcp* *gcP*
+["x]gcp, ["x]gcP Paste characterwise (newline characters and indent are
+ flattened to spaces) [count] times.
+ *glp* *glP*
+["x]glp, ["x]glP Paste linewise (even if yanked text is not a complete
+ line) [count] times.
+ *gbp* *gbP*
+["x]gbp, ["x]gbP Paste blockwise (inserting multiple lines in-place,
+ pushing existing text further to the right) [count]
times.
+ *g,p* *g,P*
+["x]g,p, ["x]g,P Paste characterwise, with each line delimited by ", "
+ instead of the newline (and indent).
+ *gqp* *gqP*
+["x]gqp, ["x]gqP Query for a separator string, then paste
+ characterwise, with each line delimited by it.
+ *gQp* *gQP*
+["x]gQp, ["x]gQP Paste characterwise, with each line delimited by the
+ previously queried (|gqp|) separator string.
+
+ *gup* *guP*
+["x]gup, ["x]guP Query for a separator pattern, un-join the register
+ contents, then paste linewise.
+ *gUp* *gUP*
+["x]gUp, ["x]gUP Un-join the register contents on the previously
+ queried (|gup|) separator pattern, then paste
+ linewise.
+
+
+CTRL-R CTRL-C {0-9a-z"%#*+/:.-} *i_CTRL-R_CTRL-C*
+ Insert the contents of a register characterwise
+ (newline characters and indent are flattened to
+ spaces).
+ If you have options like 'textwidth', 'formatoptions',
+ or 'autoindent' set, this will influence what will be
+ inserted.
+CTRL-R , {0-9a-z"%#*+/:.-} *i_CTRL-R_,*
+ Insert the contents of a register characterwise, with
+ each line delimited by ", " instead of the newline
+ (and indent).
+CTRL-R CTRL-Q {0-9a-z"%#*+/:.-} *i_CTRL-R_CTRL-Q*
+ Query for a separator string, then insert the contents
+ of a register characterwise, with each line delimited
+ by it.
+CTRL-R CTRL-Q CTRL-Q {0-9a-z"%#*+/:.-} *i_CTRL-R_CTRL-Q_CTRL-Q*
+ Insert the contents of a register characterwise, with
+ each line delimited by the previously queried (|gqp|,
+ |i_CTRL-R_CTRL-Q|) separator string.
+CTRL-R CTRL-U {0-9a-z"%#*+/:.-} *i_CTRL-R_CTRL-U*
+ Query for a separator pattern, un-join the contents of
+ a register, then insert it linewise.
+CTRL-R CTRL-U CTRL-U {0-9a-z"%#*+/:.-} *i_CTRL-R_CTRL-U_CTRL-U*
+ Un-join the contents of
+ a register on the previously queried (|gup|,
+ |i_CTRL_R_CTRL-U|) pattern, then insert it linewise.
==============================================================================
INSTALLATION *UnconditionalPaste-installation*
@@ -55,6 +116,21 @@ DEPENDENCIES *UnconditionalPaste-dependencies*
==============================================================================
CONFIGURATION *UnconditionalPaste-configuration*
+For a permanent configuration, put the following commands into your |vimrc|:
+ *g:UnconditionalPaste_JoinSeparator*
+The default separator string for the |gQp| and |i_CTRL-R_CTRL-Q_CTRL-Q|
+mappings is a <Tab> character; to preset another one (it will be overridden by
+|gqp| and |i_CTRL-R_CTRL-Q|), use: >
+ let g:UnconditionalPaste_JoinSeparator = 'text'
+<
+ *g:UnconditionalPaste_UnjoinSeparatorPattern*
+The default separator pattern for the |gUp| and |i_CTRL-R_CTRL-U_CTRL-U|
+mappings matches any whitespace and newlines (i.e. it will get rid of empty
+lines); to preset another one (it will be overridden by |gup| and
+|i_CTRL-R_CTRL-U|), use: >
+ let g:UnconditionalPaste_UnjoinSeparatorPattern = '-'
+<
+ *UnconditionalPaste-remap*
If you want to use different mappings (e.g. starting with <Leader>), map your
keys to the <Plug>UnconditionalPaste... mapping targets _before_ sourcing this
script (e.g. in your |vimrc|): >
@@ -64,6 +140,23 @@ script (e.g. in your |vimrc|): >
nmap <Leader>pl <Plug>UnconditionalPasteLineAfter
nmap <Leader>Pb <Plug>UnconditionalPasteBlockBefore
nmap <Leader>pb <Plug>UnconditionalPasteBlockAfter
+ nmap <Leader>P, <Plug>UnconditionalPasteCommaBefore
+ nmap <Leader>p, <Plug>UnconditionalPasteCommaAfter
+ nmap <Leader>Pq <Plug>UnconditionalPasteQueriedBefore
+ nmap <Leader>pq <Plug>UnconditionalPasteQueriedAfter
+ nmap <Leader>PQ <Plug>UnconditionalPasteRecallQueriedBefore
+ nmap <Leader>pQ <Plug>UnconditionalPasteRecallQueriedAfter
+ nmap <Leader>Pu <Plug>UnconditionalPasteUnjoinBefore
+ nmap <Leader>pu <Plug>UnconditionalPasteUnjoinAfter
+ nmap <Leader>PU <Plug>UnconditionalPasteRecallUnjoinBefore
+ nmap <Leader>pU <Plug>UnconditionalPasteRecallUnjoinAfter
+
+ imap <C-G>c <Plug>UnconditionalPasteChar
+ imap <C-G>, <Plug>UnconditionalPasteComma
+ imap <C-G>q <Plug>UnconditionalPasteQueried
+ imap <C-G>Q <Plug>UnconditionalPasteRecallQueried
+ imap <C-G>u <Plug>UnconditionalPasteUnjoin
+ imap <C-G>U <Plug>UnconditionalPasteRecallUnjoin
<
==============================================================================
LIMITATIONS *UnconditionalPaste-limitations*
@@ -77,6 +170,17 @@ IDEAS *UnconditionalPaste-ideas*
==============================================================================
HISTORY *UnconditionalPaste-history*
+2.00 05-Dec-2012
+- ENH: Add g,p / gqp / gQp mappings to paste lines flattened with comma,
+ queried, or recalled last used delimiter.
+- ENH: Add gup / gUp mappings to paste unjoined register with queried or
+ recalled last used delimiter pattern.
+- ENH: Add CTRL-R CTRL-C mapping to insert register contents characterwise
+ (flattened) from insert mode, and similar insert mode mappings for the other
+ new mappings.
+- CHG: Flatten all whitespace and newlines before, after, and around lines
+ when pasting characterwise or joined.
+
1.22 04-Dec-2012
- BUG: When repeat.vim is not installed, the mappings do nothing. Need to
:execute the :silent! call of repeat.vim to avoid that the remainder of the
View
78 plugin/UnconditionalPaste.vim
@@ -14,6 +14,13 @@
" http://vim.wikia.com/wiki/Unconditional_linewise_or_characterwise_paste
"
" REVISION DATE REMARKS
+" 2.00.016 05-Dec-2012 ENH: Add mappings to insert register contents
+" characterwise (flattened) from insert mode.
+" ENH: Add mappings to paste lines flattened with
+" comma, queried, or recalled last used delimiter.
+" ENH: Add mappings to paste unjoined register
+" with queried or recalled last used delimiter
+" pattern.
" 1.22.015 04-Dec-2012 Split off functions into autoload script.
" 1.22.014 28-Nov-2012 BUG: When repeat.vim is not installed, the
" mappings do nothing. Need to :execute the
@@ -73,24 +80,48 @@ let g:loaded_UnconditionalPaste = 1
let s:save_cpo = &cpo
set cpo&vim
+"- configuration ---------------------------------------------------------------
+
+if ! exists('g:UnconditionalPaste_JoinSeparator')
+ let g:UnconditionalPaste_JoinSeparator = "\t"
+endif
+if ! exists('g:UnconditionalPaste_UnjoinSeparatorPattern')
+ let g:UnconditionalPaste_UnjoinSeparatorPattern = '\_s\+'
+endif
+
+
+
+"- mappings --------------------------------------------------------------------
+
function! s:CreateMappings()
- for [l:pasteName, pasteType] in [['Char', 'c'], ['Line', 'l'], ['Block', 'b']]
+ for [l:pasteName, pasteType] in
+ \ [
+ \ ['Char', 'c'], ['Line', 'l'], ['Block', 'b'], ['Comma', ','],
+ \ ['Queried', 'q'], ['RecallQueried', 'Q'],
+ \ ['Unjoin', 'u'], ['RecallUnjoin', 'U']
+ \ ]
for [l:direction, l:pasteCmd] in [['After', 'p'], ['Before', 'P']]
let l:mappingName = 'UnconditionalPaste' . l:pasteName . l:direction
let l:plugMappingName = '<Plug>' . l:mappingName
+
+ if l:pasteType ==# '/'
+ " On repeat of the UnconditionalPasteQueried mapping, we want to
+ " skip the query and recall the last queried separator instead.
+ let l:mappingName = 'UnconditionalPasteRecalled' . l:direction
+ endif
execute printf('nnoremap <silent> %s :<C-u>' .
- \ 'execute ''silent! call repeat#setreg("\<lt>Plug>%s", v:register)''<Bar>' .
- \ 'if v:register ==# "="<Bar>' .
- \ ' call UnconditionalPaste#HandleExprReg(getreg("="))<Bar>' .
- \ 'endif<Bar>' .
- \ 'call UnconditionalPaste#Paste(v:register, %s, %s)<Bar>' .
- \ 'silent! call repeat#set("\<lt>Plug>%s")<CR>',
+ \ 'execute ''silent! call repeat#setreg("\<lt>Plug>%s", v:register)''<Bar>' .
+ \ 'if v:register ==# "="<Bar>' .
+ \ ' call UnconditionalPaste#HandleExprReg(getreg("="))<Bar>' .
+ \ 'endif<Bar>' .
+ \ 'call UnconditionalPaste#Paste(v:register, %s, %s)<Bar>' .
+ \ 'silent! call repeat#set("\<lt>Plug>%s")<CR>',
\
- \ l:plugMappingName,
- \ l:mappingName,
- \ string(l:pasteType),
- \ string(l:pasteCmd),
- \ l:mappingName
+ \ l:plugMappingName,
+ \ l:mappingName,
+ \ string(l:pasteType),
+ \ string(l:pasteCmd),
+ \ l:mappingName
\)
if ! hasmapto(l:plugMappingName, 'n')
execute printf('nmap g%s%s %s',
@@ -101,6 +132,29 @@ function! s:CreateMappings()
endif
endfor
endfor
+
+ for [l:pasteName, pasteType, pasteKey] in
+ \ [
+ \ ['Char', 'c', '<C-c>'], ['Comma', ',', ','],
+ \ ['Queried', 'q', '<C-q>'], ['RecallQueried', 'Q', '<C-q><C-q>'],
+ \ ['Unjoin', 'u', '<C-u>'], ['RecallUnjoin', 'U', '<C-u><C-u>']
+ \ ]
+ let l:plugMappingName = '<Plug>UnconditionalPaste' . l:pasteName
+ " XXX: Can only use i_CTRL-R here (though I want literal insertion, not
+ " as typed); i_CTRL-R_CTRL-R with the expression register cannot insert
+ " newlines (^@ are inserted), and i_CTRL-R_CTRL-O inserts above the
+ " current line when the register ends with a newline.
+ execute printf('inoremap <silent> %s <C-r>=UnconditionalPaste#Insert(nr2char(getchar()), %s)<CR>',
+ \ l:plugMappingName,
+ \ string(l:pasteType)
+ \)
+ if ! hasmapto(l:plugMappingName, 'i')
+ execute printf('imap <C-r>%s %s',
+ \ l:pasteKey,
+ \ l:plugMappingName
+ \)
+ endif
+ endfor
endfunction
call s:CreateMappings()
delfunction s:CreateMappings
Please sign in to comment.
Something went wrong with that request. Please try again.