LAMP ならぬ LIMP(2)
この間から新築中のFreeBSD9、やっとX方面まで足を延ばせるようになった。Xorg -configureして 雛形を作ってあげた。普通はhalとかdbusを使うようだけど、そんなに大掛かりな事はしたく ないんで、ぐぐってhal無し用のxorg.confを作ったよ。twmは某筑波大学の先生が作ったものを ソースからコンパイルした。
作り方を忘れてしまっていて、xmkmf コマンドを思い出すまで、えらく悩んでしまったわい。
ホームの引越しは無難にtarで荷作りして、新居に転送した。長年に渡って住み着いていたおかげで 、使わないものが大量に出てきたよ。断捨離(あるいはLRUのアルゴリズムの則り)で、ばさばさと 整理した。
特に眼につかない、ドット・ディレクトリィーの中に不要物が溢れ返っていた。さっぱりすると 気持ちエーーー。
vimとsbclのコラボ
Limpを仕込んだvim上で、F12キーを押してsbclを起動すると、vimのステータスラインに 下記のような質問が出てくる。おいらはリスプの名前をおいらのやつって、付けてあげたよ。
Connect to [boot new]: Name the Lisp: mine Path to core to boot [use system-default]:
sbclが起動してREPL画面が出た時、psしてみると、、、(左の数字はpid)
656 vim hoge.lisp 667 SCREEN -c /tmp/limp_bridge-screenrc.qMlUH2 -dmS limp_listener-mine 669 /bin/bash /home/sakae/limp/0.3.4/bin/lisp.sh -c /usr/lib/sbcl/sbcl.core -P /tmp/limp_bridge-screenrc.qMlU 689 rlwrap -b "#'(),;`\|!?[]{} /usr/bin/sbcl --noinform --core /usr/lib/sbcl/sbcl.core 691 /usr/bin/sbcl --noinform --core /usr/lib/sbcl/sbcl.core 694 screen -x 667
そして、それぞれの親子関係は、、、
[sakae@arch ~]$ pstree -p 656 vim(656)---screen(694) [sakae@arch ~]$ pstree -p 667 screen(667)---lisp.sh(669)---rlwrap(689)---sbcl(691)
sbcl画面を消す(hide)すると、プロセス694は消える。また、sbcl画面を出してあげると、新しい プロセスが生成される。
736 screen -x 667 [sakae@arch ~]$ pstree -p 656 vim(656)---screen(736)
これだけ分かれば、コラボの秘密を解読出来るかな。まてまて、screenの引数リストの意味も 調べておくかな。
-c file Read configuration file instead of '.screenrc'. -dmS name Start as daemon: Screen session in detached mode. -p window Preselect the named window if it exists. -x Attach to a not detached screen. (Multi display mode).
ついでに、Limp付属のlisp.shも調べておく。
[sakae@arch ~]$ limp/0.3.4/bin/lisp.sh -h lisp.sh 0.3.4. Usage: lisp.sh [options] [name-or-PID] Connects to the Lisp specified by name-or-PID, or boot a new called 'name'. Options: -h Print help (this text) and exit -v Print version information and exit -b Boot a fresh Lisp -c path Use the specified core instead of the default -l Display running Lisps -s styfile Put the screen ID in this file, otherwise display on standard output. Name must be unique! (But isn't currently enforced.) Examples: # connect to a running Lisp named mylisp lisp.sh mylisp # boot a new Lisp, using the specified core lisp.sh -b -c /path/to/my/huge-app.core mylisp
ちゃんと説明書が内蔵されてました。それじゃ仰せに従ってと
[sakae@arch ~]$ limp/0.3.4/bin/lisp.sh -l Currently running Lisps: mine (667)
更に、lisp.sh mine してみると、(同様な事は、screen -r でも出来るのかな)
774 /bin/bash limp/0.3.4/bin/lisp.sh mine 782 screen -x limp_listener-mine [sakae@arch ~]$ pstree -p 774 lisp.sh(774)---screen(782)
あらら、REPL画面に接続出来ちゃった。この時点で、vim側とターミナル側からsbclのreplを 共有してる状態となっている。面白いな。
screen
これ、screenの接続仕様書かな。
[sakae@arch ~]$ cat /tmp/limp_bridge-screenrc.qMlUH2 startup_message off defscrollback 1000 hardcopydir /home/sakae/.limp-hardcopy logstamp off shell bash caption splitonly escape ^zz termcapinfo xterm ti@:te@ bindkey -m "^[[5;2~" stuff ^u bindkey -m "^[[6;2~" stuff ^d bindkey -k F2 detach obulimit 20971520 # 20M should to be enough msgwait 0 msgminwait 0 defflow off screen -t Lisp 0 /home/sakae/limp/0.3.4/bin/lisp.sh -c /usr/lib/sbcl/sbcl.core -P /tmp/limp_bridge-screenrc.qMlUH2 -p /tmp/vmkusvL/0
[sakae@arch ~]$ ls -l /tmp/screens/S-sakae/ total 0 prwx------ 1 sakae 1000 0 Wed Feb 1 11:09:41 667.limp_listener-mine
もしかして、頭のpって、プロセスのPなのかな?そして、こんなのも。
[sakae@arch ~]$ ls -l .limp_bridge_channel-mine.667 -rw-r--r-- 1 sakae 1000 0 Feb 1 11:08 .limp_bridge_channel-mine.667
[sakae@arch ~]$ screen -ls There are screens on: 667.limp_listener-mine (Attached) 2 Sockets in /tmp/screens/S-sakae.
bridge.vim
上記の証拠品から、推理をしてく。screenとlisp.shが何処で使われたかvimスクリプトを調べると ブリッジにあった。これが、vimとsbclを橋渡ししてるのね。
そんじゃ、どのタイミングで橋にかかるかと言うと、そりゃまあ、F12キーを押した時だわなあ。
nmap <buffer> <F12> <Plug>LimpBootConnectDisplay nmap <buffer> <C-F12> <Plug>LimpDisconnect nmap <buffer> <S-F12> <Plug>LimpShutdownLisp
こんな定義が、keys.vimに載ってた。LimpBootConnectDisplayを経由で、最終的に LimpBridge_boot_or_connect_or_displayが呼ばれる。
接続済みか否かで場合分けされてて、未接続の場合は、前記の質問をし、最終的にlisp.shを 呼び出している。
let styfile = tempname() let cmd = s:Limp_location . "/bin/lisp.sh ".core_opt."-s ".styfile." -b ".name call system(cmd) while getfsize(styfile) <= len("limp_listener") sleep 200m endwhile " needs to be binary, or readfile() expects a newline... let lines = readfile(styfile, 'b') if len(lines) < 1 echom "Error getting screen ID!" return endif let sty = lines[0] call delete(styfile) call LimpBridge_connect(sty) call LimpBridge_boot_or_connect_or_display()
bootするまで時間待ちするのね。そして、起動したscreenのwindow名をvim側に回収してるのね。最後は、 再帰呼び出しして抜けてるのか。
lisp.sh
screen経由で実際にsbclを起動してるのは、lisp.shだ。(vim側でのscreen操作は、attachのみ) ちょっと覗いておく。
とか言いつつ、真面目に追うのは面倒なので、shに -x オプションを付けて、トレースして みます。(行番号も出てくればいいのにね!)
[sakae@arch bin]$ sh -x lisp.sh -b mylisp : + core_opt='-c /usr/lib/sbcl/sbcl.core' ++ mktemp /tmp/limp_bridge-screenrc.XXXXXX + initfile=/tmp/limp_bridge-screenrc.Wpqb3h + [[ '' == '' ]] ++ mktemp /tmp/limp_sty_XXXXXX + styfile=/tmp/limp_sty_5zgbwl + echo 'startup_message off' : + echo 'screen -t Lisp 0 /home/sakae/limp/0.3.4/bin/lisp.sh -c /usr/lib/sbcl/sbcl.core -P /tmp/limp_bridge-screenrc.Wpqb3h -p /tmp/limp_sty_5zgbwl' + screen -c /tmp/limp_bridge-screenrc.Wpqb3h -dmS limp_listener-mylisp + '[' '!' -s /tmp/limp_sty_5zgbwl ']' + sleep 1s + '[' '!' -s /tmp/limp_sty_5zgbwl ']' + [[ '' == '' ]] + cat /tmp/limp_sty_5zgbwl 1116.limp_listener-mylisp + rm -f /tmp/limp_sty_5zgbwl + exit 0
幾つ起動してもバッティングしないように、mktempなんてコマンドを使ってるのね。それに しても、screenrc(相当品)に、screenコマンドを埋め込んで(sbclの起動方法を含めて)、 それを起動するって、技巧的でLisp屋さんらしいな。
vimスクリプトの予習
順番からすると、次はいよいよ *.vim を見て行く番だけど、今まで真面目にvimスクリプトを 勉強してなかった。
何か胃にもたれない、もとえ脳にやさしい資料はないかと探してみたよ。そしたら、天下のIBM様が どうでっしゃろと公開されてるのに行き着いた。
肩の凝らない読み物
スパルタンVim