Mercurial > hg > RemoteEditor > emacs
view ChangeLog @ 40:1978dc75b15c
*** empty log message ***
author | gongo |
---|---|
date | Tue, 19 Aug 2008 16:36:10 +0900 |
parents | ca6df6937dd1 |
children | 991526bc3f16 |
line wrap: on
line source
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, その他編集コマンド。 * 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 してからやると使える。