blog

12020-05-14

SEAN K.H. LIAO

OSC 52

ever yanked something in nvim, switched to another window to paste, then remembered the nvim was through ssh and it didn't share a clipboard with your system?

First discovered while reading through the chrome ssh / hterm faq, OSC 52 uses escape sequences to let you send things through to the local clipboard. Requires a terminal emulator support.

testing for support

run the following in an ssh session

copypasta! should appear in your local clipboard ready for pasting

printf "\033]52;c;Y29weXBhc3RhIQ==\a\n"

vim plugins

neovim

The vim plugins didn't work when i tested them, looking at the neovim issues, 8450 stood out. That script basically worked, but requires an extra script outside. Available gist

or slightly simplified

in init.nvim with set clipboard=unnamedplus

let g:clipboard = {
     \ 'name': 'myClipboard',
     \     'copy': {
     \         '+': 'clipboard-provider copy',
     \     },
     \     'paste': {
     \         '+': 'clipboard-provider paste',
     \     },
     \ }

in $PATH

#!/bin/bash
#
# clipboard provider for neovim
#
# :help provider-clipboard

#exec 2>> ~/clipboard-provider.out
#set -x

: ${COPY_PROVIDERS:=tmux osc52}
: ${PASTE_PROVIDERS:=tmux}
: ${TTY:=`(tty || tty </proc/$PPID/fd/0) 2>/dev/null | grep /dev/`}

main() {
    declare p status=99

    case $1 in
        copy)
            slurp
            for p in $COPY_PROVIDERS; do
                $p-provider copy && status=0
            done ;;

        paste)
            for p in $PASTE_PROVIDERS; do
                $p-provider paste && status=0 && break
            done ;;
    esac

    exit $status
}

# N.B. buffer is global for simplicity
slurp() { buffer=$(base64); }
spit() { base64 --decode <<<"$buffer"; }

tmux-provider() {
    [[ -n $TMUX ]] || return
    case $1 in
        copy) spit | tmux load-buffer - ;;
        paste) tmux save-buffer - ;;
    esac
}

osc52-provider() {
    case $1 in
        copy) [[ -n "$TTY" ]] && printf $'\e]52;c;%s\a' "$buffer" > "$TTY" ;;
        paste) return 1 ;;
    esac
}

main "$@"