GNU screenのコピーモードは、vi風操作が可能ですが、以下の動作がvimと違って使いにくいので、
スクロールバッファを一時ファイルに保存してvimで編集するための方法です。
(vim以外のエディタでも同様の方法が可能)
- 日本語上での
w
等による単語単位移動の動作が異なる - 矩形選択方法が異なる(右端マーク操作)
-
i"
等のtext-objectは未対応(W
による単語選択がある程度) -
)
による文単位の移動等は未対応
(ふと、MS-DOSでVz Editorを常駐させてコンソール出力をコピーしていたのと同様のことができないかと思いついたので。)
また、複数の離れた場所からコピーする必要がある場合、
「コピーモード開始、コピー対象文字列の場所に移動、コピー対象文字列を選択、ペースト」
を繰り返す手間がかかるのに対し、vimで編集する方法であれば、
コピーモード開始は1回ですみ、ペーストしたい文字列を編集して作ってから、1回だけペースト操作をすれば良くなります。
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のコピーバッファに反映する以下のスクリプトを呼ぶ形でも可。
#!/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
で終了)
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起動以外にも、適当なスクリプトを作って、
直前のコマンドの出力結果のみを抽出したり等も可能。
(主にコマンドを実行した後になって何かしたい場合用。
コマンド実行前ならパイプを使えばいいので。)
直前のコマンドの出力結果を抽出してコピーする例:
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)をバッチモードで使用)
#!/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'
$
?^deton@colinux:
1,.d
/^deton@colinux:/d
w
備考:
-
deton@colinux:
はプロンプト文字列。要変更。 - シェルのコマンド引数としてペーストして使いやすいように、最後の改行を削除
例: 直前の出力結果抽出スクリプト(awk版)
#!/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'
#!/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でしておいた方が良いかもしれません。
さっき見ていたページの内容を参照したいことがよくあるので。
(遅いマシンだと少しちらつきが多くなるのが気になりますが)
ENABLE_SCROLLBACK:TRUE
関連
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より。)
- (screenでなくVimShellを使う)