comparison redit-client-sm.el @ 67:90e10010a4f3

*** empty log message ***
author gongo
date Fri, 19 Sep 2008 17:44:41 +0900
parents dfa3a81d3cde
children bb40c73f7af3
comparison
equal deleted inserted replaced
66:d3088b01c363 67:90e10010a4f3
1 ;; $Id$ 1 ;; $Id$
2 2
3 ;; cl-macs でマクロとして定義されているため 3 ;; defstruct
4 ;; cl.el をインクルードしておく
5 (require 'cl) 4 (require 'cl)
6 5
7 ;; 6 ;;
8 ;; REP Command 7 ;; REP Command
9 ;; 8 ;;
39 "Remote-edit client's editor-id.") 38 "Remote-edit client's editor-id.")
40 39
41 (defvar redit-client-line-max-in-server nil 40 (defvar redit-client-line-max-in-server nil
42 "Value of point-max in server's buffer.") 41 "Value of point-max in server's buffer.")
43 42
44 ;; obsolete
45 ;; Session と繋がっている各バッファで保持する事になったので
46 ;; SessionInfo に持たせている
47 ;;(defvar redit-client-previous-edited-line 1
48 ;;"Current cursor line of remote-edit client.")
49
50 (defvar redit-client-previous-max-line 1
51 "The max line in the current buffer")
52
53 (defvar redit-client-after-edited-line 1 43 (defvar redit-client-after-edited-line 1
54 "Current cursor line of remote-edit client.") 44 "Current cursor line of remote-edit client.")
55 45
56 (defvar redit-client-previous-line 1 46 (defvar redit-client-previous-line 1
57 "Behind cursor line of remote-edit client.") 47 "Behind cursor line of remote-edit client.")
128 (defconst redit-deregister-command 51) ;; obsolete 118 (defconst redit-deregister-command 51) ;; obsolete
129 (defconst redit-deregister-ack-command 52) ;; obsolete 119 (defconst redit-deregister-ack-command 52) ;; obsolete
130 (defconst redit-quit-command 53) 120 (defconst redit-quit-command 53)
131 (defconst redit-quit-ack-command 54) 121 (defconst redit-quit-ack-command 54)
132 122
123 (defconst redit-sync-command 82)
124 (defconst redit-sync-ackcommand 83)
133 125
134 (defconst redit-debug-flag t) 126 (defconst redit-debug-flag t)
135 (defun redit-debug-message (string) 127 (defun redit-debug-message (string)
136 (if (eq redit-debug-flag t) 128 (if (eq redit-debug-flag t)
137 (message string))) 129 (message string)))
179 (defun redit-get-uid-from-queue (queue) 171 (defun redit-get-uid-from-queue (queue)
180 (nth 2 (Queue-front queue))) 172 (nth 2 (Queue-front queue)))
181 (defun redit-get-text-from-queue (queue) 173 (defun redit-get-text-from-queue (queue)
182 (nth 3 (Queue-front queue))) 174 (nth 3 (Queue-front queue)))
183 175
176 (defvar redit-client-send-command-queue (make-Queue))
177
184 ;;;;;;;;;;;;;;;;;;;;;;;;; 178 ;;;;;;;;;;;;;;;;;;;;;;;;;
185 ;; Session Info struct ;; 179 ;; Session Info struct ;;
186 ;;;;;;;;;;;;;;;;;;;;;;;;; 180 ;;;;;;;;;;;;;;;;;;;;;;;;;
187 181
188 ;; sid: Session ID 182 ;; sid: Session ID
214 208
215 (defvar htable-sid2bufname (make-hash-table)) 209 (defvar htable-sid2bufname (make-hash-table))
216 (defvar htable-bufname2sinfo (make-hash-table)) 210 (defvar htable-bufname2sinfo (make-hash-table))
217 211
218 (defun redit-sinfo-put-sid2buf (sid bufname) 212 (defun redit-sinfo-put-sid2buf (sid bufname)
213 ""
219 (setf (gethash sid htable-sid2bufname) bufname)) 214 (setf (gethash sid htable-sid2bufname) bufname))
220 (defun redit-sinfo-get-sid2buf (sid) 215 (defun redit-sinfo-get-sid2buf (sid)
221 (gethash sid htable-sid2bufname)) 216 (gethash sid htable-sid2bufname))
222 (defun redit-sinfo-rm-sid2buf (sid) 217 (defun redit-sinfo-rm-sid2buf (sid)
223 (remhash sid htable-sid2bufname)) 218 (remhash sid htable-sid2bufname))
226 (setf (gethash bufname htable-bufname2sinfo) sinfo)) 221 (setf (gethash bufname htable-bufname2sinfo) sinfo))
227 (defun redit-sinfo-get-buf2sinfo (bufname) 222 (defun redit-sinfo-get-buf2sinfo (bufname)
228 (gethash bufname htable-bufname2sinfo)) 223 (gethash bufname htable-bufname2sinfo))
229 (defun redit-sinfo-rm-buf2sinfo (bufname) 224 (defun redit-sinfo-rm-buf2sinfo (bufname)
230 (remhash bufname htable-bufname2sinfo)) 225 (remhash bufname htable-bufname2sinfo))
231
232 226
233 ;;;;;;;;;;;;;;;;;;; 227 ;;;;;;;;;;;;;;;;;;;
234 ;; pack / unpack ;; 228 ;; pack / unpack ;;
235 ;;;;;;;;;;;;;;;;;;; 229 ;;;;;;;;;;;;;;;;;;;
236 (defun redit-pack-int-loop (num count) 230 (defun redit-pack-int-loop (num count)
377 ;; linenumで指定された行の編集をサーバへ送る 371 ;; linenumで指定された行の編集をサーバへ送る
378 ;; redit-client-process に insert コマンドと 372 ;; redit-client-process に insert コマンドと
379 ;; バッファ(sid)番号、行番号、行の内容を送り、 Ack を受け取る 373 ;; バッファ(sid)番号、行番号、行の内容を送り、 Ack を受け取る
380 ;; _text が指定されている場合、バッファのlinenumの文字列ではなく 374 ;; _text が指定されている場合、バッファのlinenumの文字列ではなく
381 ;; _text で指定された文字列を送信する 375 ;; _text で指定された文字列を送信する
382 (defun redit-client-insert-line (linenum isnewline &optional _text) 376 (defun redit-client-insert-line (linenum &optional isnewline _text)
383 "Send \"redit-insert-command\" to SessionManager. 377 "Send \"redit-insert-command\" to SessionManager.
384 378
385 If current buffer is not connected with SessionManager, 379 If current buffer is not connected with SessionManager,
386 nothing is done (see `redit-client-exec-join', `redit-client-exec-put'). 380 nothing is done (see `redit-client-exec-join', `redit-client-exec-put').
387 381
404 (if redit-client-process 398 (if redit-client-process
405 (save-excursion 399 (save-excursion
406 (let (sinfo) 400 (let (sinfo)
407 (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) 401 (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name)))
408 (if sinfo 402 (if sinfo
409 (let (text text-size) 403 (let ((sid (SessionInfo-sid sinfo))
410 (if (null _text) 404 (eid (SessionInfo-eid sinfo)) (packet) (text) (text-size))
411 (let (beginp endp) 405 (setq text (if (null _text)
412 (goto-line linenum) 406 (encode-coding-string
413 (setq beginp (progn (beginning-of-line) (point))) 407 (get-string-from-buffer linenum)
414 (setq endp (progn (end-of-line) (point))) 408 redit-string-coding)
415 (setq text 409 (setq text _text)))
416 (concat (encode-coding-string
417 (concat (buffer-substring beginp endp)
418 (if (eq isnewline t) "\n"))
419 redit-string-coding)
420 )))
421 (setq text _text))
422 (setq text-size (string-bytes text)) 410 (setq text-size (string-bytes text))
423 (let ((sid (SessionInfo-sid sinfo)) 411
424 (eid (SessionInfo-eid sinfo)) (packet)) 412 (setq packet (redit-make-packet
425 413 redit-insert-command sid eid
426 (setq packet (redit-make-packet 414 (gen-seqno) linenum text-size text))
427 redit-insert-command sid eid
428 (gen-seqno) linenum text-size text))
429 415
430 (process-send-string redit-client-process packet) 416 ;;(process-send-string redit-client-process packet)
417 (enqueue redit-client-send-command-queue packet)
431 418
432 (redit-debug-message 419 (redit-debug-message
433 (format "insert-command: %d %d %d %d %d %d %s" 420 (format "insert-command: %d %d %d %d %d %d %s"
434 redit-insert-command sid eid (gen-seqno) 421 redit-insert-command sid eid (gen-seqno)
435 linenum text-size text)) 422 linenum text-size text))
436 )) 423 )
437 ))) 424 )))
438 (error "redit-client is not running."))) 425 (error "redit-client is not running.")))
439 426
440 ;; linenum で指定した行の削除命令を redit-client-process に送信する 427 ;; linenum で指定した行の削除命令を redit-client-process に送信する
441 (defun redit-client-delete-line (linenum) 428 (defun redit-client-delete-line (linenum)
442 "Send \"redit-delete-line-command\" to SessionManager. 429 "Send \"redit-delete-line-command\" to SessionManager.
450 sid : Session ID corresponding to current buffer. 437 sid : Session ID corresponding to current buffer.
451 eid : Editor ID corresponding to current buffer. 438 eid : Editor ID corresponding to current buffer.
452 (sid & eid are acquired from hash table `SessionInfo'.) 439 (sid & eid are acquired from hash table `SessionInfo'.)
453 seq : Sequence Number. it can be acquired it from function `gen-seqno'. 440 seq : Sequence Number. it can be acquired it from function `gen-seqno'.
454 lno : Delete line number, LINENUM. 441 lno : Delete line number, LINENUM.
455 siz : 0 442 siz : byte size of delete text
456 443
457 * REP command text 444 * REP command text
458 445
459 No text." 446 Deleted string of the LINENUM line of current buffer.
447 "
460 (if redit-client-process 448 (if redit-client-process
461 (save-excursion 449 (save-excursion
462 (let (sinfo) 450 (let (sinfo)
463 (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) 451 (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name)))
464 (if sinfo 452 (if sinfo
465 (let ((sid (SessionInfo-sid sinfo)) 453 (let ((sid (SessionInfo-sid sinfo))
466 (eid (SessionInfo-eid sinfo)) (packet)) 454 (eid (SessionInfo-eid sinfo)) (packet) (text) (text-size))
467 ;; insert lines on server buffer 455 (setq text (get-string-from-buffer linenum))
456 (setq text-size (string-bytes text))
457
468 (setq packet (redit-make-packet 458 (setq packet (redit-make-packet
469 redit-delete-line-command sid eid 459 redit-delete-line-command sid eid
470 (gen-seqno) linenum 5 "55555")) 460 (gen-seqno) linenum text-size text))
471 461
472 (process-send-string redit-client-process packet) 462 ;;(process-send-string redit-client-process packet)
463 (enqueue redit-client-send-command-queue packet)
473 464
474 (redit-debug-message 465 (redit-debug-message
475 (format "delete-line-command: %d %d %d %d %d %d %s" 466 (format "delete-command: %d %d %d %d %d %d %s"
476 redit-delete-line-command sid eid (gen-seqno) 467 redit-delete-line-command sid eid (gen-seqno)
477 linenum 0 "")) 468 linenum text-size text))
478 )) 469 )
479 )) 470 )))
480 (error "redit-client is not running."))) 471 (error "redit-client is not running.")))
472
473 (defun redit-client-replace-line (linenum &optional text)
474 "Send \"redit-delete-line-command\" and \"redit-insert-line-command
475 to SessionManager.
476
477 `redit-replace-command' is obsolete command.
478 Now, replace command is done by using `redit-client-delete-line' and
479 `redit-client-insert-line'.
480
481 For example, now buffer
482
483 1: hoge
484 2: void
485 3: elisp
486
487 argument LINENUM = 2, TEXT = \"redit-client\"
488
489 result
490
491 1: hoge
492 2: redit-client
493 3: elisp
494 "
495 (redit-client-delete-line linenum)
496 (redit-client-insert-line linenum text))
497
498 (defun redit-client-send-rep-command ()
499 (let (command)
500 (setq command (dequeue redit-client-send-command-queue))
501 (while command
502 (process-send-string redit-client-process command)
503 (setq command (dequeue redit-client-send-command-queue))
504 ))
505 )
481 506
482 ;; proc == redit-client-process 507 ;; proc == redit-client-process
483 ;; string == redit-client-process からの output 508 ;; string == redit-client-process からの output
484 (defun redit-client-process-filter (proc string) 509 (defun redit-client-process-filter (proc string)
485 "" 510 ""
559 the beginning BEGIN and end END of the range of old text to be changed. 584 the beginning BEGIN and end END of the range of old text to be changed.
560 585
561 In this function, the line of beginning, end and max line 586 In this function, the line of beginning, end and max line
562 of old buffer are only secured. 587 of old buffer are only secured.
563 " 588 "
564 (setq redit-client-before-begin-line (real-count-lines begin)) 589 (let (sinfo)
565 (setq redit-client-before-end-line (real-count-lines end)) 590 (setq redit-client-before-begin-line (real-count-lines begin))
566 (setq redit-client-previous-max-line (real-count-lines (point-max))) 591 (setq redit-client-before-end-line (real-count-lines end))
592
593 (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name)))
594 (if sinfo
595 (progn
596 ;; previous edit line
597 (let (prev-edit-line)
598 (setq prev-edit-line (SessionInfo-prevline sinfo))
599 (if (/= prev-edit-line redit-client-before-begin-line)
600 (progn
601 (redit-client-replace-line prev-edit-line))))
602
603 ;; delete-line
604 (let (editl)
605 (setq editl redit-client-before-end-line)
606 (if (> editl redit-client-before-begin-line)
607 (while (>= editl redit-client-before-begin-line)
608 (redit-client-delete-line editl)
609 (setq editl (1- editl)))))
610 )
611 )
612 )
567 ) 613 )
568 614
569 (defun redit-client-after-change-function (begin end length) 615 (defun redit-client-after-change-function (begin end length)
570 "This function was added at the hook `after-change-functions' list. 616 "This function was added at the hook `after-change-functions' list.
571 It call after each text change of all buffer. 617 It call after each text change of all buffer.
585 (let ((editl) (cur-max-line) (max-line-diff) 631 (let ((editl) (cur-max-line) (max-line-diff)
586 (prev-edit-line) (lf-flg nil)) 632 (prev-edit-line) (lf-flg nil))
587 633
588 (setq redit-client-after-begin-line (real-count-lines begin)) 634 (setq redit-client-after-begin-line (real-count-lines begin))
589 (setq redit-client-after-end-line (real-count-lines end)) 635 (setq redit-client-after-end-line (real-count-lines end))
590 (setq cur-max-line (real-count-lines (point-max)))
591 (setq prev-edit-line (SessionInfo-prevline sinfo))
592 636
593 ;; 詳しくは ChangeLog [2008-08-28] を見て 637 ;; 詳しくは ChangeLog [2008-08-28] を見て
594 (if (= redit-client-before-begin-line redit-client-after-end-line) 638 (if (= redit-client-before-begin-line redit-client-after-end-line)
595 (progn 639 ;; case delete
596 (setq max-line-diff 640 (if (/= redit-client-before-begin-line
597 (- redit-client-previous-max-line cur-max-line)) 641 redit-client-before-end-line)
598 642 (redit-client-insert-line redit-client-before-begin-line))
599 ;; delete-line 643
600 (setq editl redit-client-before-end-line)
601 (while (> editl redit-client-before-begin-line)
602 (redit-client-delete-line editl)
603 (setq editl (1- editl)))
604
605 ;; 前回編集行が、今回の編集の範囲に無ければ insert
606 (if (not
607 (is-value-in-range redit-client-before-begin-line
608 prev-edit-line
609 redit-client-before-end-line))
610 (progn
611 ;; 行の削除による prev-edit-line のずれを考慮
612 (redit-client-insert-line
613 (if (> prev-edit-line redit-client-before-end-line)
614 (- prev-edit-line max-line-diff) prev-edit-line)
615 nil)
616 (redit-client-insert-line
617 redit-client-before-begin-line nil)
618 )
619 )
620 )
621 (progn 644 (progn
622 ;; 行の追加によって最終行が増えていれば 645 ;; case insert or replace
623 ;; insert する行の最後尾に "\n" を付加する。
624 ;; また prev-edit-line が変化している可能性があるのでそれの修正
625 (setq max-line-diff
626 (- cur-max-line redit-client-previous-max-line))
627 (if (> max-line-diff 0)
628 (setq lf-flg t)) ;;
629
630 ;; insert
631 (setq editl redit-client-before-begin-line) 646 (setq editl redit-client-before-begin-line)
632 (while (< editl redit-client-after-end-line) 647 (while (< editl redit-client-after-end-line)
633 (redit-client-insert-line editl lf-flg) 648 (redit-client-insert-line editl)
634 (setq editl (1+ editl)) 649 (setq editl (1+ editl)))
635 ) 650
636 (redit-client-insert-line redit-client-after-end-line nil) 651 ;; case insert
637 652 (if (= redit-client-before-begin-line
638 ;; 前回編集行が、今回の編集の範囲に無ければ insert 653 redit-client-before-end-line)
639 (if (not (is-value-in-range redit-client-before-begin-line 654 (redit-client-delete-line redit-client-after-end-line))
640 prev-edit-line 655
641 redit-client-after-end-line)) 656 (redit-client-insert-line redit-client-after-end-line)
642 (redit-client-insert-line
643 (if (> prev-edit-line redit-client-before-begin-line)
644 (+ prev-edit-line max-line-diff) prev-edit-line)
645 nil)
646 )
647 ) 657 )
648 ) 658 )
649 659
660 (redit-client-send-rep-command)
650 (setf (SessionInfo-prevline sinfo) redit-client-after-end-line) 661 (setf (SessionInfo-prevline sinfo) redit-client-after-end-line)
651 )))) 662 ))))
652 663
653 (defun redit-client-exec-insert-line (sid linenum text) 664 (defun redit-client-exec-insert-line (sid linenum text)
654 "Call when received \"redit-insert-command\" from SessionManager. 665 "Call when received \"redit-insert-command\" from SessionManager.
666 677
667 result 678 result
668 679
669 1: hoge 680 1: hoge
670 2: redit-client 681 2: redit-client
671 3: elisp" 682 3: void
683 4: elisp"
672 (let (curlineno bufname sinfo) 684 (let (curlineno bufname sinfo)
673 ;; SessionID から、このテキストを挿入するべき
674 ;; バッファ名を取得する
675 (setq bufname (redit-sinfo-get-sid2buf sid)) 685 (setq bufname (redit-sinfo-get-sid2buf sid))
676 686
677 (save-excursion 687 (save-excursion
678 (set-buffer bufname) 688 (set-buffer bufname)
679 689
680 (goto-line linenum) 690 (goto-line linenum)
681 (setq curlineno (real-count-lines (point))) 691 (setq curlineno (real-count-lines (point)))
692
682 (if (> linenum curlineno) 693 (if (> linenum curlineno)
683 ;; buffer の 最後の行番号が、linenum に足りない場合、 694 ;; buffer の 最後の行番号が、linenum に足りない場合、
684 ;; その行数だけ改行し、その行へ移動する。 695 ;; その行数だけ改行し、その行へ移動する。
685 ;; newline なので、下のようにテキストを削除する必要は無い 696 ;; newline なので、下のようにテキストを削除する必要は無い
686 (progn (end-of-line) 697 (progn (end-of-line)
687 (newline (- linenum curlineno)) 698 (newline (- linenum curlineno))
688 (goto-line linenum)) 699 (goto-line linenum)))
689 700
690 ;; 行頭から末尾までのテキストを削除 701 (beginning-of-line)
691 (delete-region (progn (beginning-of-line) (point)) 702 (insert (concat text "\n"))
692 (progn (end-of-line) (point)))
693 )
694
695 (insert text)
696 ))) 703 )))
697 704
698 (defun redit-client-exec-delete-line (sid linenum) 705 (defun redit-client-exec-delete-line (sid linenum)
699 "Call when received \"redit-delete-line-command\" from SessionManager. 706 "Call when received \"redit-delete-line-command\" from SessionManager.
700 see. `redit-client-process-filter'. 707 see. `redit-client-process-filter'.
778 785
779 (redit-debug-message (format "put-ack Session [%d] %s" sid bufname)) 786 (redit-debug-message (format "put-ack Session [%d] %s" sid bufname))
780 (redit-debug-message (format "Your editor id = %d" eid)) 787 (redit-debug-message (format "Your editor id = %d" eid))
781 )) 788 ))
782 789
790 (defun redit-client-exec-sync (sid)
791 (let ((max-line (real-count-lines (point-max)))
792 (curline 1))
793 (while (<= curline max-line)
794 (redit-client-delete-line curline)
795 (redit-client-insert-line curline)
796
797 (accept-process-output redit-client-process)
798
799 (setq curline (1+ curline))
800 )
801 )
802 )
803
804
783 ;; プロセスの状態を見て、対応したメッセージを表示 805 ;; プロセスの状態を見て、対応したメッセージを表示
784 (defun redit-client-sentinel (proc msg) 806 (defun redit-client-sentinel (proc msg)
785 (cond ((eq (process-status proc) 'exit) 807 (cond ((eq (process-status proc) 'exit)
786 (redit-debug-message "Client subprocess exited")) 808 (redit-debug-message "Client subprocess exited"))
787 ((eq (process-status proc) 'signal) 809 ((eq (process-status proc) 'signal)
789 811
790 (defun gen-seqno () 812 (defun gen-seqno ()
791 "generate editor local sequence number." 813 "generate editor local sequence number."
792 (setq redit-client-seqno (+ redit-client-seqno 1))) 814 (setq redit-client-seqno (+ redit-client-seqno 1)))
793 815
816 (defun get-string-from-buffer (linenum &optional _bufname)
817 (let (bufname)
818 (if (null _bufname)
819 (setq bufname (buffer-name))
820 (setq bufname _bufname))
821
822 (save-excursion
823 (set-buffer bufname)
824 (goto-line linenum)
825 (buffer-substring (progn (beginning-of-line) (point))
826 (progn (end-of-line) (point)))
827 )
828 )
829 )
794 830
795 (defun is-value-in-range (min value max) 831 (defun is-value-in-range (min value max)
796 (if (and (<= min value) (<= value max)) 832 (if (and (<= min value) (<= value max))
797 t nil)) 833 t nil))