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

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

参考: https://stuartleeks.com/posts/vscode-devcontainer-clipboard-forwarding/

参考記事では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 ホストのクリップボードへ共有する』ことができました。記事の作者様に感謝します。

Hugo で構築されています。
テーマ StackJimmy によって設計されています。