comparison redit-client-sm.el @ 48:8d73102deff6

*** empty log message ***
author gongo
date Sat, 23 Aug 2008 18:11:26 +0900
parents 991526bc3f16
children 563a0c8c5706
comparison
equal deleted inserted replaced
47:1d131b6064ae 48:8d73102deff6
61 61
62 (defvar redit-process-filter-resume nil 62 (defvar redit-process-filter-resume nil
63 "String of the unprocessing in redit-client-process-filter") 63 "String of the unprocessing in redit-client-process-filter")
64 64
65 ;; REP が使用する文字コード 65 ;; REP が使用する文字コード
66 (defconst rep-string-encoding 'utf-8) 66 (defconst redit-string-coding 'utf-8)
67 67
68 ;; port 68 ;; port
69 (defconst redit-process-port 8766) 69 (defconst redit-process-port 8766)
70 70
71 ;; REP command header size 71 ;; REP command header size
102 (defconst redit-deregister-command 51) ;; obsolete 102 (defconst redit-deregister-command 51) ;; obsolete
103 (defconst redit-deregister-ack-command 52) ;; obsolete 103 (defconst redit-deregister-ack-command 52) ;; obsolete
104 (defconst redit-quit-command 53) 104 (defconst redit-quit-command 53)
105 (defconst redit-quit-ack-command 54) 105 (defconst redit-quit-ack-command 54)
106 106
107
107 ;;;;;;;;;;;;;;;;;; 108 ;;;;;;;;;;;;;;;;;;
108 ;; Queue struct ;; 109 ;; Queue struct ;;
109 ;;;;;;;;;;;;;;;;;; 110 ;;;;;;;;;;;;;;;;;;
110 (defstruct Queue (front nil) (rear nil)) 111 (defstruct Queue (front nil) (rear nil))
111 112
188 (defun redit-set-session-info-to-sid-table (sid sinfo) 189 (defun redit-set-session-info-to-sid-table (sid sinfo)
189 (setf (gethash sid sid-to-session-table) sinfo)) 190 (setf (gethash sid sid-to-session-table) sinfo))
190 (defun redit-get-session-info-from-sid-table (sid) 191 (defun redit-get-session-info-from-sid-table (sid)
191 (gethash sid sid-to-session-table)) 192 (gethash sid sid-to-session-table))
192 193
193
194 ;;;;;;;;;;;;;;;;;;; 194 ;;;;;;;;;;;;;;;;;;;
195 ;; pack / unpack ;; 195 ;; pack / unpack ;;
196 ;;;;;;;;;;;;;;;;;;; 196 ;;;;;;;;;;;;;;;;;;;
197 (defun redit-pack-int-loop (num count) 197 (defun redit-pack-int-loop (num count)
198 (if (> count 0) 198 (if (> count 0)
218 218
219 (defun redit-unpack-int (pkt pos) 219 (defun redit-unpack-int (pkt pos)
220 (redit-unpack-int-loop pkt (* pos 4) 4)) 220 (redit-unpack-int-loop pkt (* pos 4) 4))
221 221
222 222
223 ;; binary この時点では、pkt は binary 形式なので
224 ;; substring でも抽出できる。。。ってことかな(何
225 ;; utf-8 とかで decode されていれば多分出来ないはず
226 ;; (length "あいうえお") => 5
227 ;; (string-bytes "あいうえお") => 15 (utf-8の場合)
228 (defun redit-unpack-str (pkt pos length)
229 (substring pkt (* pos 4) (+ (* pos 4) length)))
230
231 (defun redit-make-packet (cmd sid eid seq lno siz text)
232 (concat (redit-pack cmd sid eid seq lno siz) text))
233
234 (defun redit-get-command-from-pkt (pkt)
235 (redit-unpack-int pkt 1))
236 (defun redit-get-session-id-from-pkt (pkt)
237 (redit-unpack-int pkt 2))
238 (defun redit-get-editor-id-from-pkt (pkt)
239 (redit-unpack-int pkt 3))
240 (defun redit-get-sequence-id-from-pkt (pkt)
241 (redit-unpack-int pkt 4))
242 (defun redit-get-line-number-from-pkt (pkt)
243 (redit-unpack-int pkt 5))
244 (defun redit-get-text-size-from-pkt (pkt)
245 (redit-unpack-int pkt 6))
246
247 ;; text のサイズが指定されていればそれを使い、
248 ;; そうでなければ、get-text-size-from-pkt を実行する
249 (defun redit-get-text-from-pkt (pkt &optional _siz)
250 (let (size)
251 (setq size (if (null _siz) (redit-get-text-size-from-pkt pkt) _siz))
252 (decode-coding-string (redit-unpack-str pkt 6 size) redit-string-coding)))
253
223 ;;;;;;;;;;;;;;;;;; 254 ;;;;;;;;;;;;;;;;;;
224 ;; User Command ;; 255 ;; User Command ;;
225 ;;;;;;;;;;;;;;;;;; 256 ;;;;;;;;;;;;;;;;;;
226 257
227 (defun redit-join-command () 258 (defun redit-join-command ()
228 "Allow this Emacs process to be a remote-edit session manager for client processes." 259 "Allow this Emacs process to be a remote-edit session manager for client processes."
229 (interactive) 260 (interactive)
230 (let (bufname) 261 (let (bufname)
231 (setq bufname (encode-coding-string 262 (setq bufname (encode-coding-string
232 (buffer-name) 263 (buffer-name)
233 rep-string-encoding)) 264 redit-string-coding))
234 265
235 (if redit-client-process 266 (if redit-client-process
236 (progn 267 (progn
237 (set-process-sentinel redit-client-process nil) 268 (set-process-sentinel redit-client-process nil)
238 (condition-case () ;; 269 (condition-case () ;;
246 (set-process-sentinel redit-client-process 'redit-client-sentinel) 277 (set-process-sentinel redit-client-process 'redit-client-sentinel)
247 278
248 ;; called when the process receive packet 279 ;; called when the process receive packet
249 (set-process-filter redit-client-process 'redit-client-process-filter) 280 (set-process-filter redit-client-process 'redit-client-process-filter)
250 281
251 ;; //Code of the process input/output buffer is rep-string-encoding 282 ;; //Code of the process input/output buffer is redit-string-coding
252 ;; //(set-process-coding-system redit-client-process rep-string-encoding rep-string-encoding) 283 ;; //(set-process-coding-system redit-client-process redit-string-coding redit-string-coding)
253 ;; 送受信するデータはバイナリで貰わないといけない。 284 ;; 送受信するデータはバイナリで貰わないといけない。
254 ;; utf-8 じゃなくてずれる可能性があるので 285 ;; utf-8 じゃなくてずれる可能性があるので
255 (set-process-coding-system redit-client-process 'binary 'binary) 286 (set-process-coding-system redit-client-process 'binary 'binary)
256 287
257 ;; プロセスが生きてるとき、 emacs を終了しようとすると 288 ;; プロセスが生きてるとき、 emacs を終了しようとすると
344 (progn (goto-line linenum) (beginning-of-line) (point))) 375 (progn (goto-line linenum) (beginning-of-line) (point)))
345 (setq endp 376 (setq endp
346 (progn (goto-line linenum) (end-of-line) (point))) 377 (progn (goto-line linenum) (end-of-line) (point)))
347 (setq text 378 (setq text
348 (encode-coding-string 379 (encode-coding-string
349 (buffer-substring beginp endp) rep-string-encoding)) 380 (buffer-substring beginp endp) redit-string-coding))
350 (setq length (string-bytes text)) 381 (setq length (string-bytes text))
351 382
352 ;;(setq packet (concat (redit-pack redit-insert-command 383 ;;(setq packet (concat (redit-pack redit-insert-command
353 ;; redit-client-session-id 384 ;; redit-client-session-id
354 ;; redit-client-editor-id 385 ;; redit-client-editor-id
449 480
450 (block loop 481 (block loop
451 ;; process-filter が受け取れるのは1024byteまで。 482 ;; process-filter が受け取れるのは1024byteまで。
452 ;; なので、string に入っているパケットが途中で切れてる可能性がある 483 ;; なので、string に入っているパケットが途中で切れてる可能性がある
453 (while (> allsize redit-command-header-size) 484 (while (> allsize redit-command-header-size)
454 (setq command (rep-get-command-from-pkt string)) 485 (setq command (redit-get-command-from-pkt string))
455 (setq textsize (rep-get-text-size-from-pkt string)) 486 (setq textsize (redit-get-text-size-from-pkt string))
456 487
457 ;; ヘッダ (redit-command-header-size) + テキストサイズ 488 ;; ヘッダ (redit-command-header-size) + テキストサイズ
458 (setq cursize (+ redit-command-header-size textsize)) 489 (setq cursize (+ redit-command-header-size textsize))
459 490
460 ;; パケットが 1024 byte の壁で途切れてる場合、 491 ;; パケットが 1024 byte の壁で途切れてる場合、
461 ;; テキストが読めないので、ループを抜ける 492 ;; テキストが読めないので、ループを抜ける
462 (if (> cursize allsize) (return-from loop)) 493 (if (> cursize allsize) (return-from loop))
463 494
464 (let ((command (rep-get-command-from-pkt string))) 495 (let ((command (redit-get-command-from-pkt string)))
465 ;; command がどの命令かを判断し、対応した処理をする。case みたい 496 ;; command がどの命令かを判断し、対応した処理をする。case みたい
466 (cond 497 (cond
467 ;; FIXME 498 ;; FIXME
468 ;;((if (= command redit-open-ack) 499 ;;((if (= command redit-open-ack)
469 ;;(if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 500 ;;(if (/= redit-client-editor-id (redit-get-editor-id-from-pkt string))
470 ;;(redit-client-exec-open-ack string)))) 501 ;;(redit-client-exec-open-ack string))))
471 502
472 ((if (= command redit-read-ack) 503 ((if (= command redit-read-ack)
473 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 504 (if (= redit-client-editor-id (redit-get-editor-id-from-pkt string))
474 (redit-client-exec-read-ack string)))) 505 (redit-client-exec-read-ack string))))
475 506
476 ((if (= command redit-insert-ack) 507 ((if (= command redit-insert-ack)
477 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 508 (if (= redit-client-editor-id (redit-get-editor-id-from-pkt string))
478 (redit-client-exec-insert-ack string)))) 509 (redit-client-exec-insert-ack string))))
479 510
480 ((if (= command redit-delete-line-ack) 511 ((if (= command redit-delete-line-ack)
481 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 512 (if (= redit-client-editor-id (redit-get-editor-id-from-pkt string))
482 (redit-client-exec-delete-line-ack string)))) 513 (redit-client-exec-delete-line-ack string))))
483 514
484 ((if (= command redit-close-ack) 515 ((if (= command redit-close-ack)
485 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 516 (if (= redit-client-editor-id (redit-get-editor-id-from-pkt string))
486 (redit-client-exec-close-ack string)))) 517 (redit-client-exec-close-ack string))))
487 518
488 ((if (= command redit-insert-command) 519 ((if (= command redit-insert-command)
489 (if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 520 (if (/= redit-client-editor-id (redit-get-editor-id-from-pkt string))
490 (redit-client-exec-insert-line string)))) 521 (redit-client-exec-insert-line string))))
491 522
492 ;; from Session Manager 523 ;; from Session Manager
493 ;; join ack (editor id) 524 ;; join ack (editor id)
494 ((if (= command redit-join-ack-command) 525 ((if (= command redit-join-ack-command)
498 ((if (= command redit-put-ack-command) 529 ((if (= command redit-put-ack-command)
499 (redit-client-exec-put string))) 530 (redit-client-exec-put string)))
500 531
501 ;; delete line 532 ;; delete line
502 ((if (= command redit-delete-line-command) 533 ((if (= command redit-delete-line-command)
503 (if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string)) 534 (if (/= redit-client-editor-id (redit-get-editor-id-from-pkt string))
504 (redit-client-exec-delete-line string)))) 535 (redit-client-exec-delete-line string))))
505 ) 536 )
506 537
507 (setq allsize (- allsize cursize)) 538 (setq allsize (- allsize cursize))
508 ;; string の分割 539 ;; string の分割
613 (setq redit-client-previous-edited-line endl))) 644 (setq redit-client-previous-edited-line endl)))
614 645
615 ;; 引き数で与えられた string (line_num + text_data) から 646 ;; 引き数で与えられた string (line_num + text_data) から
616 ;; 指定された行を削除し、そこに text_data を挿入する 647 ;; 指定された行を削除し、そこに text_data を挿入する
617 (defun redit-client-exec-insert-line (string) 648 (defun redit-client-exec-insert-line (string)
618 (let ((linenum (rep-get-line-number-from-pkt string)) ;; 行番号 649 (let ((linenum (redit-get-line-number-from-pkt string)) ;; 行番号
619 (text (rep-get-text-from-pkt string))) ;; テキストデータ 650 (text (redit-get-text-from-pkt string))) ;; テキストデータ
620 (if (< (real-count-lines (point-max)) linenum) 651 (if (< (real-count-lines (point-max)) linenum)
621 (progn 652 (progn
622 (call-interactively 'end-of-buffer) (newline))) 653 (call-interactively 'end-of-buffer) (newline)))
623 (goto-line linenum) 654 (goto-line linenum)
624 (delete-region (progn (beginning-of-line) (point)) ;; 行の頭から 655 (delete-region (progn (beginning-of-line) (point)) ;; 行の頭から
626 (insert text) ;; テキストデータを挿入 657 (insert text) ;; テキストデータを挿入
627 )) 658 ))
628 659
629 ;; 引き数 string (line_num + text_data) で指定された行を削除する 660 ;; 引き数 string (line_num + text_data) で指定された行を削除する
630 (defun redit-client-exec-delete-line (string) 661 (defun redit-client-exec-delete-line (string)
631 (let ((linenum (rep-get-line-number-from-pkt string))) 662 (let ((linenum (redit-get-line-number-from-pkt string)))
632 (goto-line linenum) 663 (goto-line linenum)
633 ;; 行頭から末尾までのテキストを削除 664 ;; 行頭から末尾までのテキストを削除
634 (delete-region (progn (beginning-of-line) (point)) 665 (delete-region (progn (beginning-of-line) (point))
635 (progn (end-of-line) (point))) 666 (progn (end-of-line) (point)))
636 ;; 指定された行自体を削除 667 ;; 指定された行自体を削除
643 ;; 何用?相手が開いてるファイルを取得するのかな? 674 ;; 何用?相手が開いてるファイルを取得するのかな?
644 ;; read みたいなもん? 675 ;; read みたいなもん?
645 ;; 引き数 string (buf_num + line_num + text_data) 676 ;; 引き数 string (buf_num + line_num + text_data)
646 ;;(defun redit-client-exec-open-ack (string) 677 ;;(defun redit-client-exec-open-ack (string)
647 ;; (save-excursion 678 ;; (save-excursion
648 ;; (let ((bufnum (rep-get-editor-id-from-pkt string)) 679 ;; (let ((bufnum (redit-get-editor-id-from-pkt string))
649 ;; (linenum (rep-get-line-number-from-pkt string))) 680 ;; (linenum (redit-get-line-number-from-pkt string)))
650 ;; (make-variable-buffer-local 'redit-client-buffer-name) 681 ;; (make-variable-buffer-local 'redit-client-buffer-name)
651 ;; (make-variable-buffer-local 'redit-client-editor-id) 682 ;; (make-variable-buffer-local 'redit-client-editor-id)
652 ;; (setq redit-client-buffer-name 683 ;; (setq redit-client-buffer-name
653 ;; (rep-get-text-from-pkt string)) 684 ;; (redit-get-text-from-pkt string))
654 ;; (setq redit-client-buffer (get-buffer-create redit-client-buffer-name)) 685 ;; (setq redit-client-buffer (get-buffer-create redit-client-buffer-name))
655 ;; ;; プロセスとバッファを関連づける 686 ;; ;; プロセスとバッファを関連づける
656 ;; (set-process-buffer redit-client-process redit-client-buffer) 687 ;; (set-process-buffer redit-client-process redit-client-buffer)
657 ;; (switch-to-buffer redit-client-buffer) ;; windowのバッファを変更する 688 ;; (switch-to-buffer redit-client-buffer) ;; windowのバッファを変更する
658 ;; (make-variable-buffer-local 'redit-client-previous-edited-line) 689 ;; (make-variable-buffer-local 'redit-client-previous-edited-line)
680 711
681 ;; string (line_num + text_data) で指定された行に 712 ;; string (line_num + text_data) で指定された行に
682 ;; text_data を挿入する 713 ;; text_data を挿入する
683 (defun redit-client-exec-read-ack (string) 714 (defun redit-client-exec-read-ack (string)
684 (save-excursion 715 (save-excursion
685 (let ((lines (rep-get-line-number-from-pkt string))) 716 (let ((lines (redit-get-line-number-from-pkt string)))
686 ;; redit-client-buffer をカレントバッファにする 717 ;; redit-client-buffer をカレントバッファにする
687 (set-buffer redit-client-buffer) 718 (set-buffer redit-client-buffer)
688 (goto-line lines) 719 (goto-line lines)
689 (beginning-of-line) ;; 行の始めへ移動 720 (beginning-of-line) ;; 行の始めへ移動
690 ;; (delete-region (progn (beginning-of-line) (point)) 721 ;; (delete-region (progn (beginning-of-line) (point))
691 ;; (progn (end-of-line) (point))) 722 ;; (progn (end-of-line) (point)))
692 (insert (rep-get-text-from-pkt string))))) ;; テキストデータを挿入 723 (insert (redit-get-text-from-pkt string))))) ;; テキストデータを挿入
693 724
694 ;; redit-client-line-max-in-server に行番号を入れてる(だけ) 725 ;; redit-client-line-max-in-server に行番号を入れてる(だけ)
695 (defun redit-client-exec-insert-ack (string) 726 (defun redit-client-exec-insert-ack (string)
696 (save-excursion 727 (save-excursion
697 (set-buffer redit-client-buffer) 728 (set-buffer redit-client-buffer)
698 (let ((linenum (rep-get-line-number-from-pkt string ))) 729 (let ((linenum (redit-get-line-number-from-pkt string )))
699 (setq redit-client-line-max-in-server linenum)))) 730 (setq redit-client-line-max-in-server linenum))))
700 731
701 (defun redit-client-exec-delete-line-ack (string) 732 (defun redit-client-exec-delete-line-ack (string)
702 (save-excursion 733 (save-excursion
703 (set-buffer redit-client-buffer) 734 (set-buffer redit-client-buffer)
704 (let ((linenum (rep-get-line-number-from-pkt string))) 735 (let ((linenum (redit-get-line-number-from-pkt string)))
705 (setq redit-client-line-max-in-server linenum)))) 736 (setq redit-client-line-max-in-server linenum))))
706 737
707 ;; プロセスとバッファ、ローカル変数を削除する 738 ;; プロセスとバッファ、ローカル変数を削除する
708 (defun redit-client-exec-close-ack (string) 739 (defun redit-client-exec-close-ack (string)
709 (if redit-client-process 740 (if redit-client-process
713 (kill-all-local-variables)) 744 (kill-all-local-variables))
714 745
715 ;; 引き数で与えられた string から Editor IDを取得する 746 ;; 引き数で与えられた string から Editor IDを取得する
716 (defun redit-client-exec-join (string) 747 (defun redit-client-exec-join (string)
717 (let (sinfo) 748 (let (sinfo)
718 (setq redit-client-editor-id (rep-get-editor-id-from-pkt string)) 749 (setq redit-client-editor-id (redit-get-editor-id-from-pkt string))
719 (setq redit-client-session-id (rep-get-session-id-from-pkt string)) 750 (setq redit-client-session-id (redit-get-session-id-from-pkt string))
720 751
721 (setq sinfo (redit-create-session-info redit-client-editor-id)) 752 (setq sinfo (redit-create-session-info redit-client-editor-id))
722 (redit-set-session-info-to-sid-table redit-client-session-id sinfo) 753 (redit-set-session-info-to-sid-table redit-client-session-id sinfo)
723 (redit-set-sid-to-bufname-table "test.c" redit-client-session-id) 754 (redit-set-sid-to-bufname-table "test.c" redit-client-session-id)
724 755
732 ;; //引き数で与えられた string から Session IDを取得する 763 ;; //引き数で与えられた string から Session IDを取得する
733 ;; 新仕様で、(put = ファイル有りjoin) ってことになって 764 ;; 新仕様で、(put = ファイル有りjoin) ってことになって
734 ;; editor id を返すことになったので、sid と共に eid もセーブする 765 ;; editor id を返すことになったので、sid と共に eid もセーブする
735 (defun redit-client-exec-put (string) 766 (defun redit-client-exec-put (string)
736 (let (sinfo) 767 (let (sinfo)
737 (setq redit-client-editor-id (rep-get-editor-id-from-pkt string)) 768 (setq redit-client-editor-id (redit-get-editor-id-from-pkt string))
738 (setq redit-client-session-id (rep-get-session-id-from-pkt string)) 769 (setq redit-client-session-id (redit-get-session-id-from-pkt string))
739 770
740 (setq sinfo (redit-create-session-info redit-client-editor-id)) 771 (setq sinfo (redit-create-session-info redit-client-editor-id))
741 (redit-set-session-info-to-sid-table redit-client-session-id sinfo) 772 (redit-set-session-info-to-sid-table redit-client-session-id sinfo)
742 (redit-set-sid-to-bufname-table "test.c" redit-client-session-id) 773 (redit-set-sid-to-bufname-table "test.c" redit-client-session-id)
743 774
763 (message "Client subprocess killed")))) 794 (message "Client subprocess killed"))))
764 795
765 (defun gen-seqno () 796 (defun gen-seqno ()
766 "generate editor local sequence number." 797 "generate editor local sequence number."
767 (setq redit-client-seqno (+ redit-client-seqno 1))) 798 (setq redit-client-seqno (+ redit-client-seqno 1)))
768
769 (defun redit-make-packet (cmd sid eid seq lno siz text)
770 (concat (redit-pack cmd sid eid seq lno siz) text))
771
772 (defun rep-get-command-from-pkt (pkt)
773 (redit-unpack-int pkt 1))
774 (defun rep-get-session-id-from-pkt (pkt)
775 (redit-unpack-int pkt 2))
776 (defun rep-get-editor-id-from-pkt (pkt)
777 (redit-unpack-int pkt 3))
778 (defun rep-get-sequence-id-from-pkt (pkt)
779 (redit-unpack-int pkt 4))
780 (defun rep-get-line-number-from-pkt (pkt)
781 (redit-unpack-int pkt 5))
782 (defun rep-get-text-size-from-pkt (pkt)
783 (redit-unpack-int pkt 6))
784
785 ;; コマンド後ろにあるテキストは
786 ;; (substring packet 24)
787 ;; でとれるので、text-size は要らない、とうれしい。
788 ;; が、(通信テストまだなので)例えば連続してパケットが送られて来たとき
789 ;; そのパケットが繋がってしまうと駄目。
790 ;; もし、process-filter が、一つのパケットの処理が終わるまで
791 ;; 後続のパケットを止めててくれるならこれでいけるが。
792 ;; 念のため、受け取った text-size と比較して
793 ;; 同じならおk、だめならそのサイズ分だけ取る、って所か。
794 ;; 最初からサイズ分だけでいいんじゃね?と思ったりもするが。
795 ;; あと、現時点ではサイズが違う(失敗)時の処理いれてない。
796 (defun rep-get-text-from-pkt (pkt)
797 (let ((size) (text))
798 (setq size (rep-get-text-size-from-pkt pkt))
799 (setq text (substring pkt 24))
800 (decode-coding-string text rep-string-encoding)))
801 ;;(if (= size (string-bytes text)) text
802 ;;(decode-coding-string (apply 'concat (split-string text "\xe3"))
803 ;;rep-string-encoding))))
804 799
805 (defun redit-line-translate-out (cque rque) 800 (defun redit-line-translate-out (cque rque)
806 "redit line translate for output" 801 "redit line translate for output"
807 (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0)) 802 (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0))
808 (setq xcc 0) 803 (setq xcc 0)