Small Changes

DockerコンテナのVimでヤンクした内容をWindowsホストのクリップボードへ共有する方法


Metadata


Dockerコンテナ上のVimでヤンクした内容をWindowsホストのクリップボードへ共有する方法がなかなか見つからず苦戦したのですが、やっと参考になる記事を見つけました。

参考記事ではsocatを使います。socatを初めて知ったのですが、TCPコネクションで待ち受けたり、TCPコネクションで通信したりできるようです。うまく動くようになったときにやったことを残しておきます。

WSL側の対応

ホストのWSL側ではsocatでヤンクした内容をTCPコネクションで待ち受ける必要があるため、WSLにsudo apt install socatsocatをインストールします。

次に、~/.bashrcに次の内容を追記します。WindowsのWSL環境では、echo 'hello world' | clip.exeでWindowsのクリップボードにデータを送信できますが、ここでも同じようにclip.exeに受け取ったデータを送信するようです。

bashrc

  • if [[ $(command -v socat > /dev/null; echo $?) == 0 ]]; then
        # Start up the socat forwarder to clip.exe
        ALREADY_RUNNING=$(ps -auxww | grep -q "[l]isten:8121"; echo $?)
        if [[ $ALREADY_RUNNING != "0" ]]; then
            echo "Starting clipboard relay..."
            (setsid socat tcp-listen:8121,fork,bind=0.0.0.0 EXEC:'clip.exe' &) > /dev/null 2>&1
        else
            echo "Clipboard relay already running"
        fi
    fi

以降、WSLのターミナルを開くたびにsocatでTCPコネクションを待ち受けるようになります。

  • ポート番号は任意ですが参考記事と一緒にしています。

Docker側の対応

Docker側でもsocatを使うのでsudo apt install socatでインストールします。

次に、socatのTCPコネクションに送信するためのclip.shファイルを作成します。

echo "hello from clip.sh" | clip.sh -iのような使い方をします。この時点でホストのWSLのsocatにデータが送られてWindowsのクリップボードにコピーされます。

clip.sh

  • #!/bin/bash
    for i in "$@"
    do
      case "$i" in
      (-i|--input|-in)
        tee <&0 | socat - tcp:host.docker.internal:8121
        exit 0
        ;;
      esac
    done

vimrcは下記設定を追加します。ヤンクしたときに先ほどのclip.shにデータを送るので、それがホストのWSLのsocatにデータが送られてWindowsのクリップボードにコピーされます。

vimrc

" ヤンクした内容をクリップボードにコピー
augroup Yank
  au!
  autocmd TextYankPost * :call system('clip.sh -i', @")
augroup END

これで念願の『DockerコンテナのVimでヤンクした内容をWindowsホストのクリップボードへ共有する』ことができました。記事の作者様に感謝します。

References