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様が どうでっしゃろと公開されてるのに行き着いた。

第 1 回 変数、値、式

第 2 回 ユーザー定義関数

第 3 回 組み込みリスト

第 4 回 辞書

第 5 回 イベント駆動型のスクリプト作成と自動化

肩の凝らない読み物
スパルタンVim