Vim Tips Wiki
(add new version that might replace tip)
(Change <tt> to <code>, perhaps also minor tweak.)
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
  +
{{TipNew
{{TipProposed
 
|id=0
+
|id=1593
|previous=0
+
|previous=1592
|next=0
+
|next=1594
|created=March 3, 2008
+
|created=2008
 
|complexity=basic
 
|complexity=basic
|author=Definite
+
|author=
 
|version=7.0
 
|version=7.0
 
|subpage=/200803
 
|subpage=/200803
Line 25: Line 25:
 
</pre>
 
</pre>
   
In Vim, put the cursor on the closing brace '<tt>}</tt>' in the following. Then press Ctrl-v.
+
In Vim, put the cursor on the closing brace '<code>}</code>' in the following. Then press Ctrl-v.
 
<pre>
 
<pre>
 
if (x==1){
 
if (x==1){
Line 37: Line 37:
 
printf("x=1");
 
printf("x=1");
 
if (y==1){
 
if (y==1){
printf("y=1");
+
printf("y=1");
 
}
 
}
 
}
 
}
Line 43: Line 43:
   
 
==Explanation==
 
==Explanation==
The command <tt>"+P</tt> pastes the system clipboard before the cursor position. The pasted text becomes the "last change" which sets mark <tt>'[</tt> to the beginning of the pasted text, and mark <tt>']</tt> to the end. After the <tt>P</tt> command, the cursor is at the <tt>'[</tt> mark, and the command <tt>=']</tt> applies the <tt>=</tt> filter to the pasted text (all lines from the cursor line to the line with the <tt>']</tt> mark, inclusive). Assuming the defaults, the <tt>=</tt> command applies the indent rules for the C language, or for the language of the current buffer, if your syntax rules have defined an indent expression. In insert mode, Ctrl-o (<tt><c-o></tt>) executes one normal-mode command, then returns to insert mode. See {{help|P}} {{help|tag='%5D|label='&#93;}} {{help|1==}} {{help|i_CTRL-O}}
+
The command <code>"+P</code> pastes the system clipboard before the cursor position. The pasted text becomes the "last change" which sets mark <code>'[</code> to the beginning of the pasted text, and mark <code>']</code> to the end. After the <code>P</code> command, the cursor is at the <code>'[</code> mark, and the command <code>=']</code> applies the <code>=</code> filter to the pasted text (all lines from the cursor line to the line with the <code>']</code> mark, inclusive). Assuming the defaults, the <code>=</code> command applies the indent rules for the C language, or for the language of the current buffer, if your syntax rules have defined an indent expression. In insert mode, Ctrl-o (<code><c-o></code>) executes one normal-mode command, then returns to insert mode.
   
  +
==References==
 
  +
*{{help|P}}
----
 
  +
*{{help|tag='%5D|label='&#93;}}
{{todo}}
 
  +
*{{help|1==}}
*I think the text above implements what this tip wants (but it's only had a very quick test).
 
  +
*{{help|i_CTRL-O}}
*Review the following. Does anything need to be kept? If not, delete it.
 
*Let me know (reply here) if I've missed some point. [[User:JohnBeckett|JohnBeckett]] 02:09, 24 March 2009 (UTC)
 
----
 
 
 
For people used to [[wikipedia:Common User Access|Common User Access]], the paste in Vim is neither intuitive nor convenient. <tt>]p</tt> and <tt>[p</tt> are usually mentioned as "smart paste". However, the smartness only works when the copy (yank) is from line visual mode. This does not apply when the copy is from another application such as a web browser.
 
 
Most applications use the system clipboard, which can be operated from the select mode of Vim. So I wrote the following script which pastes code from the clipboard smartly.
 
 
In [[vimrc]]:
 
<pre>
 
function! SmartPasteSelection(insertMode)
 
let s:old_col = col(".")
 
let s:old_lnum = line(".")
 
" Correct the cursor position
 
exec 'normal "+gP'
 
if a:insertMode
 
exec 'normal x'
 
endif
 
let s:after_col = col(".")
 
let s:after_col_end=col("$")
 
let s:after_col_offset=s:after_col_end-s:after_col
 
let s:after_lnum = line(".")
 
let s:cmd_str='normal V'
 
if s:old_lnum < s:after_lnum
 
let s:cmd_str=s:cmd_str . (s:after_lnum - s:old_lnum) . "k"
 
elseif s:old_lnum> s:after_lnum
 
let s:cmd_str=s:cmd_str . (s:old_lnum - s:after_lnum) . "j"
 
endif
 
let s:cmd_str=s:cmd_str . "="
 
exec s:cmd_str
 
let s:new_col_end=col("$")
 
call cursor(s:after_lnum, s:new_col_end-s:after_col_offset)
 
if a:insertMode
 
if s:after_col_offset <=1
 
exec 'startinsert!'
 
else
 
exec 'startinsert'
 
endif
 
endif
 
endfunction
 
 
" Use CTRL-V for pasting, also in Insert mode
 
nmap <C-V> :call SmartPasteSelection(0)<CR>
 
imap <C-V> #<Esc>:call SmartPasteSelection(1)<CR>
 
</pre>
 
   
 
==Comments==
 
==Comments==
Hi Definite &ndash; I'm including a couple of points raised in the [[Vim_Tips_Wiki:New_tips/200803#Smart_selection_mode_paste|discussion on March new tips]], with some further queries. I see that you recently edited the tip (thanks), so I'm hoping you will notice this comment and reply here with your views.
 
 
This tip looks potentially useful, but I don't think readers should have to decode the script to work out what the tip ''does''. We need an introductory paragraph describing what outcome is achieved by the tip, and what goes wrong when you copy from another application (that is, explain why the tip is needed).
 
 
I don't understand why the tip starts by talking about CUA. Why is that relevant? Perhaps you mean that Ctrl-V is the defacto standard for paste on some platforms (I don't think CUA has ever been extended to embrace Ctrl-V), and using 'p' in normal mode in Vim is therefore not intuitive?
 
 
Surely if you use <tt>set clipboard=unnamed</tt> then Vim's built-in paste would be very convenient for those who want easy access to the clipboard?
 
 
I am not familiar with the term "smart paste" so I had to study the tip to decide that it applies '=' to indent the pasted text (useful for code). Is that what is meant by "smart"? Is the point that you might be pasting some code that originally used (say) 3 spaces per indent, and you want it re-indented to match its new location (which might use 4 spaces per indent)?
 
 
Is the tip trying to deal with the situation that occurs with console Vim on some platforms where the indents on pasted text are lost? If so, is using 'pastetoggle' as outlined in [[VimTip906]] enough?
 
 
I am not a Vim script expert, but it seems to me that the 's:' used for each variable is not warranted. You could replace each 's:' with 'l:' because they are dynamic local variables. Since 'l:' is the default, I'm inclined to just omit the 's:' altogether. As I understand it, the only reason to use 'l:' would be to avoid conflict with a Vim 'v:' variable.
 
 
Also, it might be worth using the '.=' operator a few times to replace things like <tt>let a = a . b</tt> with <tt>let a .= b</tt>.
 
 
In your recent edit, you have the imap start by inserting '#'. I haven't studied the script enough to decide why you've done that, but in a quick test I found that the '#' was left in the text when pasting whole lines.
 
 
--[[User:JohnBeckett|JohnBeckett]] 09:13, 7 May 2008 (UTC)
 
----
 
 
Hi John,
 
Thanks for showing concern of my script.
 
I agree that mentioning "CUA" is a bit misleading, What I meant to say was: "People who used to mswin key binding". How about "mswin key binding" or whatever more appropriate?
 
 
The main propose of this script is to provide consistance of the current buffer you are editing, not actually keep the original format. Consider following example:
 
 
Copying following block
 
<table style="background-color:#cccccc; "><tr><td><pre>
 
if (a==b){
 
printf("a=b");
 
}
 
</pre></td></tr></table>
 
 
to your current editing buffer:
 
<table style="background-color:#cccccc; "><tr><td><pre>
 
if (c==b){
 
printf("c=b");
 
&lt;---
 
}
 
</pre></td></tr></table>
 
 
After copy, it should become :
 
<table style="background-color:#cccccc; "><tr><td><pre>
 
if (c==b){
 
printf("c=b");
 
if (a==b){
 
printf("a=b");
 
}
 
}
 
</pre></td></tr></table>
 
 
After some googling with the keyword "smart paste", none of the tips and scripts fit my need, so that's why I developed this script as "smart paste".
 
 
Character '#' in the start of imap line is a workaround solution for inserting at column 2.
 
The detail explanation is at: http://dingyichen.livejournal.com/2008/05/07/
 
 
I only start using vim for months, so I am new to vim script, Thanks for pointing out my error.
 
 
Regards,
 
 
Ding-Yi Chen
 

Latest revision as of 06:37, 13 July 2012

Tip 1593 Printable Monobook Previous Next

created 2008 · complexity basic · version 7.0


Here is a mapping that provides a "smart paste" to insert the system clipboard and automatically indent the pasted text. This is useful when pasting code from another application into the program you are working on. You could put the following lines in your vimrc:

:nnoremap <C-v> "+P=']
:inoremap <C-v> <C-o>"+P<C-o>=']

Example[]

Copy the following three lines to the clipboard (for example, you could use your web browser to copy the lines from this tip).

if (y==1){
printf("y=1");
}

In Vim, put the cursor on the closing brace '}' in the following. Then press Ctrl-v.

if (x==1){
    printf("x=1");
}

The above mapping will insert the clipboard and indent it, with result:

if (x==1){
    printf("x=1");
    if (y==1){
        printf("y=1");
    }
}

Explanation[]

The command "+P pastes the system clipboard before the cursor position. The pasted text becomes the "last change" which sets mark '[ to the beginning of the pasted text, and mark '] to the end. After the P command, the cursor is at the '[ mark, and the command ='] applies the = filter to the pasted text (all lines from the cursor line to the line with the '] mark, inclusive). Assuming the defaults, the = command applies the indent rules for the C language, or for the language of the current buffer, if your syntax rules have defined an indent expression. In insert mode, Ctrl-o (<c-o>) executes one normal-mode command, then returns to insert mode.

References[]

Comments[]