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)