Pyclewn

『事実は小説より奇なり』と申します。

『ワトソン君、用事がある、ちょっと来てくれたまえ』

電話が発明された時に伝えられた内容だそうです。これって、今から100年程前に、グラハム・ベル が電話を発明した(とされる)時の有名なフレーズなんで、伝記で一度ぐらいは読んだ事があるんでは なかろうか?

今回、(とされる)って付けておいたのは、 『グラハム・ベル空白の12日間の謎』(日経BP社)という翻訳本を読んでしまったからだ。

そう、彼が発明して特許を取ったとされる件の裏には、いろいろな陰謀が渦巻いていたんでは ないかと言う点について書かれた本なんだ。余り書いてしまうとネタばれになるんで、詳細は控えます。 『事実は小説より奇なり』なのか、各自で当たってみてください。

歴史に、IF は無いと言われるけど、若し、彼が電話事業で当てなければ、きっとベル研も 無かっただろう。そうすると、トランジスタは誰が発見したんだろうか? 未だにトランジスタは おろかICも造られていなくて、真空管の世の中だったりして。

ベル研が存在しなければ、unixは生まれなかっただろうか? unix関連のC言語はどうだ? メインフレーム上で、FORTRANやCOBOLが我物顔で動いていたりして。普通の人はTSSによるLispを 使う世の中になっていたりして。TSSって今風に言うとクラウドですかね。そして端末はちょい前にブームに なりそうだった、Thin端末(馬鹿端末)なんすか。歴史はバズワードと共に、なんちゃってね。

そして電気屋さんがお世話になっている、増幅度や減衰度を表す(デシ)ベルって単位も、どうなっていたやら?

嗚呼、今調べたら、ベル研って、名前だけグラハム・ベルから頂いてきたっぽい。スマソ。 (最初はベルがベル電話会社を作り、それがAT&Tとなった。ベル研ってのは、AT&Tの研究所なのね。)

vim and ctags

前回のgoshのcore事件、何とかしたいと思った訳だ。ソース眺めてみろ。それなら、globalだなと 思うんだけど、ちと大げさかな。折角vimに嵌まっているんで、vim上で何とかしたい。

前にWebに出てたヘッダファイルなどをVimのキー操作一発で探す 方法もあるなと思い出した。簡単に使えそうだけど、ちと機能が多すぎて、指使いを忘れちゃうな。

そんな訳なんで、もう少し簡便なやつを。ctagsでテーブルを造っておいて、それを頼りに すいすいと動く。飛んでけ CTRL+] もとへ戻れ CTRL+t たったこれだけ。

準備は、必要な所に下りていって、

[sakae@arch Gauche-0.9.2]$ ctags -R

するだけ。tagsってファイル上に飛んでけ情報が出来上がる。たったこれだけ。楽でええわ。-Rオプションが recurseとは別の意味になってるctags(FreeBSDのやつがそうだった)だと、ちょいと面倒だけど、

[sakae@secd ~/Gauche-0.9.2]$ find . -name '*.[ch]' | xargs ctags -a -f tags

すれば良い。

cgdb

ソースを読むのもいいけど、もっとダイナミックにやるのがオイラ流なんだよな。 前回はgoshの動きを追ってみようとして、素のgdbを使ってみた。emacsからならソース行を 表示しながら追えたんだけど、何か退化しちゃったな。そこでdddですよってのは置いておいて 他にないものかと、portsの中を探してみたよ。そしたら出てきたね。

CGDB is to be lightweight and responsive; not encumbered with
unnecessary features.

The interface is designed to deliver the familiar GDB text interface,
with a split screen showing the source as it executes. The UI is modeled
on the classic Unix text editor, vi. Those familiar with vi should feel
right at home using CGDB.

WWW:    http://cgdb.sourceforge.net/

viはクラッシクなエディタですって。上等じゃん。それ以上何を望もうぞ。

使い方は、CGDB - curses interface to gdb とか とあるエンジニアの雑多な日記 とかを参考にすると良い。もっと詳しくってのは、GNUお得意のinfoを見れ。 (Documentationでもいいけど)

と言う事で、ちょっと使うには楽でいいですよん。

Pyclewn

折角なので、vimから使えるgdbを探してみた。出来ればpdbも使えると有り難い。何たって、 emacsに対抗するんだ。ググル先生に、"vim gdb pdb" って注文してみた。

トップページに出てきたのがPyclewn。しっかりSEO対策 されてるな。有名なんかな? 有名なんだろうな。

Homeの下の方に対抗馬との比較表が載ってる。まあ、宣伝だからPyclewnが断然優れてまっせってのは 、お約束。騙されたと思って入れてみる鹿。

既に騙されて?入れている人が居た。使い心地はどうなんだろ?

Pyclewn で、GDB ノススメ

一緒に使うgdbが古いと文句垂れるよ。しょうがないので、gdb7.4を作ろうとした、gdbからpythonとも 仲良く出来るけど、どうしますですって。どんな蜜月なんだろう。興味津々。

# C-B : break "${fname}":${lnum} # set breakpoint at current line
# C-D : down
# C-E : clear "${fname}":${lnum} # clear breakpoint at current line
# C-N : next
# C-P : print ${text}            # print value of selection at mouse position
# C-U : up
# C-X : print *${text}           # print value referenced by word at mouse position
# C-Z : sigint                   # kill the inferior running program
# S-A : info args
# S-B : info breakpoints
# S-C : continue
# S-F : finish
# S-L : info locals
# S-Q : quit
# S-R : run
# S-S : step
# S-W : where
# S-X : foldvar ${lnum}          # expand/collapse a watched variable

これ、.vim/macro/.pyclewn_keys.gdb に有った、デフォルトのキーバインドです。実際にdebug するには、次のようにします。

vim main.c     ;; mainがあるファイルを指定
:Pyclewn       ;; gdb起動
:Cfile gosh    ;; 実行binary指定
:Cmapkeys      ;; キーの定義
CTRL-B         ;; breakしたい行まで移動して、そこにBPをセット
SHIFT-R        ;; 実行
SHIFT-S        ;; 後はお好きに
 :

よく使うgdbコマンドはCTRLにバインドされてて、そうでもないのはSHIFTキーに割付られて いるって事でいいのかな。おいらは、結構whereを使うんで、時々指が硬直するな。(と贅沢な悩み)

pdbを使うには、vimを起動した後

:Pyclewn pdb /usr/local/bin/pythontidy blood.py after.py
:Cmapkeys
 :

とすれば良い。

# C-B : break "${fname}:${lnum}" # set breakpoint at current line
# C-D : down
# C-E : clear "${fname}:${lnum}" # clear breakpoint at current line
# C-N : next
# C-P : p ${text}                # print value of selection at mouse position
# C-U : up
# C-Z : interrupt
# S-A : args
# S-B : break
# S-C : continue
# S-R : return
# S-S : step
# S-W : where

pdb用のキーバインドだけど、SHIFT-R が、returnになってるって微妙だな。こんがらがるぞ。 これ、Pyclewnを起動した時点でスクリプトはもうrun状態になってるから、 そもそもrunコマンドは不要って事なんだ。頭では分かってるけどな。。。

自由になれ

上記で指使いがおいら的に微妙って書いた。そう、CTRLやらSHIFTを覚えるのが難儀やん。やっぱり 世の中には、そういう人も居て、安心した。

Pyclewnを使ってVimからGDBを操作

こちらのを見ると、.pyclewn_keys.gdb でのカスタマイズに限界を見出しちゃったので、vimを サブプロセスとして使うようにされてた。そうすれば、起動の旅に、Cmapkeys なんて呪文を 唱える必要が無くなるからだ。

但し、pyclewnを起動する時、長ったらしいコマンドライン入力が必要になるんで、ちと面倒くさい。 そんなのbashに押し付けちゃえ。.bashrcに

alias debug='pyclewn -e vim --cargs "-S ~/.pyclewn_mapping.vim" --args '

こんなのを登録しておいた。使い方は、

[sakae@secd ~/Gauche-0.9.2/src]$ debug ./gosh
:Cbreak main       ;; 最初はソースが出ていないので、コマンドは手打ち
R                  ;; 実行すると、該当するソースが出てくる
N                  ;; 後は、適当に進めて行く
:

debug中にpsすると

 1580   2  S+    0:00.48 /usr/local/bin/python /usr/local/bin/pyclewn -e vim --cargs -S ~/.pyclewn_mapping.vim --args gosh
 1587   2  S+    0:00.16 vim -nb -S /tmp/vimscriptbJrzN8.clewn -S ~/.pyclewn_mapping.vim
 1588   3  Ss+   0:00.17 gdb -tty=/dev/null -x /tmp/gdbscriptRCEE1z.clewn --interpreter=mi gosh

コントローラーになってる、pyclewnが居て、その下で、vimとgdbが動いてるって構図だな。これって Webの3層構造ですな。んでもって、/tmpの下に出来てるやつは、

[sakae@secd /tmp]$ cat gdbscriptRCEE1z.clewn
/usr/home/sakae/Gauche-0.9.2/src/main.c:368:breakpoint 1 enabled
/usr/home/sakae/Gauche-0.9.2/gc/misc.c:416:breakpoint 2 enabled
[sakae@secd /tmp]$ cat vimscriptbJrzN8.clewn

set confirm off
set height 0
set width 0
set annotate 1

これって、いつかやったLIMPと同じ仕組みなのかな。ソース読んでみるか。えっと、ソースは

[sakae@secd /usr/local/lib/python2.7/site-packages/clewn]$ ls *.py
__init__.py     debugger.py     misc.py         pydb.py
__version__.py  evtloop.py      netbeans.py     simple.py
asyncproc.py    gdb.py          nt.py           tty.py
buffer.py       gdbmi.py        posix.py        vim.py

ここに有ったぞ。

最後に、私が追加した指使いも含めて、 .pyclewn_mapping.vim を開陳しておきます。

cnoremap <expr> <SID>lineno line(".")

nnoremap <script> BB :Cbreak <C-R><C-%>:<SID>lineno<CR>
nnoremap <script> BC :Cclear <C-R><C-%>:<SID>lineno<CR>

nnoremap R :Crun
nnoremap V :Cset args
nnoremap S :Cstep<CR>
nnoremap N :Cnext<CR>
nnoremap F :Cfinish
nnoremap U :Cuntil
nnoremap C :Ccontinue
nnoremap W :Cwhere<CR>
nnoremap Z :Csigint
nnoremap A :Cinfo args<CR>
nnoremap L :Cinfo locals<CR>
nnoremap G :Cinfo reg
nnoremap X :Cx/2xw
nnoremap M :Cdisassemble

nnoremap <C-U> :Cup<CR>
nnoremap <C-D> :Cdown<CR>

nnoremap PP :Cprint <C-R><C-W>
nnoremap PO :Cprint *<C-R><C-W>

nnoremap Q :Cdbgvar <C-R><C-W>
nnoremap D :Cdelvar <C-R><C-W>
nnoremap <script> T :Cfoldvar <SID>lineno<CR>

必殺、ちゃぶ台返し

PyclewnでPythonをdebug出来る事も確認出来た。でもね、IPythonが入っているならこれを 使わない手はないよ。そう、必殺、ちゃぶ台返しの裏技です。(もっと早く出せよってのは、 却下ね。)

IPythonの中で使えるコマンドの一つとして、run なんてのが有る。ちょいとその説明を 読むと、

-d: run your program under the control of pdb, the Python debugger.
This allows you to execute your program step by step, watch variables,
etc.  Internally, what IPython does is similar to calling:

  pdb.run('execfile("YOURFILENAME")')

with a breakpoint set on line 1 of your file.  You can change the line
number for this automatic breakpoint to be <N> by using the -bN option
(where N must be an integer).  For example:

  %run -d -b40 myscript

will set the first breakpoint at line 40 in myscript.py.  Note that
the first breakpoint must be set on a line which actually does
something (not a comment or docstring) for it to stop execution.

When the pdb debugger starts, you will see a (Pdb) prompt.  You must
first enter 'c' (without qoutes) to start execution up to the first
breakpoint.

Entering 'help' gives information about the use of the debugger.  You
can easily see pdb's full documentation with "import pdb;pdb.help()"
at a prompt.

これの何が嬉しいかと言うと

In [2]: run -d -b4820 /usr/local/bin/pythontidy blood.py after.py
Breakpoint 1 at /usr/local/bin/pythontidy:4820
NOTE: Enter 'c' at the ipdb>  prompt to start your script.
> <string>(1)<module>()

ipdb> c
> /usr/local/bin/pythontidy(4820)<module>()
   4819         file_out = sys.stdout
1> 4820     tidy_up(file_in, file_out)
   4821

ipdb> s
--Call--
> /usr/local/bin/pythontidy(4777)tidy_up()
   4776
-> 4777 def tidy_up(file_in=sys.stdin, file_out=sys.stdout):  # 2007 Jan 22
   4778

ipdb> n
> /usr/local/bin/pythontidy(4790)tidy_up()
   4789     global INPUT, OUTPUT, COMMENTS, NAME_SPACE, INPUT_CODING  # 2007 May 23
-> 4790     INPUT = InputUnit(file_in)
   4791     OUTPUT = OutputUnit(file_out)

こんな具合に、ソースが表示される事。楽でええわな。

先週のクイズの答え

3を3回使って、0から10までの数式を出せ ってのクイズだった。答えは

0  3 X (3 - 3) = 0
1  3 ** (3 - 3) = 1
2  3 - 3 / 3 = 2
3  3 + 3 - 3 = 3
4  3 + 3 / 3 = 4
5  3 ! - 3 / 3 = 5
6  3 X 3 -3 = 6
7  3 ! + 3 / 3 = 7
8  (3 ! / 3) ** 3 = 8
9  3 + 3 + 3 = 9
10 3.3 X 3 = 9.9 ~= 10

最後の10はインチキ臭いけど、そこは海軍魂の臨機応変、ユーモアなんだそうです。