Jonatan Littke
Jonatan Littke

Reputation: 5663

Pasting from the clipboard and automatically toggling ":set paste"

When I paste things from the clipboard, they're normally (always) multilined, and in those cases (and those cases only), I'd like :set paste to be triggered, since otherwise the tabbing will increase with each line (you've all seen it!).

Though the problem with :set paste is that it doesn't behave well with set smartindent, causing the cursor to jump to the beginning of a new line instead of at the correct indent. So I'd like to enable it for this instance only.

I'm using Mac, sshing to a Debian machine with Vim, and thus pasting in Insert mode using cmd + v.

Upvotes: 19

Views: 28423

Answers (5)

SergioAraujo
SergioAraujo

Reputation: 11820

We can paste (insert mode) without messing up indentation using

Ctrl-r Ctrl-o Register
Ctrl-r Ctrl-o +
Ctrl-r Ctrl-o *
Ctrl-r Ctrl-o 0
CTRL-R CTRL-O {0-9a-z"%#*+/:.-=}            *i_CTRL-R_CTRL-O*
Insert the contents of a register literally and don't
auto-indent.  Does the same as pasting with the mouse
"MiddleMouse". When the register is linewise this will
insert the text above the current line, like with `P`.
Does not replace characters!
The '.' register (last inserted text) is still inserted as
typed.

Upvotes: 0

Bruno Bronosky
Bruno Bronosky

Reputation: 70439

This ought to be solvable with a Vim script. (I hate Vim scripting, so it would have to be a much more serious infliction to cause me to solve it myself.) Even with iTerm2's "paste slowly" mode, the default is to break the data to be pasted into 16 byte chunks and send one every 0.125 seconds. Therefore, you should be able to programmatically detect a 16 byte chunk of "keystrokes" and do something about it.

In pseudocode that would look like:

if too_fast_too_be_human():
    set('pastemode', True)
else
    set('pastemode', False)

# where either
def too_fast_too_be_human
    char_threshold = 16
    return len(input_buffer) > char_threshold

# or
def too_fast_too_be_human
    static byte_times = []
    char_threshold = 16
    time_threshold = 0.125
    byte_times.append(now())
    while(len(byte_times) > char_threshold):
        byte_times.unshift()
    return (byte_times[-1] - byte_times[0]) < time_threshold

There are weaknesses to that, but it would work for most cases.

Upvotes: 0

Maxim Kim
Maxim Kim

Reputation: 6392

I have the following in my .vimrc:

inoremap <S-Insert> <ESC>:setl paste<CR>gi<C-R>+<ESC>:setl nopaste<CR>gi

gi is to start insert mode in the same position as where insert mode was stopped last time in the current buffer.

Update:

Jefromi posted a better solution. I have tinkered it a bit

inoremap <S-Insert> <ESC>"+p`]a

It inserts clipboard text and places the cursor right after it.

Upvotes: 3

Cascabel
Cascabel

Reputation: 497322

I don't use a mac, but I believe I have the prefix right here: <D-v> should mean cmd-v. For insert mode:

:imap <D-v> ^O:set paste<Enter>^R+^O:set nopaste<Enter>

or really, just do this:

:imap <D-V> ^O"+p

The ^O and ^R are literal control-O and control-R, which you can type with ^V^O (control-v control-o) and ^V^R (control-v control-r). Control-O in insert mode allows you to execute one command then return to insert mode; here you can use it to put from the clipboard register.

This worked for me when I tested them mapped to a different key, so you should be all set.

There's no need to map anything when not in insert mode; you can just use "+p.

Upvotes: 7

jamessan
jamessan

Reputation: 42737

You're right in that you should only enable 'paste' when you need it. It does more than just affect indenting. You can read everything that it affects in its documentation. A related option that is very useful to ease the use of 'paste' is 'pastetoggle'.

If you were using X-forwarding and a terminal that can properly communicate mouse actions, you could also take advantage of the 'mouse' option. With :set mouse=a, Vim is made aware of what the mouse is doing and therefore won't perform automatic indentation when it receives a multi-line paste via a middle-button mouse click.

Even without the mouse capability, X-forwarding could help because Vim will do the same thing when manually pasting from the clipboard or selection registers ("+ and "* respectively).

Upvotes: 1

Related Questions