Mercurial > hg > RemoteEditor > emacs
changeset 61:2dea55a8d0e4
*** empty log message ***
author | gongo |
---|---|
date | Thu, 28 Aug 2008 17:19:48 +0900 |
parents | f0a30adf13de |
children | 5e44d3723fa9 |
files | ChangeLog redit-client-sm.el |
diffstat | 2 files changed, 264 insertions(+), 164 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Wed Aug 27 18:29:21 2008 +0900 +++ b/ChangeLog Thu Aug 28 17:19:48 2008 +0900 @@ -1,3 +1,77 @@ +2008-08-28 Wataru MIYAGUNI <gongo@cr.ie.u-ryukyu.ac.jp> + + * 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
--- a/redit-client-sm.el Wed Aug 27 18:29:21 2008 +0900 +++ b/redit-client-sm.el Thu Aug 28 17:19:48 2008 +0900 @@ -47,6 +47,9 @@ (defvar redit-client-line-max-in-server nil "Value of point-max in server's buffer.") +;; obsolete +;; Session と繋がっている各バッファで保持する事になったので +;; SessionInfo に持たせている (defvar redit-client-previous-edited-line 1 "Current cursor line of remote-edit client.") @@ -130,7 +133,7 @@ (defconst redit-quit-ack-command 54) -(defconst redit-debug-flag nil) +(defconst redit-debug-flag t) (defun redit-debug-message (string) (if (eq redit-debug-flag t) (message string))) @@ -213,14 +216,14 @@ (defvar htable-sid2bufname (make-hash-table)) (defvar htable-bufname2sinfo (make-hash-table)) -(defun redit-sinfo-add-sid2buf (sid bufname) +(defun redit-sinfo-put-sid2buf (sid bufname) (setf (gethash sid htable-sid2bufname) bufname)) (defun redit-sinfo-get-sid2buf (sid) (gethash sid htable-sid2bufname)) (defun redit-sinfo-rm-sid2buf (sid) (remhash sid htable-sid2bufname)) -(defun redit-sinfo-add-buf2sinfo (bufname sinfo) +(defun redit-sinfo-put-buf2sinfo (bufname sinfo) (setf (gethash bufname htable-bufname2sinfo) sinfo)) (defun redit-sinfo-get-buf2sinfo (bufname) (gethash bufname htable-bufname2sinfo)) @@ -369,16 +372,16 @@ ;; redit-client-process にreadコマンドとバッファ番号、行番号を送り、 ;; サーバからの出力を得る -(defun redit-client-read-line (linenum) - (if redit-client-process - (save-excursion - (progn - (process-send-string - redit-client-process - (format "%10d%10d%10d%10d%10d%10d\n" redit-read-command redit-client-session-id redit-client-editor-id (gen-seqno) linenum 0)) - (while (eq nil - (accept-process-output redit-client-process))))) - (error "redit-client is not running."))) +;;(defun redit-client-read-line (linenum) +;; (if redit-client-process +;; (save-excursion +;; (progn +;; (process-send-string +;; redit-client-process +;; (format "%10d%10d%10d%10d%10d%10d\n" redit-read-command redit-client-session-id redit-client-editor-id (gen-seqno) linenum 0)) +;; (while (eq nil +;; (accept-process-output redit-client-process))))) +;; (error "redit-client is not running."))) ;; linenumで指定された行の編集をサーバへ送る @@ -398,9 +401,10 @@ (progn (goto-line linenum) (end-of-line) (point))) (setq text (concat (encode-coding-string - (buffer-substring beginp endp) + (concat (buffer-substring beginp endp) + (if (eq isnewline t) "\n")) redit-string-coding) - (if (eq isnewline t) "\n")))) + ))) (setq text _text)) (setq text-size (string-bytes text)) @@ -409,7 +413,7 @@ (progn (setq redit-client-session-id (SessionInfo-sid sinfo)) (setq redit-client-editor-id (SessionInfo-eid sinfo)) - + (setq packet (redit-make-packet redit-insert-command redit-client-session-id redit-client-editor-id (gen-seqno) linenum @@ -445,31 +449,31 @@ (error "redit-client is not running."))) ;; redit-client-process へcloseコマンドを送る -(defun redit-client-close () - "Save File and exit Remote-edit client." - (interactive) - (let ((line redit-client-previous-line)) - (redit-client-insert-line line nil) - (process-send-string - redit-client-process - (concat - ;; obsolete send string - ;; (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-close-command) redit-client-session-id redit-client-editor-id (gen-seqno) 0 0) - (redit-pack - redit-close-command - redit-client-session-id - redit-client-editor-id - (gen-seqno) 0 0) "\n")))) +;;(defun redit-client-close () +;; "Save File and exit Remote-edit client." +;; (interactive) +;; (let ((line redit-client-previous-line)) +;; (redit-client-insert-line line nil) +;; (process-send-string +;; redit-client-process +;; (concat +;; ;; obsolete send string +;; ;; (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-close-command) redit-client-session-id redit-client-editor-id (gen-seqno) 0 0) +;; (redit-pack +;; redit-close-command +;; redit-client-session-id +;; redit-client-editor-id +;; (gen-seqno) 0 0) "\n")))) ;; redit-client-process を終了させる -(defun redit-client-kill () - "Stop Remote-Edit client process." - (interactive) - (if redit-client-process - (kill-process redit-client-process)) - (if redit-client-buffer - (kill-buffer redit-client-buffer)) - (kill-all-local-variables)) +;;(defun redit-client-kill () +;; "Stop Remote-Edit client process." +;; (interactive) +;; (if redit-client-process +;; (kill-process redit-client-process)) +;; (if redit-client-buffer +;; (kill-buffer redit-client-buffer)) +;; (kill-all-local-variables)) ;; proc == redit-client-process ;; string == redit-client-process からの output @@ -478,9 +482,9 @@ ;; redit-client-before-change-function を取り除く. after も同じ ;; proc からの出力に hook しないように (remove-hook 'before-change-functions - 'redit-client-before-change-function t) + 'redit-client-before-change-function) (remove-hook 'after-change-functions - 'redit-client-after-change-function t) + 'redit-client-after-change-function) (let (command textsize text allsize cursize) ;; 前回に余った奴があれば、それを前方追加する @@ -554,45 +558,45 @@ (setq redit-process-filter-resume string) (add-hook 'before-change-functions - 'redit-client-before-change-function t t) + 'redit-client-before-change-function t) (add-hook 'after-change-functions - 'redit-client-after-change-function t t) + 'redit-client-after-change-function t) ) ;; window-scroll-functions に hook される。 ;; window がスクロールする度に呼ばれる -(defun redit-client-update-function (window window-start) - (if (equal (window-buffer) redit-client-buffer) - (save-excursion - (remove-hook 'before-change-functions - 'redit-client-before-change-function t) - (remove-hook 'after-change-functions - 'redit-client-after-change-function t) - ;; read part. - (while (and (= (point-max) - (window-end nil t)) - (> redit-client-line-max-in-server - (real-count-lines (window-end nil t)))) - ;; (count-lines (window-end nil t)))) - (redit-client-read-line (real-count-lines (window-end nil t)))) - - (if (not (= (count-lines (point-min) (window-end nil t)) - (real-count-lines (window-end nil t)))) - (redit-client-read-line - (progn (goto-line redit-client-line-max-in-server) - (real-count-lines (point))))) - - (if (< redit-client-line-max-in-server - (real-count-lines (window-end nil t))) - (progn (goto-line (window-end nil t)) - (delete-region - (progn (beginning-of-line) (backward-char) (point)) - (progn (forward-char) (end-of-line) (point))))) - - (add-hook 'before-change-functions - 'redit-client-before-change-function t t) - (add-hook 'after-change-functions - 'redit-client-after-change-function t t)))) +;;(defun redit-client-update-function (window window-start) +;; (if (equal (window-buffer) redit-client-buffer) +;; (save-excursion +;; (remove-hook 'before-change-functions +;; 'redit-client-before-change-function t) +;; (remove-hook 'after-change-functions +;; 'redit-client-after-change-function t) +;; ;; read part. +;; (while (and (= (point-max) +;; (window-end nil t)) +;; (> redit-client-line-max-in-server +;; (real-count-lines (window-end nil t)))) +;; ;; (count-lines (window-end nil t)))) +;; (redit-client-read-line (real-count-lines (window-end nil t)))) +;; +;; (if (not (= (count-lines (point-min) (window-end nil t)) +;; (real-count-lines (window-end nil t)))) +;; (redit-client-read-line +;; (progn (goto-line redit-client-line-max-in-server) +;; (real-count-lines (point))))) +;; +;; (if (< redit-client-line-max-in-server +;; (real-count-lines (window-end nil t))) +;; (progn (goto-line (window-end nil t)) +;; (delete-region +;; (progn (beginning-of-line) (backward-char) (point)) +;; (progn (forward-char) (end-of-line) (point))))) +;; +;; (add-hook 'before-change-functions +;; 'redit-client-before-change-function t t) +;; (add-hook 'after-change-functions +;; 'redit-client-after-change-function t t)))) ;; currentp の位置の行数を返す (defun real-count-lines (currentp) @@ -601,12 +605,12 @@ 0) 1 0))) -(defun limited-save-excursion (&rest exprs) - (let ((saved-point (point))) - (while exprs - (eval (car exprs)) - (setq exprs (cdr exprs))) - (goto-char saved-point))) +;;(defun limited-save-excursion (&rest exprs) +;; (let ((saved-point (point))) +;; (while exprs +;; (eval (car exprs)) +;; (setq exprs (cdr exprs))) +;; (goto-char saved-point))) ;; before-change-functions に hook される ;; バッファが変更される直前に呼ばれる。 @@ -621,59 +625,81 @@ ;; バッファが変更された直後に呼ばれる ;; begin と end には変更後の変更部分の始まりと終わりの point が入る (defun redit-client-after-change-function (begin end length) - (let ((endl) (cur-max-line) (max-line-diff) (prev-edit-line) (sinfo)) - (setq redit-client-after-begin-line (real-count-lines begin)) - (setq redit-client-after-end-line (real-count-lines end)) - (setq cur-max-line (real-count-lines (point-max))) - ;;(setq prev-edit-line redit-client-previous-edited-line) + (let (sinfo) (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) - (setq prev-edit-line (SessionInfo-prevline sinfo)) + ;; sinfo が nil であれば、編集されたバッファは + ;; REP と無関係のバッファってことで、以降無視。 + (if sinfo + (let ((editl) (cur-max-line) (max-line-diff) + (prev-edit-line) (flg nil)) + + (setq redit-client-after-begin-line (real-count-lines begin)) + (setq redit-client-after-end-line (real-count-lines end)) + (setq cur-max-line (real-count-lines (point-max))) + (setq prev-edit-line (SessionInfo-prevline sinfo)) + + (setq redit-client-session-id (SessionInfo-sid sinfo)) + (setq redit-client-editor-id (SessionInfo-sid sinfo)) + + ;; 詳しくは ChangeLog [2008-08-28] を見て + (if (= redit-client-before-begin-line redit-client-after-end-line) + (progn + (setq max-line-diff + (- redit-client-previous-max-line cur-max-line)) + + ;; delete-line + (setq editl redit-client-before-end-line) + (while (> editl redit-client-before-begin-line) + (redit-client-delete-line editl) + (setq editl (1- editl))) - ;; 詳しくは ChangeLog [2008-08-27] を見て - (if (= redit-client-before-begin-line - redit-client-after-end-line) - ;; 同じ行での編集 - (if (= redit-client-before-begin-line - redit-client-before-end-line) - ;; 前回編集した所と違う行を編集していれば、 - ;; 前回編集した行を insert する - (if (not (= redit-client-after-end-line prev-edit-line)) - (redit-client-insert-line prev-edit-line nil)) - (progn - ;; 行の削除が行われた - (setq endl redit-client-before-end-line) - (while (> endl redit-client-before-begin-line) - (redit-client-delete-line endl) - (setq endl (1- endl))) - (redit-client-insert-line - redit-client-before-begin-line nil))) - (progn - ;; 行の追加が行われた + ;; 前回編集行が、今回の編集の範囲に無ければ insert + (if (not + (is-value-in-range redit-client-before-begin-line + prev-edit-line + redit-client-before-end-line)) + (progn + ;; 行の削除による prev-edit のずれを考慮 + (redit-client-insert-line + (if (> prev-edit-line redit-client-before-end-line) + (- prev-edit-line max-line-diff) prev-edit-line) + nil) + (redit-client-insert-line + redit-client-before-begin-line nil) + ) + ) + ) + (progn + ;; 行の追加によって最終行が増えていれば + ;; insert する行の最後尾に "\n" を付加する。 + ;; また prev-edit-line が変化している可能性があるのでそれの修正 + (setq max-line-diff + (- cur-max-line redit-client-previous-max-line)) + (if (> max-line-diff 0) + (setq flg t)) ;; "\n" の付加 - ;; 改行の追加 - (setq max-line-diff (- cur-max-line redit-client-previous-max-line)) - (if (> max-line-diff 0) - (progn - (if (> prev-edit-line redit-client-before-begin-line) - (setq prev-edit-line (+ prev-edit-line max-line-diff))) - (let (line-feed) - (setq line-feed (make-string max-line-diff ?\n)) - (redit-client-insert-line redit-client-before-begin-line - nil line-feed)))) - (if (not (is-value-in-range redit-client-before-begin-line - prev-edit-line - redit-client-after-end-line)) - (redit-client-insert-line prev-edit-line nil) - ) - (setq endl redit-client-after-end-line) - (while (>= endl redit-client-before-begin-line) - (redit-client-insert-line endl nil) - (setq endl (1- endl)))) - ) + ;; insert + (setq editl redit-client-before-begin-line) + (while (< editl redit-client-after-end-line) + (redit-client-insert-line editl flg) + (setq editl (1+ editl)) + ) + (redit-client-insert-line redit-client-after-end-line nil) - ;;(setq redit-client-previous-edited-line redit-client-after-end-line) - (setf (SessionInfo-prevline sinfo) redit-client-after-end-line) -)) + ;; 前回編集行が、今回の編集の範囲に無ければ insert + (if (not (is-value-in-range redit-client-before-begin-line + prev-edit-line + redit-client-after-end-line)) + (redit-client-insert-line + (if (> prev-edit-line redit-client-before-begin-line) + (+ prev-edit-line max-line-diff) prev-edit-line) + nil) + ) + ) + ) + + (setf (SessionInfo-prevline sinfo) redit-client-after-end-line) +)))) ;; 引き数で与えられた string (line_num + text_data) から ;; 指定された行を削除し、そこに text_data を挿入する @@ -768,37 +794,37 @@ ;; string (line_num + text_data) で指定された行に ;; text_data を挿入する -(defun redit-client-exec-read-ack (string) - (save-excursion - (let ((lines (redit-get-line-number-from-pkt string))) - ;; redit-client-buffer をカレントバッファにする - (set-buffer redit-client-buffer) - (goto-line lines) - (beginning-of-line) ;; 行の始めへ移動 - ;; (delete-region (progn (beginning-of-line) (point)) - ;; (progn (end-of-line) (point))) - (insert (redit-get-text-from-pkt string))))) ;; テキストデータを挿入 +;;(defun redit-client-exec-read-ack (string) +;; (save-excursion +;; (let ((lines (redit-get-line-number-from-pkt string))) +;; ;; redit-client-buffer をカレントバッファにする +;; (set-buffer redit-client-buffer) +;; (goto-line lines) +;; (beginning-of-line) ;; 行の始めへ移動 +;; ;; (delete-region (progn (beginning-of-line) (point)) +;; ;; (progn (end-of-line) (point))) +;; (insert (redit-get-text-from-pkt string))))) ;; テキストデータを挿入 ;; redit-client-line-max-in-server に行番号を入れてる(だけ) -(defun redit-client-exec-insert-ack (string) - (save-excursion - (set-buffer redit-client-buffer) - (let ((linenum (redit-get-line-number-from-pkt string ))) - (setq redit-client-line-max-in-server linenum)))) - -(defun redit-client-exec-delete-line-ack (string) - (save-excursion - (set-buffer redit-client-buffer) - (let ((linenum (redit-get-line-number-from-pkt string))) - (setq redit-client-line-max-in-server linenum)))) +;;(defun redit-client-exec-insert-ack (string) +;; (save-excursion +;; (set-buffer redit-client-buffer) +;; (let ((linenum (redit-get-line-number-from-pkt string ))) +;; (setq redit-client-line-max-in-server linenum)))) +;; +;;(defun redit-client-exec-delete-line-ack (string) +;; (save-excursion +;; (set-buffer redit-client-buffer) +;; (let ((linenum (redit-get-line-number-from-pkt string))) +;; (setq redit-client-line-max-in-server linenum)))) ;; プロセスとバッファ、ローカル変数を削除する -(defun redit-client-exec-close-ack (string) - (if redit-client-process - (kill-process redit-client-process)) - (if redit-client-buffer - (kill-buffer redit-client-buffer)) - (kill-all-local-variables)) +;;(defun redit-client-exec-close-ack (string) +;; (if redit-client-process +;; (kill-process redit-client-process)) +;; (if redit-client-buffer +;; (kill-buffer redit-client-buffer)) +;; (kill-all-local-variables)) ;; 引き数で与えられた string から Editor IDを取得する (defun redit-client-exec-join (string) @@ -816,8 +842,8 @@ (setq bufname (buffer-name (generate-new-buffer filename))) ;; SessionID => BufferName => SessionInfo のテーブル生成 - (redit-sinfo-add-sid2buf redit-client-session-id bufname) - (redit-sinfo-add-buf2sinfo bufname sinfo) + (redit-sinfo-put-sid2buf redit-client-session-id bufname) + (redit-sinfo-put-buf2sinfo bufname sinfo) (switch-to-buffer bufname) @@ -845,8 +871,8 @@ (setq bufname (buffer-name)) ;; SessionID => BufferName => SessionInfo のテーブル生成 - (redit-sinfo-add-sid2buf redit-client-session-id bufname) - (redit-sinfo-add-buf2sinfo bufname sinfo) + (redit-sinfo-put-sid2buf redit-client-session-id bufname) + (redit-sinfo-put-buf2sinfo bufname sinfo) (switch-to-buffer bufname) @@ -860,9 +886,9 @@ ;; FIXME ;; SessionIDではなく、Session Nameが望ましい? ;; バッファを開いた後、Sessionで開いてるファイルの中身を表示するべき -(defun redit-client-exec-select () - (switch-to-buffer (get-buffer-create - (number-to-string redit-client-session-id)))) +;;(defun redit-client-exec-select () +;; (switch-to-buffer (get-buffer-create +;; (number-to-string redit-client-session-id)))) ;; プロセスの状態を見て、対応したメッセージを表示 (defun redit-client-sentinel (proc msg)