Mercurial > hg > RemoteEditor > emacs
view ChangeLog @ 70:e8814b2db649
update tags
author | convert-repo |
---|---|
date | Mon, 10 Nov 2008 01:13:09 +0000 |
parents | 34ac82ad8ca8 |
children |
line wrap: on
line source
2008-10-28 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * thinking: 一つのセッションで一つのソケットを開く方がいい。 今は Sesssion Manager が一つしかないので問題ないが、 複数の Session Manager からくるコマンドを見ると、 来たコマンドがどこの Session Manager からきたかというのを コマンドから判別できない。 emacs だと、filter で持ってるので、見れない事はない。。。が やっぱり分けた方がいいだろうね。 2008-09-12 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * cvs-rm: line-merge.el translate.el redit_client.pl 現在の ver には要らないので削除。 今後、参考として使うなら、以降の cvs-tag には残ってるのでそこから。 2008-08-29 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * test: SessionManager GUI 版 cvs の member/gongo/JavaSessionManagerCUI/export に置いてます。 sm-cui.jar ってやつで、実行は sm-cui.sh で行けます。 ちなみにGUI版は sessionmanager.jar で、sm.sh で実行できる。 GUI版と違い、CUI版ではマウスでセッション選んで〜ってのができないので、 暫定的に redit-select-command を実装しました。 M-x redit-select-command で、下の minibuffer に "Session ID: " とかでるので 先に put した時に出てきた Session ID を指定すると 入れるので、あとはいつもと同じ感じです。 send command byUTF8: 46,1,2,0,0,6,test.c UTF-8: Set REPComand textlen(Byte) : 6 コマンドが 46 になってるやつの、左から2番目が session id です。 ここでは 1 になります。 「Session ID はこれです!」って強調した文字出力してねーや。。。 GUI/CUI ともに、なぜか textsize が 0 のコマンドは 送っても何も送らない不思議。なんか見逃してるかもしれない。 emacs 側か sm 側かはしらないけど、要チェック。 * redit-client-sm.el: delete redit-client-session-id redit-client-editor-id を、大域変数から削除しました。 SessionInfo で管理してて、必要ある毎に redit-sinfo-get-* とかしてて sinfo 取得 -> sid eid をゲット とかしてるので。 まあもしかしたらまた使う事になるかもしれないが、今は要らない。 2008-08-28 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * cvs-tag: v20080828-2 現在使ってない関数を抹殺したver いずれ必要になるとは思うが、今は見づらくなるので消去。 後ほど必要になったら、下の cvs-tag で取ってこればおk。 * cvs-tag: v20080828-1 現在使ってない関数をコメントで残しているver * redit-client-sm.el (redit-client-process-filter) (redit-client-exec-insert-line, redit-client-exec-join) (redit-client-exec-put, redit-client-exec-delete-line): fix 一斉大編集。 今までは各関数内で (redit-get-*-from-pkt ) とかしてたんだけど それもなんかめんどくさくなったので、 process-filter で予め cmd 〜 siz, text を取得し、 各関数の引数に渡す感じにしました。 redit-client-editor-id, redit-client-session-id なんかが バッファ毎に管理する必要がでて、普通の大域変数へのアクセスだけだと きつくなってきたのでこういう変更にしました。 動いてるのは確認しました。 * redit-client-sm.el (redit-client-after-change-function): fix 前回(2008-08-27)の判定ルーチンを修正してみた。 if (before-begin == after-end) { // 行の削除による max-line の変化をチェック (max-line-diff) // #1 // before-begin-line < line <= before-end-line まで delete // prev-edit-line が 上の範囲に無ければ insert // このとき、prev-edit-line が before-end-line より // 大きければ (- prev-edit-line max-line-diff) の行に送る // #2 } else { // 行の追加による max-line の変化のチェック // max-line に変化があれば line-feed-flg を t に // #3 // before-begin <= line < after-end までを insert (flg) // after-end を insert (改行コード無し) // #4 // before-begin > previous-edited-line // && after-end < previous-edited-line // の時、previous-edited-line を insert // このとき、prev-edit-line が before-begin-line より // 大きければ (+ prev-edit-line max-line-diff) の行を送る // #2 } - #1 行の削除及び行の追加によって改行の追加/削除が行われると 前回編集した行というのがずれてしまう可能性がある。 before-change-function で送れば問題ないのだが、現在は after-change-function で判定しているのでそれはできない。 つーことで、max-line に変化があれば、その差分を保持しておく(ずれた行) - #2 #1 で求めた max-line を使って、prev-edit-line を編集後のずれた行を 正確に参照するように max-line を prev-edit-line に加減する。 加減する条件としては、編集によってずれる範囲にいる場合です。 - #3, #4 前回までは、「予め改行を送って領域確保」とかしてたんですが、 要は行の始めの方から順に insert して、その文字列に改行コード入れれば 問題ないなーと気づいたので。 after-end までは flg によって改行コード入れるか入れないかを決め、 after-end 自身は改行コードを入れないようにしている。 こうすることで、ずれても大丈夫なようにしています(多分) ======= こんな感じかなー。まだまだありそうです見落としバグ。 * redit-client-sm.el (redit-client-after-change-function): fix add/remove-hook を、全てのバッファに対して引っ掛けるように したので(add-hook の 4つめの引数を省略(nil指定))、 *Messages* とかその他いらんものの編集も拾ってしまうようになった。 つーことで、最初に redit-sinfo-get-buf2sinfo で (buufer-name) して、 編集されたバッファが Session Manager と繋がっているものかどうかを 判定して、繋がっていれば以下の処理をするように変更。 本当は (if (nill sinfo) return) とかしたかったんだけど、emacs lisp ではできない。 return ってのは Common Lisp のやつで、block から脱出するってやつ。 Common Lisp だと、defun や defmacro は block 属性なんだけど emacs lisp では違うので、return を使っても抜けれない。 ・・・なんかあると思うんだけどなー 2008-08-27 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el (redit-debug-message): add message ラッパー。redit-debug-flag を見て message するか否か * thinking: テスト用SMGUIを使って、二つのSessionを立ち上げてみた。 / B (test.c) A \ C (hoge.c) B と C がそれぞれ Session を立ち上げ、A が両方に join した。 A が test.c バッファを開いている時に C が入力しても、 ちゃんと A の hoge.c バッファ に書き込まれているのは確認した。 と思ったけど、やっぱり少し問題があった。 process-filter 内で、remove-hook している。 これは、before/after-change-functions を呼ばれないように、 つまりは受け取ったパケットの処理でバッファが編集されても その編集に対しては REPcommand を生成しないようにするためです。 それはいいんだけど、問題が少しあります。 1. A が B のバッファを開いている 2. C が送信した 3. A が受け取って remove-hook をかける (しかし、B のバッファのみ) 4. REPcommand 解析により、C のバッファに書き込む 5. C のバッファには remove-hook が掛かっていないため、 その編集が REPcommand 生成され、C に送られる 6. C はポカーン ってことだ。add-hook,remove-hook の 4つめの引数に nil 以外を設定すると 「この hook はカレントバッファにのみ適用されるYO」って意味なわけだ。 だから上の問題が起きたわけ。 じゃあどうすればいいかって、nil を設定(省略)すればいいわけ。 しかしそうなると全てのバッファに対して hook がかかる。 まあこれでいいんじゃないかってのもあるけどね。 SessionManager に接続しているバッファ(上でいうhoge.cとかtest.c)の確認は redit-sinfo-get-buf2sinfo で nil 以外が返ってくればいい。 nil が来るってことは、そのバッファ(名)は登録されていないわけで。 なので、before/after-change-function の時は、 現在の buffer が登録されているかを確認して、そうでなければ 何もしないってコードをいれるだけでおk。だと思う。 全てのバッファに対してこの確認が入るので、そこらへんのコストが どれだけの物かわからないけど、あるバッファへの hook の管理をするよりは 楽だし、案外軽いかもしれない。わからんけどね。 * redit-client-sm.el (redit-client-after-change-function): 下の変更により、ここでは SessionInfo から prev を取得している * redit-client-sm.el (defstruct SessionInfo): Session 毎(つまりバッファ毎)に previous-edited-line の保持が必要 ってことで SessionInfo に追加 * redit-client-sm.el (redit-client-after-change-function): memo insert/delete 発行判別の説明 バッファで編集が行われたとき、次の二つの hook が反応します。 - before-change-functions バッファが変更される『直前』に呼ばれる。 引数には変更される予定の範囲の begin point と end point を受け取る。 - after-change-functions バッファが変更された『直後』に呼ばれる。 引数には変更された範囲の begin point と end point 、 そして二つの間にあった文字列の長さ length を受け取る。 例えば 1: hoge (n: は n行目 を表す) というバッファがあったとする。そこで、hoge の後ろで改行を入れてみると 1: hoge 2: となる。この時の before, after が受け取る begin と end の行数は before: begin=1 end=1 after : begin=1 end=2 また、hoge の後ろに文字を追加すると 1: hogea この時は以下のようになる。 before: begin=1 end=1 after : begin=1 end=1 次に、以下のようなバッファがあるとする 1: huge 2: sanma この時、2行目の先頭で backspace (DEL) をすると 1: hugesanma となる。この時の begin/end は以下のようになる。 before: begin=1 end=2 after : begin=1 end=1 以上の動作を複数行でやってみる。 1: a 2: b 3: c というバッファで、1〜3を C-Space, M-w, C-y というカット&ペーストで 3行目の c の直後で行う。 1: a 2: b 3: ca 4: b 5: c before: begin=3 end=3 after : begin=3 end=5 before: begin=3 end=5 after : begin=3 end=5 before: begin=5 end=5 after : begin=5 end=5 C-y (yank) を行うと、何故か 3回呼ばれる。(要ソース読み) 次に 1: a 2: b 3: ca 4: b 5: c というバッファがあるとして、5行目 から 2行目のbの直後までを C-Space,C-W でカットする。すると 1: a 2: b before: begin=2 end=5 after : begin=2 end=2 となる。 以上のことをふまえて、以下の法則を見つけた(気がする) if (before-begin == after-end) { (before-begin == before-end) { if (previous-edited-line == before-end) { // 前回と違う行を編集しているので // previous-edited-line を insert // before-end を次の previous-edited-line にする。 } else { // 同じ行での編集なので何もしない } } else { // before-begin < line <= before-end を delete (改行コードも) // before-begin を insert // #1 } } else { // 1. 編集前と後でバッファの最終行が変更されていれば、 // その差だけ改行を insert で before-begin に送る // #2 // 2. 1. で得られた差の数値を、 // previous-edited-line が before-begin より下であれば // previous-edited-line に 加える。 // #3 // 3. before-begin > previous-edited-line // && after-end < previous-edited-line // の時、previous-edited-line を insert // 4. before-begin <= line <= after-end までを insert } - #1 before-begin を delete でない理由ですが、 例えばこんな感じ。まあ上にもあるけど 1: a 2: b ってあって、b の先頭で DEL すると 1: ab になる。このとき、before-end である 2 行目は削除されるわけですが before-begin である 1 行目は 変更されている。 なので、before-begin だけは insert を行っているというわけ。 1: 2: で、2行目で DEL だと 1: になるわけで、この場合は変更してないので送る必要はないが、 そこまで判別するのもアレなので、今は同じく送るようにしている。 実害ないし。無駄なのが送られるってのはアレだが。 - #2 改行を入れる必要性について。 例えば 1: a 2: b 3: c 4: d ってあったとき、1〜3をカットし、3の直後にペースとしたとすると 1: a 2: b 3: ca 4: b 5: c 6: d ってなるのが理想的なわけです。しかし、改行を入れてないと 1: a 2: b 3: ca 4: b 5: c と、もともと 4 行目にあった d が上書きされてしまう。 exec-insert-line では、バッファ範囲外の line number に insert 命令が来ると、自動的にその行まで改行を入れるように 記述してあります。なので、この場合だと、変更があったのは 3〜5なので 相手側では 5 行目までは行が確保されるわけ。しかし、insert そのものは、 line number の文字列を消去して書き直す、 上書きみたいなものなので、こんなことがおこったと。 ですから、予め改行しておいて下の行をずらしておき、 書く予定の行を確保しておく。 イメージ的には、改行いれた後は以下の感じ。 最終行が 4 から 6 に変更されてるので、受け取り側には 改行を 2 個送って、そのあと変更部分 (3〜5) を送る 改行のみ 1: a 2: b 3: c 4: 5: 6: d insert 1: a 2: b 3: ca 4: b 5: c 6: d #3 差の分を previous-edited-line に加えているのは、 改行によって行数がずれているからです。 before-begin より上の行であれば影響されないので無視。 ======= 以上。 これでいいんじゃないかと思いました。 現在この感じで実装していますが、今のところちゃんと動いてます(きっと) yank で before/after が 3回も呼ばれているのは謎です。 ちらっとソース読んでみたんですが。。。。ふーんみたいな(何 今のままだと無駄に3回 insert が呼ばれてしまうので optimize 的な意味では、ちゃんと yank を理解すべき。 今は、正確に適切な行が insert/delete されているかを 確かめる状況なので、ひとまず置いておく。 上の条件式で、「もっとコンパクトにできる」「意味不明」ってのがあるかも 誰かヘルプみー 2008-08-26 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el (redit-client-delete-line): TODO REP_project/JavaSessionManager/export にある テスト用の GUI だと、text size が 0 だと 向こうでスルーするらしい。 delete-line-command だとテキストを送る必要がないので 今まで 0 にしてたんだけど、上の問題で delete が反応しなかった。 なので、今は "55555" とかテキストに追加してます。 テスト用GUIが修正されたらこっちも直します。 * redit-client-sm.el (redit-client-after-change-function): fix,TODO insert/delete の条件判定変更。 before-change-function と after-change-function の それぞれの begin line, end line を見て判定する事にした。 Cで書くと if ((before-begin == after-end) && (before-begin != before-end)) { int endl = before-end; while (endl > before-begin) { delete-line(endl); } insert-line(before-begin); } else { int endl = after-end; while (endl >= before-begin) { // 注意 insert-line(endl); } } こんな感じ。詳しい説明聞きたい人は俺に直で。 もしくは後ほど詳しく書きます。 - 注意 >= だと、1文字ずつ編集しても command が送信されてしまう。 > だと全く送信されなくなるので、そこは要修正 * redit-client-sm.el (redit-client-before-change-function): fix insert/delete の条件判定変更のため、 ここでは、beginl と endl を取得するのみ * redit-client-sm.el (redit-client-exec-insert-line): fix 指定したバッファの指定した行に、指定した文字列を 挿入できるように変更。 詳しくは test/buffer-edit に書いてます。 2008-08-23 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * memo: 文字列の長さ、バイト数 UTF-8環境で (length "あいうえお") => 5 (string-bytes "あいうえお") => 15 なわけです。こういうとき、文字数での文字の分割はともかく、 バイト数での分割ってのがなくて、どうしようかと悩んでたんだが、 (setq str (encode-coding-string "あいうえお" 'binary)) => "\222\244\242\222\244\244\222\244\246\222\244\250\222\244\252" だと、 (length str2) => 15 (string-bytes str2) => 15 となるわけだ。つまりそういうことだ(何 length ってのは文字コードとかふまえた上での文字数なのねーまあそうか * redit-client-sm.el (redit-client-process-filter): process-filter で受け取る文字列に 複数の REP command が連結された状態になってて それをどうやって読んでいくかっていうのを追加。多分動いてる。 詳しい変更は test/packet を見ればわかると思う。多分。 test 書いてて思ったけど、やっぱり pack/unpack とか そういうのは redit-client-sm.el に置くんじゃなくて redit-util.el とかに置いた方が test でも使いやすい気がする。知らんけど 2008-08-19 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * thinking: buffer と session の関連性 とりあえずバッファとSessionを関連づけるために SessionInfo なるものを作ってあるんだけど その切り替えをいつするかって話。2007-12-23 に書いてるね。 先生からの助言で、 - Session の情報が必要になるのは SessionManager に送るときだけなので before-change-functions/after-change-functions の時に 切り替えればいいんじゃないか - 表に出てないバッファに対しても変更は効くはずなので、 SessionManager から受け取った REP コマンドによる変更は バッファを指定してバックグラウンドで行う こんな感じになりました。なるほどなるへそ。 で、SessionInfo はハッシュテーブルで管理してて、 キーとして SessionID と その Session に対応するバッファ名 にしようかと思ってる。思ってた。思い続けてた。 で、バッファ名は基本ファイル名なので、重複する恐れがある云々で いろいろ考えてたんだけど、よくよく考えて 通常の emacs でもディレクトリが違ってファイル名同じだったら、 下のファイル名の横に hoge.c<2> みたいな表示が出来る事を思い出した。 つーことでこれでいいんじゃね? ということでこの方法とテストプログラム書いてみる 2008-08-05 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * thinking: delete,replace SessionManager で、delete や replace に対する undo には 編集前の文字列をコマンドに付けないと、 SessionManager が変更できない。 delete: 編集前の文字列 replace: 編集前と後 そんな感じ 2007-12-23 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * thinking: buffer に対しての replace は (replace-string FROM TO) がある。 けど、先輩と一緒に探してみたけど、変数に対しての replace がない。 デフォルトでは実装されてない string.el ってのにありそうで。 まあ、デフォルトである関数を駆使すると FROM で文字列を分割 リストに変換される。: (split-string FROM) TO を間に挟んで文字列に変換 : 関数不明 てかないとは思えないんだよな replace 。 * 日本語関係: 昔のゼミの資料に載ってるしね!! (decode-coding-string "\201\202" 'utf-8) * thining: eid は sid から、sid は bufname からってことにした。 で、global な変数の redit-client-session-id とか editor-id が 要らなくなってしまうが、本当は使いたい。 get-eid-from-session-info みたいなことはできるけど 送る度に毎回呼ぶのはちょっと。どこまで高い負荷かはわからんけど。 で、理想としては バッファ(ファイル)を切り替える度に、bufname->sid を呼んで editor-id に設定してってのがよい。これだと get-* を呼ぶのは バッファ切る変える時だけですむ。 けど、「バッファを切り替えたとき」の hook が無いみたい。 探し方が悪いのか。見つからない。てか無い? いろいろやり方はあるみたい(buffer-list のソートがほげほげ)だが よくわからん。難しい。 「バッファが変更されたとき」はあるけど、これは文字を 打つだけで呼び出されるので余計悪化する。 当分は * redit-client-sm.el: Session Info struct, hash table Session ID から取得できる Session Info 構造体を作成。 これで Session 毎に情報を保持できると信じる。 あとは、bufname => sid => session inf o を作る hash table を2つ(以下のhashのキーについてぐらいを参照)。 こんどは実際に格納したり取り出したりのテストかな * thinking: hash のキーについて 今まで、(buffer-name) をキーにしてコマンドリストをほげほげと 思ってたけど、受け取る command には Session ID があるので それをキーにした方がいいのではと思い始める。 そして、バッファ毎に Session ID は覚えとかないといけないので、 (buffer-name) から Session ID を取得するハッシュテーブルも 必要ではないかと思う。 そして、Session ID 毎に editor ID や seq-no も保持すべき? ================ put-ack, select-ack で Session ID, file name が来るので bufname-to-sid-table => key = bufname, value = sid; sid-to-session-table => key = sid, value = session; // C 風に struct session { int eid; int seq-no; CmdListPtr recv_cmdlist; CmdListPtr send_cmdlist; } ================ こんな二つの hash table を作る方がいいのかな。 bufname はグローバルだし、sid も確か ローカルなSession Managerでは一意に決まるはずだし。 送信受信(insert,delete,replace)の流れ的には - cmd 送信 現在の (buffer-name) をキーとして、 bufname-to-sid-table から Session ID (以下sid) を取得。 sid をキーとして、sid-to-session-table から Editor ID , Seq-no を取得し command を作成。 その command は、sid-to-session-table から取った send_cmdlist に放り込む - cmd 受信 cmd 内の sid で、sid-to-session-table から取得した recv_cmdlist に cmd を放り込む。こんなところか。 put-ack, select-ack の場合、text にファイル名があるはずなので bufname-to-sid-table に file と sid を登録する。 こんなところでしょう。今から実装してみる 2007-12-22 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * gethash(): キーが (gethash "hoge" hash) じゃ使えない。 (gethash 'hoge hash)ならできる。 前は出来たと思ったけど、(buffer-name) は 厳密には文字列じゃなかったってことかなあ さてどうしようか・・・ 2007-12-21 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * thinking: hash の扱い(解答) 解答っつーか・・・ (gethash '(buffer-name) hash) じゃなくて (gethash (buffer-name) hash) だよ。' 要らなかったね!!これでおk。 あと、キーとして (buffer-name) か (current-buffer) が使える。 バッファの名前か、もしくはバッファのオブジェクト?か。 名前も、ファイル名@ホスト名だから(だっけ?)、 一意に決まるので重複しないし。オブジェクトもしかり。 ま、ループ回して速い方を選ぶとするか。 * thinking: hash の扱い join or put command からの流れ 1-1. join command を発行する 1-2. join-ack 内の Session Name の buffer を作成する(そして入る) 1-3. Session Name をキーとして、値には、対応コマンドリストかな 2-1. put command を発行する 2-2. current buffer の名前をキーとして、値は上に同じ。 current buffer の名前は (buffer-name) で取れるわ。 (setf (gethash '(buffer-name) hash) command-list) こんな感じ?ってやってみたらだめだった。 文字列じゃなくて オブジェクト でやらないと?俺もわからん。 まあ、適当に文字列をオブジェクトにすれば、ってできんのか。 * fix: 文字コード 研究室の方針で ## 漢字コードは utfで!! ## ってことで、このプロジェクトも utf に変更しました。 参考として % nkf --overwrite -w *.el これで *.el のファイルは UTF8 (-w) に変換できました。 * TODO: - ファイル毎に buffer を用意し、コマンドが来たら 対応する buffer に書き込む。 buffer は buffer name をハッシュ値として、テーブルで持てばいいかな。 確か lisp ではハッシュテーブルを作れた気がする。 と思って調べてみたら、Emacs 21 以上からか hash 実装は。 でも 「Emacs 20 以前でもシンボル表を用いればできる」そうだ。 (参考->http://www.mew.org/~kazu/doc/elisp/hash.html) - 通信テストは、Session Manager 待ちではあるが、 今のうちに、ある程度のテストルーチンを作ってた方が あとあと楽になりそうな気がしないでもなくも(ry - 受け取ったコマンドは、どのタイミングで適用しようか。 来た瞬間でいいのかなやっぱり。 それとも、貯めて、自分が更新したら?そりゃちがうわな。 - 逆に自分が送る時はどうするんだろう。 1. コマンド発行 2. 適用前のコマンドリストとマージ 3. マージ後のコマンドを送りつつ、適用 こんな感じかなあ。 でも、「適用前のコマンドリスト」ってのがわからん。 それなりの時間貯めとかないと重なるってことないんじゃない? そのためのマージなのか。それともやっぱり貯めたりほげほげするのか 2007-11-11 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el: redit-unpack-int 256 以上を取得できなかったのを修正。4バイトぐらい。 * redit-client-sm.el: redit-*-command REPcommand では 「insert」 なのに ここでは 「write」 なので、時々混乱する。insert に変更。 それに総じて、write-* 関数を insert-* 関数にリネーム。 あと、redit-*-command を使うときに、文字列で定義されてるので (string-to-number redit-read-command) とかやらないといけない。今日の話し合いで 「別に文字列である必要はないぜ」ってことで 全て数値に変更。こっちの方が楽だし、きっと速い。 2007-11-10 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el: set-process-coding-system 送受信するパケットは binary の方が良いと指摘。 そう言われれば確かにそうでした。pack/unpackの意味なす ってことで 'utf-8 から 'binary に変更しました。 * redit-client-sm.el: process-send-string 関連 process-send-string で、以前までは、送るコマンドを (format "%10d%10d" sid eid) って感じの文字列を生成して出力してましたが、 これは、通信用の Perl スクリプトに送るためのものでした。 今は既に、lispから直接 SessionManager にコマンドを送るので、これではだめ。 前々から使ってたけど、(redit-pack sid eid...) ってのに変更しました。 引数を何にするかって参考で、一応 obsolete な記述も残してはいますが。 * redit-client-sm.el: redit-select-command (obsolete) editor側では select 要らないってことで。 これで、editor側で必要なのは join, put, quit, その他編集コマンド。 * cvs-add: translate.el translate のテストルーチン。使い方は M-x load-file RET [translate.el] M-x translate-test ってやると、*Message* バッファに、 translateの結果が出力されます。きっと。 * redit-client-sm.el:unpack-int < (setq num (* byte 4)) < (string-to-char (substring pkt num (+ num 1))))) ---------- > (setq num (* byte 4)) > (string-to-char (substring pkt (- num 1) num)))) 通りで、SMからのACKにある eid や sid を取得できない訳だ。 * error: redit-put-command cmd(redit-put-command, 0, 0, 0, 0, str-length, str) みたいに送ると、GUI SessionManager で受け取る文字列が化ける。 emacs || GUI SessionManager ------++------------------- gongo -> 杯湧 どっちが原因なのか・・・ * TODO 送信文字数がバイトとかになるんで (length str) ぐらいでいけると思ったけど、SMで文字化け。ずれてるんだろうか、 もしくは単に文字コードの問題?でも送ったの "hoge" なんだわ。 ま、それは明日にして寝よう (現在AM2:16) 2007-11-09 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el: TCP/IP通信の実装、それに伴うpack/unpack 久々の更新ですわ。 open-network-stream を追加してみた。 redit-join-command() < (setq redit-client-process < (start-process "reditclient" nil redit-client-program host)) ----- > (setq redit-client-process (open-network-stream > "redit-client" > nil > "localhost" > 8766)) nil は buffer なんだけど、よくわからんので nil 。多分使わない。きっと。 localhost/8766 は、何か仕様変更で SM はデーモンで持つらしいので、 ホスト名/ポート番号 決めうちで。 ここ変えるだけで、後はプロセスを同じように使えます。 Perlスクリプトを使わなくなったので、変更点としては 以前:lisp からREPコマンド"っぽい文字列" -> Perl で文字列受け取って ここでpack->SessionManager へ 現在:lisp から直接 REPコマンドを -> SessionManagerへ ってことで lisp 内で pack/unpack を実装。 (defun pack-int) (defun pack-int-loop) (defun unpack-int) です。 もう少しちゃんとやるべきなんだろうか。 ちゃんと SessionManager で反映されてるので 成功はしてるみたい。偶然? 2006-12-26 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * 独り言 うん、やっぱりpack/unpackの処理はアホだな。 暫定版で出したんだからしょうがない、って言い訳をしておこう。 今のところ0〜255までしかできないので、以下のように変更 ;; num : packする整数 ;; count : byte length (defun pack-int-loop (num count) (if (> count 0) (concat (pack-int-loop (/ num 256) (- count 1)) (char-to-string (% num 256))))) (defun pack-int (num) (pack-int-loop num 4)) ex. num が 30000、byte length が4(32bit)の時 ('X'=不定) ;; loop start count 4 -> (% num 256) => 48 を1バイト目 (/ num 256) => 117 を2バイト目 XXXXXXXX XXXXXXXX XXXXXXXX 00110000 (0 0 0 48) count 3 -> (% num 256) => 117 を2バイト目 (/ num 256) => 0 を3バイト目 XXXXXXXX XXXXXXXX 01110101 00110000 (0 0 117 48) count 2 -> (% num 256) => 0 を3バイト目 (/ num 256) => 0 を4バイト目 XXXXXXXX 00000000 01110101 00110000 (0 0 0 48) count 1 -> (% num 256) => 0 を4バイト目 (/ num 256) => 0 を5バイト目 00000000 00000000 01110101 00110000 (0 0 117 48) ;; loop end これでおkでした。Perl側の unpack でデータ取得できました こんな感じでいいのかな。packソース見たい。 あ〜あとはunpackか。まあ簡単かなpackと同じことすればいいのか。 int だけでいいのかな。浮動小数とかいやですね。 2006-12-24 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el - redit-client-after-change-function () < (progn (redit-client-write-line beginl nil) ;; t) ----- > (progn (redit-client-write-line currline nil) ;; t) while でループしてるのに ずっとbeginlってのはおかしいかな〜と思った * 独り言 pack/unpackもどきができた。まだ使用段階なので組み込んでません。 - pack (defun pack (num) ;; num=42 (concat (char-to-string 0) ;; 4バイト目 (char-to-string 0) ;; 3バイト目 (char-to-string 0) ;; 2バイト目 (char-to-string num))) ;; 1バイト目 => 00000000 00000000 00000000 00101010 lispでバイト列を扱うやりかたがよくわからなかったけど これでなんとかrep_manager.plが unpack できてました。 エンディアンとか考える必要あるかな。 - unpack 受け取ったデータから、各値(command、eid 、etc...)を取り出す。 1〜4、5〜8、9〜12、13〜16、17〜20、21〜24 cmd sid eid seq line t_siz 下位1バイト目(?)に値が入ってるので (substring pkt 3 4) => "*" ;; (char-to-string 42) => "*" なので (string-to-char "*") => 42 ・・・ 値取得成功!! まだまだ見直す所ありそうだけど、 うまくいけば完全に lisp だけで REP できますね 2006-12-15 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * 独り言 open-network-stream で rep_manager.pl に接続できた。 だけど、lisp 側で送信データがうまく作れてない。 (format "%4d%4d%4d%4d%4d%4d" 41 0 0 1 0 0) だと、なんかうまくいかない。 pack/unpackないかな・・・ 2006-12-14 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * 独り言 なんか lisp から network に TCP 接続する方法があるっぽい (open-network-stream NAME BUFFER HOST SERVICE) まだ実証してませんが、なんか使えるっぽいです。(ex. navi-2ch) うまくいけば、redit_client.pl はいらなくなるかも。 文字コード関係はどうしよう。decode-coding-* ぐらいで どうにかならないかな。ならないかも。無駄なヘッダ付加される・・・ * redit-client-sm.el - redit-client-close () linenum が定義されてなかったので、 0 にしました。 別に0で大丈夫ですよね?close だし。多分。。。 * redit-client-sm.el - redit-client-exec-write-line (string) なんか Warning でてたので < (end-of-buffer) ----- > (call-interactively 'end-of-buffer) end-of-buffer は interactive 関数以外で 呼び出したら駄目らしいです。 いろいろ調べてたらこれで Warning 出ないので落ち着きました。 いいのかなこれで。。。 2006-12-12 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> * redit-client-sm.el obsolete function を変更 since Emacs 22.1 < (process-kill-without-query redit-client-process) ----- > (set-process-query-on-exit-flag redit-client-process nil) 第2引数が non-nil だと、emacs終了時に 「`Active processes exist; kill them and exit anyway?' 」 って聞いてきます。process は redit_client.pl のことです。 多分いらないので nil を入れました。 since Emacs 21.1 < (make-local-hook 'before-change-functions) ;; afterも ----- > ;; (make-local-hook 'before-change-functions) not necessary らしいです。21.1以前だと必須みたいですが。 * 独り言 defstruct を使うときは (eval-when-compile (require 'cl)) を加えた後に byte-compile-file してからやると使える。