11
12

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 5 years have passed since last update.

GNU screenのスクロールバッファをvimで開いて、コピーモードのかわりに使う方法

Last updated at Posted at 2014-04-29

GNU screenのコピーモードは、vi風操作が可能ですが、以下の動作がvimと違って使いにくいので、
スクロールバッファを一時ファイルに保存してvimで編集するための方法です。
(vim以外のエディタでも同様の方法が可能)

  • 日本語上でのw等による単語単位移動の動作が異なる
  • 矩形選択方法が異なる(右端マーク操作)
  • i"等のtext-objectは未対応(Wによる単語選択がある程度)
  • )による文単位の移動等は未対応

(ふと、MS-DOSでVz Editorを常駐させてコンソール出力をコピーしていたのと同様のことができないかと思いついたので。)

また、複数の離れた場所からコピーする必要がある場合、
「コピーモード開始、コピー対象文字列の場所に移動、コピー対象文字列を選択、ペースト」
を繰り返す手間がかかるのに対し、vimで編集する方法であれば、
コピーモード開始は1回ですみ、ペーストしたい文字列を編集して作ってから、1回だけペースト操作をすれば良くなります。

.screenrc
minmsgwait 0
defscrollback 1000
bufferfile $HOME/tmp/screen-xchg
bind V eval 'msgwait 0' copy 'stuff "g G$>"' screen 'stuff "vim +$ $HOME/tmp/screen-xchg;exit^M"' 'msgwait 1' 'echo ""'

備考:

  • msgwait 0で、邪魔になるメッセージ表示を抑制。
  • g G$>で、スクロールバッファを最初から最後までコピーしてbufferfileに書き出し。
  • screen 'stuff "vim ..."'で、新しくwindowを作ってそこでvimを起動。vimが終了されたらシェルをexitしてwindowを閉じる。
  • vim +$で、起動後に:$を実行して最終行に移動。
  • echo ""で、msgwait 1実行によって表示されるメッセージを即時消去。

vimからscreenのコピーバッファへのコピー

vimからscreenのコピーバッファへのコピーは、fakeclip.vim参照。
(もしくは、以下の記事のYankToScreen()参照。
http://qiita.com/deton/items/61466d630edbac6734ae#3-5 )
また、vimを直接呼ぶかわりに、一時ファイルを編集・保存したら、
その内容をscreenのコピーバッファに反映する以下のスクリプトを呼ぶ形でも可。

vsbuf
#!/bin/sh
# edit file and copy to screen's buffer
vim +$ $HOME/tmp/screen-xchg
screen -X eval 'msgwait 0' readbuf 'msgwait 1'

bashのedit-and-execute-command(C-xC-e)との組み合わせ

エディタ起動後、vimで画面分割してscreenのコピーバッファを開いて、コマンドライン編集の参考用に使えるようにする。
(やっぱりコマンドライン実行したくなくなった場合はvimを:cqで終了)

.screenrc
bind E eval 'msgwait 0' copy 'stuff "g G$>"' 'stuff "^X^E:sp ~/tmp/screen-xchg^MG"' 'msgwait 1' 'echo ""'

複数行を,付きで連結してのコピー

screenのコピー機能の、複数行を,付きで連結してのコピー等は、vim側で適当に編集すればいいかと思っています。
めったに使わないので。
({dir1,dir2,dir3}/*.htmlのように指定したい場合くらいしか使ったことが無いです。)

スクロールバッファに対してスクリプトを実行

vim起動以外にも、適当なスクリプトを作って、
直前のコマンドの出力結果のみを抽出したり等も可能。

(主にコマンドを実行した後になって何かしたい場合用。
コマンド実行前ならパイプを使えばいいので。)

直前のコマンドの出力結果を抽出してコピーする例:

.screenrc
bind P eval 'msgwait 0' copy 'stuff "g G$>"' screen 'stuff "picklastout.sh;exit^M"' 'msgwait 1' 'echo ""'
# 以下では動かない模様。
#bind P eval copy 'stuff "?deton@colinux:^Mnj /deton@colinux:^Mk$ "'

例: 直前の出力結果抽出スクリプト(vim(あるいはed)をバッチモードで使用)

picklastout.sh
#!/bin/sh
cp ~/tmp/screen-xchg ~/tmp/picklastout
vim -e -s ~/tmp/picklastout < ~/bin/picklastout.ed
#ed -s ~/tmp/picklastout < ~/bin/picklastout.ed > /dev/null 2>&1
# remove last "\n"
head -c -1 ~/tmp/picklastout > ~/tmp/screen-xchg
screen -X eval 'msgwait 0' readbuf 'msgwait 1'
picklastout.ed
$
?^deton@colinux:
1,.d
/^deton@colinux:/d
w

備考:

  • deton@colinux:はプロンプト文字列。要変更。
  • シェルのコマンド引数としてペーストして使いやすいように、最後の改行を削除

例: 直前の出力結果抽出スクリプト(awk版)

picklastout.sh
#!/bin/sh
cat $HOME/tmp/screen-xchg | picklastout.awk >$HOME/tmp/picklastout
mv $HOME/tmp/picklastout $HOME/tmp/screen-xchg
screen -X eval 'msgwait 0' readbuf 'msgwait 1'
picklastout.awk
#!/usr/bin/awk -f
BEGIN {
	prevout = "\n";
}
# CHANGEIT: prompt string
/^deton@colinux:/ {
	if (out != "") {
		prevout = out;
	}
	out = "";
	next;
}
{
	out = out $0 "\n";
}
END {
	# remove last "\n"
	printf("%s", substr(prevout, 0, length(prevout) - 1));
}

備考: スクロールバッファ内容は表示内容なので元の出力と異なる場合あり

通常のscreenでのコピーと同様に以下は気を付ける必要あり。

  • タブがスペースに展開される
  • less等で長い行を表示した際、折り返されると、継続行とみなされない。

lynxの表示をコピーしたい場合のlynx側設定

lynxを使う場合、1スクリーンへの表示ごとにscrollback bufferがクリアされるので、
以下の設定をlynx.cfgでしておいた方が良いかもしれません。
さっき見ていたページの内容を参照したいことがよくあるので。
(遅いマシンだと少しちらつきが多くなるのが気になりますが)

lynx.cfg
ENABLE_SCROLLBACK:TRUE

関連

.screenrc
bind P eval "copy" "stuff -k ku" "stuff Y" "stuff \033"
# 以下でいい気も。
#bind P eval "copy" "stuff kY"

(GNU Screenバージョン4.2がリリースされましたの記事からたどって、GNU Screen Watch: January 2011 - April 2013より。)

11
12
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
11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?