GNU screenで領域を分割したり レイアウトを設定したり、 それらをショートカットキーで簡単に変更したりする設定についてやった GNU screenでのレイアウトの整理 の不満があったところを改善したことについて。
以前のレイアウト/ウィンドウ分割設定の不満点
上のページのところで画面分割やレイアウトを初期化する コマンドをまとめてキーバインドに割り当てたりしました。
一番不満があったのは、現状のウィンドウ数とかを把握する術を知らなかったので、 例えば
bind s eval 'screen' 'screen' 'screen' 'source $HOME/.screen/4-windows.layout'
bind r eval 'source $HOME/.screen/4-windows.layout'
の様に、
- s1:
screen
コマンド3回行って現スクリーンと合わせて最低4つのウィンドウを 作ってから画面を4分割 - r: ウィンドウを新たに作らずに画面を4分割
みたいな事をして、最初はsを、一度作業したりしてレイアウトを 変更したりした後に4分割に戻すにはrを、みたいなことをしていました。
ただ、途中でウィンドウを色々つくってから 小さい番号の方を消してしまうと、0-3のウィンドウが無いと 4分割コマンド後にはそれぞれの領域に何も無い状態になったり、 iをしてしまうと余計にウィンドウが出来たりしてしまって余り賢くありませんでした。
レイアウトの方は消してもあまり弊害が無いので同じ名前のレイアウトが存在してたら それを消してリセット、みたいな事をしたのでそれなりにいい感じではありましたが。
レイアウトコマンド時の表示を変更(、のちに元に戻す)
キーバインドでCtrl-qをレイアウトモード みたいな感じでコマンドを続けられるようにして、 ステータスラインに
こんな感じで、キーバインドの最後にlayout show
を呼んで表示させる様にしていました。
ここに、使えるキーの説明を付けたいと思って、
exec /bin/bash -c "screen -X echo \"$(screen -X layout show && screen -Q lastmsg), n: next, p: prev, i: init/reset, s: save, c: new, m: set, x: remove, <n>: goto <n>\""
こんな感じで、screen -Q
でlayout show
を取ってきて、
そこにコマンドの説明を加えて、ということを考えて、
上のコマンドを~/.screen/layout_show
と言うファイルに入れて、
各キーバインドの最後にlayout show
の代わりにsource ~/.screen/layout_show
と、上のコマンドを呼ぶようにしました。
そうするとこんな感じ。
ただし、
GNU screenでscreen内の情報をシェルスクリプトで取り出す & 問題点
で書いたように、
screen -Q
を使うと途中で表示が崩れたり、特にCygwinでは全く動かなかったりしたので
この設定はボツに。。。
後、途中でmsgminwait
を変えて、一定時間経ったら
コマンド表示、みたいなことをやってみようかとも思って
msgminwait 3
layout show
echo "n: next, p: prev, i: init/reset, s: save, c: new, m: set, x: remove, <n>: goto <n>"
msgminwait 0
こんなこともしてみたんですが、
GNU screenでscreen -Xを使うときの注意点
でも書いたように、msgminwait
が上手く機能してくれずに、
待たずにすぐに最後のコマンドの結果が出てしまうので上手くいかず。
(何か勘違いしてるのかバグなのか。。。)
最後のmsgminwait 0
を外してもダメ。
さらにこれやってる時に、echo
がファイルの中で使われて
をれをsource
で呼ぶと全く効かない状態になりました。
上のコマンドをキーバインドに一つ一つ順番に割り当てると最後のecho
のものが
表示されるのですが、
上のコマンドをファイルに書いて、それをsource file
で呼ぶと
何故かecho
コマンドだけは実行されてるようですが、何も表示しない、
という状態になります。
(前のlayout show
の結果が残ってるわけではないし、
command -c layout
みたいなクラス指定については効いているので
キーバインド自体は実行されて、さらにecho
の部分まではたどり着いていて何らか実行されてるけど
すぐに表示が消えてしまう状態。。。?)
これを
exec /bin/bash -c "screen -X echo \"xxx\""
みたいに無理やりexec
からのscreen -X
にすると表示が出るようにはなりました。
この辺も謎な部分。
色々やりましたが、結局あまりうまくないので、とりあえずあとで簡単に変えられる様に、
~/.screen/layout_show
ファイルを使うのは残して、
このファイル内に単にlayout show
を実行するだけ、にしておきます。
ウィンドウの存在を確認する
簡単にはscreen -Q windows
によってシェルスクリプト等で現在のウィンドウ一覧が取れるわけですが、
screen -Q
は問題があるので
これは避けます。
どうするかというと、screen -X
を使うのですが、このコマンドでは
同時に-p n
と言う引数を指定すると、n番のウィンドウを指定して
コマンドを実行出来ることを利用します。
ウィンドウが存在しないとコマンドが実行されないので、 それにより存在をチェックします。
チェックする方法は、writebuf
を使います。
これが今のところ思いつくscreen -Q
以外で唯一のscreen外へ情報を取り出す
方法なので。
具体的には、まず、コピーレジスター(.
)が空だと書き出しも行われないので、
適当な言葉(win_test)をコピーレジスターに書き込みます
2。
screen -X register . win_test
その後、各ウィンドウにwritebuf
コマンドを送ってファイルが書き出されているか
確認します。
rm -f ~/test_file
screen -p 0 -X writebuf ~/test_file
date >/dev/null
if [ -f $test_file ];then
...
こんな感じで。
途中でdate
とか余計な物が入ってますが、
これが無いと環境によってはwritebuf
が終了する前にファイルのチェックを行ってしまって
上手くいかなかったのでちょっとした待ち時間を入れるために入れています。
これを使ってウィンドウを用意するために作ったスクリプトがこちら:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
|
こんな感じ。
最初のループのところで、
番号を小さい方から適当な数(ここでは0-19)のウィンドウをチェックしていって、
ほしい数(n_windows
)分だけあるかどうかチェックしています。
見つかった場合に、screen内でwin$n
という変数にその番号を宛てる様にしています。
これを使ってあとで、select $win0
と言うように順番に詰めていくことが出来ます。
さらに2番めのループでは飛ばされた番号3 があればそこに新たなウィンドウを、 3番目のループではそれ以降の番号にウィンドウを必要なだけ作っていきます。
n_windows
がwin$n
で使いたい量、
n_create
が最低限欲しいウィンドウの数です。
select $win7
とやった時にwin7
が定義されてないと下手なエラーを表示するので
それを避けるため、ウィンドウが無くても使うwin$n
は埋めておく、と言った感じで。
また、リセットされた時にこれらが正しく変更されるようにも必要です。
レイアウト設定
前に用意していた レイアウト設定スクリプトを
1 2 3 4 5 6 7 8 9 10 11 12 |
|
の様に変更して、これを呼ぶ前にwin_prepare.sh
を呼べば
いくつウィンドウが存在していようとも必要な数だけ用意して
それぞれの領域にアサインしてくれます。
上のスクリプトの中では最後にウィンドウをソートしていますが、 新しく出来たものは後ろに、としたいのであれば
$ win_prepare.sh 8 4 0
と3つめに引数として0を渡せばOK。 (面倒できちんと作ってないので引数の使い方が雑。。。)
これを使うと、4分割キーバインドは
bind r eval 'next' 'exec /bin/sh -c $HOME/.screen/win_prepare.sh' 'source ~/.screen/4-windows.layout'
の一つで良くなります 4。
実際には
.screen/layout.sh
というスクリプトをもう一つかませて、
この中でwin_prepare.sh
を呼んで、
レイアウト名やらautosave
やらの設定もする、
みたいなことをしています。
これを、いくつかのレイアウトをまとめて作るスクリプト (.screen/all_layout.sh) でまとめています。
今回は、4分割を二つ作って、最初の4分割は
autosave
をoff
にして基本維持、
2つ目の方をon
にして変更がすぐに変更されるようにみたいなのを作っています。
autosave
をoff
にしているものがあるので、ウィンドウを切り替えたとかを保持したいとき、
save
を簡単にするために
.screen/layout_save.sh
というスクリプトも作りました。
save
するときには必ず名前が必要なので、
現在のレイアウトをそのまま保存、みたいなことをしたいときには
現在のレイアウトの名前を取ってくる必要があるのですが、
これが結局screen -Q
を使う以外に上手く出来なかったので、
この中だけではscreen -Q
を使っています(Cygwinでは使えない。。。)。
全てのレイアウト関連のシェル/screenスクリプトは~/.screen
ディレクトリに入れるようにしています。
以下のキーも含めてscreen内のキーバインドについてはCtrl-a(デフォルト)のエスケープキーは省略しています ↩
-
ここで元の値があれば保存してあとで戻す、みたいな事をしても良いですが、 multi_clipboard があれば特に問題ないかな、ということでとりあえず書きっぱなしに。 ↩
それより大きな番号のウィンドウがあるが 消されたとかでウィンドウが存在しない番号。screenコマンドでウィンドウを作るときには 使われていない番号の中から低い方から順に新しいウィンドウができるので ↩
最初の
next
は、Windowが空の領域(select -
で選べる領域)に居るとexec
コマンドが呼べないようなのでその対策。 ↩