4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SSH接続先で開いたtmuxペイン上で動いているemacsとクリップボードを共有する

Posted at

私は普段リモートサーバーにSSHして、emacs + tmux環境で作業をしています。

その時に、emacsのコードをローカルのクリップボードにコピーしたかったり、逆にローカルでコピーしたコードをリモートのemacsにペーストしたいということがよくあります。

最近になってようやく解を見つけたので、紹介したいと思います。

環境について

  • クライアント
    • Windows 10
    • ターミナルとしてWSL1 (Penguin)を使用
    • X clientはX410
  • サーバ
    • CentOS 6.9
    • emacsclient 26.3
    • tmux 2.3
    • xsel 1.2.0

方法

emacs(client), tmux, xselはそれぞれサーバに入っている前提です。また、SSH接続する際にはX11 Forwardingを有効にしてあります(alias ssh='ssh -X'でも、~/.ssh/configで書くもよしです)。

以前に書いた記事で詳しく紹介しておりますが、tmuxは今開かれている環境変数を返すtmux showenvコマンドというものがあります。これで返して来た環境変数を使ってxselコマンドを動かしてあげることによって、実現可能です。

具体的には

hoge | env $(tmux showenv DISPLAY) xsel -bi

のようにすれば、例えどんな環境変数を持ったアプリケーションが起動していても、正しいX(クリップボード)にアクセス出来るという仕組みです1

stack overflowの記事を参考に、以下のようなelispを~/.emacsなどに書きます。

.emacs
;; sync with x clipboard
(unless window-system
    (defun xsel-cut-function (text &optional push)
      (with-temp-buffer
	(insert text)
	(call-shell-region (point-min) (point-max) "env $(tmux showenv DISPLAY) xsel -bi")))
    (defun xsel-paste-function()
      (let ((xsel-output (shell-command-to-string "env $(tmux showenv DISPLAY) xsel --clipboard --output")))
	(unless (string= (car kill-ring) xsel-output)
	  xsel-output )))
    (setq interprogram-cut-function 'xsel-cut-function)
    (setq interprogram-paste-function 'xsel-paste-function))

基本的に上のものを使わせてもらいましたが、call-process-regionではどうやら$マークを正しく評価出来ずうまくいかなかったので、ここをprocessではなくshellで行うように書き換えました。

結果

挙動のテスト結果のgifを置いておきます。

テストとして

  1. 異なるDISPLAY変数を持つ2つのログイン済端末を用意(Windows Terminalのタブで2つ用意し、一つは19.0, もう一つは20.0であることを確認済)
  2. 19.0の端末でtmuxを開き、emacsclientを立ち上げる
  3. "from emacs (19.0)" という文字列をemacsのkill ringに格納
  4. Windows上のクリップボードからメモ帳に貼り付け
  5. 逆に、Windowsのクリップボードに"from windows (client)"という文字列を格納し、19.0で開いているemacsにyank
  6. 20.0の端末で19.0で開いているtmuxをattachする
  7. 19.0の端末でログアウトする(ここでDISPLAY=19.0の接続が切れる)
  8. 20.0の端末で開かれているemacs上で"from emacs (20.0)"という文字列をkill ringに格納
  9. Windows上のクリップボードからメモ帳に貼り付け
  10. Windowsのクリップボードに"from windows (client)"という文字列を格納し、20.0で開いているemacsにyank

の操作を行っています。

shared_clipboard_tmux.gif

この一連の動作でDISPLAY変数が変わってもクリップボードが共有されていることが確認出来ました。

  1. これまでは、これを応用してxclipenv $(tmux showenv DISPLAY) xclipにaliasし、MELPAにあるxclip-modeを使っていて、概ねうまくいっていました。しかしxclipコマンドを評価するのはemacs(client)の起動時で、tmuxをDetachして別のDISPLAY変数の端末でAttachすると、前のDISPLAY変数でxclipを実行してしまい、うまくいきませんでした。そこで、コマンドが実行される度に式を評価してもらうようにelispを書きました。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?