19

I'd like to be able to paste from the system clipboard (or text selection) into my "vi-like" shell prompt using the keyboard. I normally use zsh and sometimes bash. In both cases, I have the shell set up with vi-like behaviour (bindkey -v / set -o vi).

In vim, the behaviour I'm looking for is available with the key sequence "+p. This particular key sequence doesn't work as expected in a vi-enabled shell prompt, though. Is there any way to either enable this or a similar behaviour, using keyboard only, while remaining with vi-like keybindings in a zsh or bash shell prompt?

-- edit --

Usage case: I often navigate between Firefox with the Pentadactyl addon, a terminal emulator and vim itself - using the Xmonad window manager with custom keys to move around. All three programs have vi-like keybindings, which is very efficient (for "finger memory") so it would be ideal communicate text between them using vim syntax (or a very similar syntax) only.

5 Answers 5

11

Zsh doesn't support anything but internal registers, and bash doesn't support register at all as far as I know. By and large, shells support vi commands, not vim commands.

In zsh, here's a proof-of-concept for accessing the X selection from command mode. For real use you'd want to elaborate on these techniques. I use the xsel program, you can use xclip instead; see How to copy from one vim instance to another using registers. You'll find the features I used in the zle manual.

vi-append-x-selection () { RBUFFER=$(xsel -o -p </dev/null)$RBUFFER; }
zle -N vi-append-x-selection
bindkey -a '^X' vi-append-x-selection
vi-yank-x-selection () { print -rn -- $CUTBUFFER | xsel -i -p; }
zle -N vi-yank-x-selection
bindkey -a '^Y' vi-yank-x-selection

The function vi-append-x-selection inserts the current X selection after the cursor (similar to p or P). The function vi-yank-x-selection copies the last killed or yanked text to the X selection. zle -N declares the functions as zle widgets (i.e. edition commands). bindkey -a sets bindings for vi command mode.

2
  • This worked perfectly after installing xsel and copying your suggested code with a slight modification to my .zshrc (I chose '^P' instead of '^X', overwriting the original behaviour of '^P')
    – Dalker
    Dec 1, 2011 at 6:23
  • Many thanks for your answer @Gilles 'SO- stop being evil'. I tried to implement your answer without success. I posted a question with what I tried so far: unix.stackexchange.com/questions/703946/… . Do you have any idea about what am I doing wrong?
    – ecjb
    May 26, 2022 at 14:48
6

Here is a solution for zsh (vi mode) that wraps the original widgets so the clipboard always is synchronized

Replace xclip with your preferred clipboard tool.

function x11-clip-wrap-widgets() {
    # NB: Assume we are the first wrapper and that we only wrap native widgets
    # See zsh-autosuggestions.zsh for a more generic and more robust wrapper
    local copy_or_paste=$1
    shift

    for widget in $@; do
        # Ugh, zsh doesn't have closures
        if [[ $copy_or_paste == "copy" ]]; then
            eval "
            function _x11-clip-wrapped-$widget() {
                zle .$widget
                xclip -in -selection clipboard <<<\$CUTBUFFER
            }
            "
        else
            eval "
            function _x11-clip-wrapped-$widget() {
                CUTBUFFER=\$(xclip -out -selection clipboard)
                zle .$widget
            }
            "
        fi

        zle -N $widget _x11-clip-wrapped-$widget
    done
}


local copy_widgets=(
    vi-yank vi-yank-eol vi-delete vi-backward-kill-word vi-change-whole-line
)
local paste_widgets=(
    vi-put-{before,after}
)

# NB: can atm. only wrap native widgets
x11-clip-wrap-widgets copy $copy_widgets
x11-clip-wrap-widgets paste  $paste_widgets
2
  • This works like a charm in xterm-termite.
    – Rotareti
    Jan 29, 2018 at 5:21
  • Seems to work great and also with tmux!
    – ecjb
    May 28, 2022 at 8:39
4

There's a ZSH plugin I'd recommend: https://github.com/kutsan/zsh-system-clipboard . To install it, run:

git clone https://github.com/kutsan/zsh-system-clipboard ~/.zsh/plugins/zsh-system-clipboard

And then source the file in your .zshrc:

source "$HOME/.zsh/plugins/zsh-system-clipboard/zsh-system-clipboard.zsh"

The plugin supports using Tmux' buffers to locate where the clipboard is saved, and you can even configure alternative keybindings for the functions that cut / paste / copy.

One slight detail the plugin has taken care of, which the other answers suggested don't, is differentiating between system clipboard contents with and without new lines (see PR). This small checks of the clipboard input, should ensure the experience of pasting any type of content is identical to that of Vim/Neovim.

1
  • I added it as a oh-my-zsh plugin, and it worked directly. Excellent, thanks! Feb 5, 2021 at 17:27
3

Selection and clipboard are different things under X Window, and IMHO "desktop environments" tend to make the issue even more murky than it was.

Does shift-insert work for you? On bare X applications, it is bound to pasting the selection when such a binding is made.

2
  • Selection and clipboard being different is not really relevant here, a solution that works with one would be easy to adapt to the other. Desktop environments don't change a thing; their spread has accompanied a shift in the balance of power away from selection and towards the clipboard. Dec 1, 2011 at 1:41
  • shift-insert does work in my environment, and it's definitely good to know, for use when in a different system. I'm looking however for something closer to actual vim keybindings for yank and/or paste between terminals, vim itself and other programs
    – Dalker
    Dec 1, 2011 at 6:20
1

This solution works if you have installed oh-my-zsh and enabled the vi-mode plugin.

Gilles' xsel and zle based solution didn't work for me. However, since I have configured vim to use my system clipboard by default (set clipboard=unnamedplus in ~/.vimrc), I simply type v in terminal normal mode to open the current command in vim and then I can copy it to the X-clipboard with any of the vim yank commands.

4
  • How is this related to ZSH? Are you talking about the embedded :term available in the new versions of Neovim and Vim? Aug 27, 2018 at 9:05
  • @DoronBehar If you have vi-mode enabled in zsh, you can type v in normal mode to edit the currently typed command inside vim instead of at the terminal prompt. Aug 27, 2018 at 14:51
  • You should mention the fact that you are talking about Neovim's and Vim's :term feature in your answer, otherwise it's not clear at all. Aug 27, 2018 at 18:10
  • @DoronBehar I am not talking about :term. However, I did discover that the functionality I am referring to is actually provided by oh-my-zsh. I have updated the answer accordingly. Aug 27, 2018 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.