Mercurial > hg > RemoteEditor > emacs
view redit-client-sm.el @ 62:5e44d3723fa9 v20080828-1
*** empty log message ***
author | gongo |
---|---|
date | Thu, 28 Aug 2008 18:23:27 +0900 |
parents | 2dea55a8d0e4 |
children | 0f7d2aab0e04 |
line wrap: on
line source
;; $Id$ ;; cl-macs でマクロとして定義されているため ;; cl.el をインクルードしておく (require 'cl) ;; ;; REP Command ;; ;; 32 bits 32 32 32 32 32 textsiz ;; o-------o--------o--------o-------o--------o---------o-------... ;; +-------+--------+--------+-------+--------+---------+------+ ;; | cmd | session| editor | seqid | lineno | textsiz | text | ;; | | id | id | | | | | ;; +-------+--------+--------+-------+--------+---------+------+ ;; o-------header section (network order)---------------o-------... ;; ;; textsiz: ;; This size is number of bytes for character string encoded with UTF8. ;; ;; text: ;; This size is variable length (textsiz). ;; (defvar redit-client-process nil "Remote-edit client process.") (defvar redit-client-buffer nil "Remote-edit client's buffer.") (defvar redit-client-buffer-name nil "Remote-edit client's buffer-name.") (defvar redit-client-buffer-number nil "Remote-edit client's buffer-number.") ;; obsolete ;; SessionInfo で管理する ;;(defvar redit-client-editor-id "0" ;;"Remote-edit client's editor-id.") ;; obsolete ;; SessionInfo で管理する ;;(defvar redit-client-session-id 0 ;;"Remote-edit client's session-id.") ;; editor local sequence number (defvar redit-client-seqno 0 "Remote-edit client's editor-id.") (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.") (defvar redit-client-previous-max-line 1 "The max line in the current buffer") (defvar redit-client-after-edited-line 1 "Current cursor line of remote-edit client.") (defvar redit-client-previous-line 1 "Behind cursor line of remote-edit client.") (defvar redit-max-string-length 1004 "Read-Write max length of string.") (defvar redit-process-filter-resume nil "String of the unprocessing in redit-client-process-filter") ;; REP が使用する文字コード (defconst redit-string-coding 'utf-8 "Default coding that REP use") ;; port (defconst redit-process-port 8766 "Default port that REP use") (defvar redit-client-before-begin-line nil "Begin edited line of redit-client-before-change-function") (defvar redit-client-before-end-line nil "End edited line of redit-client-before-change-function") (defvar redit-client-after-begin-line nil "Begin edited line of redit-client-after-change-function") (defvar redit-client-after-end-line nil "End edited line of redit-client-after-change-function") ;; REP command header size (defconst redit-command-header-size 24) (defconst redit-command-offset-cmd 0) (defconst redit-command-offset-sid 4) (defconst redit-command-offset-eid 8) (defconst redit-command-offset-seq 12) (defconst redit-command-offset-lno 16) (defconst redit-command-offset-siz 20) (defconst redit-command-offset-txt 24) (defconst redit-open-command 1) (defconst redit-open-ack 2) (defconst redit-read-command 3) (defconst redit-read-ack 4) (defconst redit-read-finish-ack 5) ;; obsolete (defconst redit-insert-command 6) (defconst redit-insert-ack 7) ;;(defconst redit-write-still-ack "7") ;;(defconst redit-write-finish-ack "8") (defconst redit-delete-line-command 9) (defconst redit-delete-line-ack 10) (defconst redit-close-command 11) (defconst redit-close-ack 12) (defconst redit-replace-command 13) (defconst redit-replace-ack 14) (defconst redit-nop-command 15) ;; REP Session (defconst redit-join-command 41) (defconst redit-join-ack-command 42) (defconst redit-get-command 43) ;; obsolete (defconst redit-get-ack-command 44) ;; obsolete (defconst redit-put-command 45) (defconst redit-put-ack-command 46) (defconst redit-select-command 47) ;; obsolete (defconst redit-select-ack-command 48) (defconst redit-register-command 49) ;; obsolete (defconst redit-register-ack-command 50) ;; obsolete (defconst redit-deregister-command 51) ;; obsolete (defconst redit-deregister-ack-command 52) ;; obsolete (defconst redit-quit-command 53) (defconst redit-quit-ack-command 54) (defconst redit-debug-flag t) (defun redit-debug-message (string) (if (eq redit-debug-flag t) (message string))) ;;;;;;;;;;;;;;;;;; ;; Queue struct ;; ;;;;;;;;;;;;;;;;;; (defstruct Queue (front nil) (rear nil)) ;; memo ;; car: return first element of list ;; cdr: return elements list since the second of list ;; (ex.) ;; (car '(rose violet daisy buttercup)) => rose ;; (cdr '(rose violet daisy buttercup)) => (violet daisy buttercup) ;; enqueue item in queue (defun enqueue (queue item) (let ((new-cell (list item))) (if (Queue-front queue) ;; update last cell (setf (cdr (Queue-rear queue)) new-cell) ;; if queue is empty (setf (Queue-front queue) new-cell)) (setf (Queue-rear queue) new-cell))) ;; dequeue (defun dequeue (queue) (if (Queue-front queue) (prog1 (pop (Queue-front queue)) (unless (Queue-front queue) ;; if queue is empty (setf (Queue-rear queue) nil))))) (defun dequeue-all (queue) "clean queue" (while (Queue-front queue) (dequeue queue))) (defun redit-get-command-from-queue (queue) (nth 0 (Queue-front queue))) (defun redit-get-line-from-queue (queue) (nth 1 (Queue-front queue))) (defun redit-get-uid-from-queue (queue) (nth 2 (Queue-front queue))) (defun redit-get-text-from-queue (queue) (nth 3 (Queue-front queue))) ;;;;;;;;;;;;;;;;;;;;;;;;; ;; Session Info struct ;; ;;;;;;;;;;;;;;;;;;;;;;;;; ;; sid: Session ID ;; eid: Editor ID ;; prevline: この Session に対応するバッファで最後に編集された行 ;; send_cmdlist: rep_command list from user to SessionManager ;; recv_cmdlist: rep_command list from SessionManager to user (defstruct SessionInfo (sid nil) (eid nil) (prevline 1) (send_cmdlist nil) (recv_cmdlist nil)) ;; create and initialize (defun redit-create-session-info (sid eid) (make-SessionInfo :sid sid :eid eid :send_cmdlist (make-Queue) :recv_cmdlist (make-Queue))) (defun redit-get-session-id-from-session-info (sinfo) (SessionInfo-sid sinfo)) (defun redit-get-editor-id-from-session-info (sinfo) (SessionInfo-eid sinfo)) (defun redit-get-sendqueue-from-session-info (sinfo) (SessionInfo-send_cmdlist sinfo)) (defun redit-get-recvqueue-from-session-info (sinfo) (SessionInfo-recv_cmdlist sinfo)) ;; hash table of SessionInfo (defvar htable-sid2bufname (make-hash-table)) (defvar htable-bufname2sinfo (make-hash-table)) (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-put-buf2sinfo (bufname sinfo) (setf (gethash bufname htable-bufname2sinfo) sinfo)) (defun redit-sinfo-get-buf2sinfo (bufname) (gethash bufname htable-bufname2sinfo)) (defun redit-sinfo-rm-buf2sinfo (bufname) (remhash bufname htable-bufname2sinfo)) ;;;;;;;;;;;;;;;;;;; ;; pack / unpack ;; ;;;;;;;;;;;;;;;;;;; (defun redit-pack-int-loop (num count) (if (> count 0) (concat (redit-pack-int-loop (/ num 256) (- count 1)) (char-to-string (% num 256))))) (defun redit-pack-int (num) (redit-pack-int-loop num 4)) (defun redit-pack (cmd sid eid seq lno siz) (concat (redit-pack-int cmd) (redit-pack-int sid) (redit-pack-int eid) (redit-pack-int seq) (redit-pack-int lno) (redit-pack-int siz))) (defun redit-unpack-int-loop (pkt pos count) (if (> count 0) (+ (* (string-to-char (substring pkt pos (1+ pos))) (expt 256 (1- count))) (redit-unpack-int-loop pkt (1+ pos) (1- count))) 0 )) (defun redit-unpack-int (pkt pos) (redit-unpack-int-loop pkt pos 4)) (defun redit-make-packet (cmd sid eid seq lno siz text) (concat (redit-pack cmd sid eid seq lno siz) text)) (defun redit-get-command-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-cmd)) (defun redit-get-session-id-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-sid)) (defun redit-get-editor-id-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-eid)) (defun redit-get-sequence-id-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-seq)) (defun redit-get-line-number-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-lno)) (defun redit-get-text-size-from-pkt (pkt) (redit-unpack-int pkt redit-command-offset-siz)) ;; text のサイズが指定されていればそれを使い、 ;; そうでなければ、redit-get-text-size-from-pkt を実行する (defun redit-get-text-from-pkt (pkt &optional _siz) (let ((size) (text) (offset redit-command-offset-txt)) (setq size (if (null _siz) (redit-get-text-size-from-pkt pkt) _siz)) (if (= size 0) "" (progn (setq text (substring pkt offset (+ offset size))) (decode-coding-string text redit-string-coding))))) ;;;;;;;;;;;;;;;;;; ;; User Command ;; ;;;;;;;;;;;;;;;;;; (defun redit-join-command () "Allow this Emacs process to be a remote-edit session manager for client processes." (interactive) (let (bufname) (setq bufname (encode-coding-string (buffer-name) redit-string-coding)) (if redit-client-process (progn (set-process-sentinel redit-client-process nil) (condition-case () ;; (delete-process redit-client-process) (error nil)))) (setq redit-client-process (open-network-stream "redit-client" nil "localhost" redit-process-port)) ;; called when the process changes state (set-process-sentinel redit-client-process 'redit-client-sentinel) ;; called when the process receive packet (set-process-filter redit-client-process 'redit-client-process-filter) ;; 送受信するデータはバイナリで受け取る。 (set-process-coding-system redit-client-process 'binary 'binary) ;; プロセスが生きてるとき、 emacs を終了しようとすると ;; 「processがうんたらで、本当に切ってもいいの y/n」 ;; って聞かれる。nil てやっておくと聞かれない。 ;; quit を入れるんなら t にして有効にすべきなんだろうか。 ;; 今は nil で (set-process-query-on-exit-flag redit-client-process nil) ;; not necessary since Emacs 21.1 ;; (make-local-hook 'before-change-functions) ;; (make-local-hook 'after-change-functions) (if (string= "*scratch*" bufname) (progn ;; JOIN if buffer-name is "*scratch*" (process-send-string redit-client-process (redit-make-packet redit-join-command 0 0 0 0 7 "bufname")) (redit-debug-message (format "join-command: %d 0 0 0 0 0" redit-join-command)) ) ;; PUT if buffer-name is not "*scratch*" (progn (process-send-string redit-client-process (redit-make-packet redit-put-command 0 0 0 0 (string-bytes bufname) bufname)) (redit-debug-message (format "put-command: %d 0 0 0 0 %d %s" redit-put-command (string-bytes bufname) (buffer-name))) ) ))) (defun redit-quit-command () "quit" (interactive) ;; process kill とかしよう ) ;; obsolete ;;(defun redit-client-open (file) ;; (interactive "P") ;; (if redit-client-process ;; (if (setq file (read-string "Filename: ")) ;; (progn ;; ;; redit-client-process の input に文字列を送信する ;; (process-send-string ;; redit-client-process ;; ;; redit-open-command (01) と file を連結させる ;; (concat redit-open-command file)) ;; ;; redit-client-process から出力を得るまでループ ;; (while (eq nil (accept-process-output redit-client-process))))) ;; (error "redit-client is not running."))) ;; 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."))) ;; linenumで指定された行の編集をサーバへ送る ;; redit-client-process に insert コマンドと ;; バッファ(sid)番号、行番号、行の内容を送り、 Ack を受け取る ;; _text が指定されている場合、バッファのlinenumの文字列ではなく ;; _text で指定された文字列を送信する (defun redit-client-insert-line (linenum isnewline &optional _text) (if redit-client-process (save-excursion (let (sinfo packet text text-size) (if (null _text) (let (beginp endp) (setq beginp (progn (goto-line linenum) (beginning-of-line) (point))) (setq endp (progn (goto-line linenum) (end-of-line) (point))) (setq text (concat (encode-coding-string (concat (buffer-substring beginp endp) (if (eq isnewline t) "\n")) redit-string-coding) ))) (setq text _text)) (setq text-size (string-bytes text)) (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) (if sinfo (let ((sid (SessionInfo-sid sinfo)) (eid (SessionInfo-eid sinfo)) (packet)) (setq packet (redit-make-packet redit-insert-command sid eid (gen-seqno) linenum text-size text)) (process-send-string redit-client-process packet) (redit-debug-message (format "insert-command: %d %d %d %d %d %d %s" redit-insert-command sid eid (gen-seqno) linenum text-size text)) )) )) (error "redit-client is not running."))) ;; linenum で指定した行の削除命令を redit-client-process に送信する (defun redit-client-delete-line (linenum) (if redit-client-process (save-excursion (let (sinfo) (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) (if sinfo (let ((sid (SessionInfo-sid sinfo)) (eid (SessionInfo-eid sinfo)) (packet)) ;; insert lines on server buffer (setq packet (redit-make-packet redit-delete-line-command sid eid (gen-seqno) linenum 5 "55555")) (process-send-string redit-client-process packet) (redit-debug-message (format "delete-line-command: %d %d %d %d %d %d %s" redit-delete-line-command sid eid (gen-seqno) linenum 5 "55555")) )) )) (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")))) ;; 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)) ;; proc == redit-client-process ;; string == redit-client-process からの output (defun redit-client-process-filter (proc string) ;; バッファローカルなフックリスト before-change-functions から ;; redit-client-before-change-function を取り除く. after も同じ ;; proc からの出力に hook しないように (remove-hook 'before-change-functions 'redit-client-before-change-function) (remove-hook 'after-change-functions 'redit-client-after-change-function) (let (cmd sid eid seq lno siz txt allsize cursize) ;; 前回に余った奴があれば、それを前方追加する (setq string (concat redit-process-filter-resume string)) (setq allsize (length string)) (block loop ;; process-filter が受け取れるのは1024byteまで。 ;; なので、string に入っているパケットが途中で切れてる可能性がある (while (> allsize redit-command-header-size) (setq siz (redit-get-text-size-from-pkt string)) ;; ヘッダ (redit-command-header-size) + テキストサイズ (setq cursize (+ redit-command-header-size siz)) ;; パケットが 1024 byte の壁で途切れてる場合、 ;; テキストが読めないので、ループを抜ける (if (> cursize allsize) (return-from loop)) (setq cmd (redit-get-command-from-pkt string)) (setq sid (redit-get-session-id-from-pkt string)) (setq eid (redit-get-editor-id-from-pkt string)) (setq seq (redit-get-sequence-id-from-pkt string)) (setq lno (redit-get-line-number-from-pkt string)) (setq txt (redit-get-text-from-pkt string)) ;; command がどの命令かを判断し、対応した処理をする。case みたい (cond ;; FIXME ;;((if (= command redit-open-ack) ;;(if (/= redit-client-editor-id eid) ;;(redit-client-exec-open-ack string)))) ;;((if (= cmd redit-read-ack) ;;(if (= redit-client-editor-id (redit-get-editor-id-from-pkt string)) ;;(redit-client-exec-read-ack string)))) ;;((if (= command redit-insert-ack) ;;(if (= redit-client-editor-id (redit-get-editor-id-from-pkt string)) ;;(redit-client-exec-insert-ack string)))) ;;((if (= command redit-delete-line-ack) ;;(if (= redit-client-editor-id (redit-get-editor-id-from-pkt string)) ;;(redit-client-exec-delete-line-ack string)))) ;;((if (= command redit-close-ack) ;;(if (= redit-client-editor-id (redit-get-editor-id-from-pkt string)) ;;(redit-client-exec-close-ack string)))) ((if (= cmd redit-insert-command) (redit-client-exec-insert-line sid lno txt))) ((if (= cmd redit-join-ack-command) (redit-client-exec-join txt sid eid))) ((if (= cmd redit-put-ack-command) (redit-client-exec-put sid eid))) ((if (= cmd redit-delete-line-command) (redit-client-exec-delete-line sid lno))) ) (setq allsize (- allsize cursize)) ;; string の分割 (setq string (substring string cursize)) ) ) ) ;; 途切れたやつは次の process-filter の string に入っているので ;; この時点で余った奴を保存し、 ;; 次の process-filter の string の前に連結する (setq redit-process-filter-resume string) (add-hook 'before-change-functions 'redit-client-before-change-function t) (add-hook 'after-change-functions '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)))) ;; currentp の位置の行数を返す (defun real-count-lines (currentp) (+ (count-lines (point-min) currentp) (if (= (save-excursion (goto-char currentp) (current-column)) 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))) ;; before-change-functions に hook される ;; バッファが変更される直前に呼ばれる。 ;; begin と end には変更前の変更部分の始まりと終わりの point が入る (defun redit-client-before-change-function (begin end) (setq redit-client-before-begin-line (real-count-lines begin)) (setq redit-client-before-end-line (real-count-lines end)) (setq redit-client-previous-max-line (real-count-lines (point-max))) ) ;; after-change-functions に hook される ;; バッファが変更された直後に呼ばれる ;; begin と end には変更後の変更部分の始まりと終わりの point が入る (defun redit-client-after-change-function (begin end length) (let (sinfo) (setq sinfo (redit-sinfo-get-buf2sinfo (buffer-name))) ;; 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)) ;; 詳しくは 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))) ;; 前回編集行が、今回の編集の範囲に無ければ insert (if (not (is-value-in-range redit-client-before-begin-line prev-edit-line redit-client-before-end-line)) (progn ;; 行の削除による prev-edit-line のずれを考慮 (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" の付加 ;; 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) ;; 前回編集行が、今回の編集の範囲に無ければ 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 を挿入する (defun redit-client-exec-insert-line (sid editlineno text) (let ((curlineno) (bufname) (sinfo)) ;; SessionID から、このテキストを挿入するべき ;; バッファ名を取得する (setq bufname (redit-sinfo-get-sid2buf sid)) (save-excursion (set-buffer bufname) ;; 指定行番号へ移動 ;; diff には、editlineno と 実際に移動した行番号の差が入る ;; バッファの末尾の行が指定した行に足りない場合に diff > 0 になる (goto-line editlineno) ;; 指定行番号へ移動 (setq curlineno (real-count-lines (point))) ;; 現在の行番号 (if (> editlineno curlineno) ;; buffer の 最後の行番号が、editlineno に足りない場合、 ;; その行数だけ改行し、その行へ移動する。 ;; newline なので、下のようにテキストを削除する必要は無い (progn (end-of-line) (newline (- editlineno curlineno)) (goto-line editlineno)) ;; 行頭から末尾までのテキストを削除 (delete-region (progn (beginning-of-line) (point)) (progn (end-of-line) (point))) ) ;; 新しい行を挿入 (insert text)))) ;; 引き数 string (line_num + text_data) で指定された行を削除する (defun redit-client-exec-delete-line (sid linenum) (let ((diff) (bufname (redit-sinfo-get-sid2buf sid))) (save-excursion (set-buffer bufname) (setq diff (goto-line linenum)) (if (= diff 0) (progn ;; 行頭から末尾までのテキストを削除 (delete-region (progn (beginning-of-line) (point)) (progn (end-of-line) (point))) ;; 指定された行自体を削除 ;; 指定された行番号は別の行の番号を表すことになる (if (= (point) (point-max)) (delete-backward-char 1) (delete-char 1))) ) ))) ;; 何用?相手が開いてるファイルを取得するのかな? ;; read みたいなもん? ;; 引き数 string (buf_num + line_num + text_data) ;;(defun redit-client-exec-open-ack (string) ;; (save-excursion ;; (let ((bufnum (redit-get-editor-id-from-pkt string)) ;; (linenum (redit-get-line-number-from-pkt string))) ;; (make-variable-buffer-local 'redit-client-buffer-name) ;; (make-variable-buffer-local 'redit-client-editor-id) ;; (setq redit-client-buffer-name ;; (redit-get-text-from-pkt string)) ;; (setq redit-client-buffer (get-buffer-create redit-client-buffer-name)) ;; ;; プロセスとバッファを関連づける ;; (set-process-buffer redit-client-process redit-client-buffer) ;; (switch-to-buffer redit-client-buffer) ;; windowのバッファを変更する ;; (make-variable-buffer-local 'redit-client-previous-edited-line) ;; (make-variable-buffer-local 'redit-client-after-edited-line) ;; (make-variable-buffer-local 'redit-client-line-max-in-server) ;; (make-variable-buffer-local 'redit-client-previous-line) ;; (setq redit-client-line-max-in-server linenum) ;; (setq redit-client-editor-id bufnum) ;; (setq redit-client-previous-edited-line 1) ;; (setq redit-client-after-edited-line 1) ;; (setq redit-client-previous-line 1) ;; ;; ;;(add-hook 'before-change-functions ;; ;;'redit-client-before-change-function t t) ;; ;;(add-hook 'after-change-functions ;; ;;'redit-client-after-change-function t t) ;; ;; ;; not necessary since Emacs 21.1 ;; ;; (make-local-hook 'window-scroll-functions) ;; ;; ;; window がスクロールする度に呼ばれる関数群 ;; (add-hook 'window-scroll-functions ;; 'redit-client-update-function t t)))) ;; 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))))) ;; テキストデータを挿入 ;; 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-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 (filename sid eid) (let ((bufname) (sinfo)) ;; SessionInfo の生成 (setq sinfo (redit-create-session-info sid eid)) ;; SessionManager から受け取った、このセッションのファイル名を ;; バッファ名とし、そのバッファを生成する。 (setq bufname (buffer-name (generate-new-buffer filename))) ;; SessionID => BufferName => SessionInfo のテーブル生成 (redit-sinfo-put-sid2buf sid bufname) (redit-sinfo-put-buf2sinfo bufname sinfo) (switch-to-buffer bufname) (redit-debug-message (format "join-ack: Session [%d] %s" sid bufname)) (redit-debug-message (format "Your editor id = %d" eid)) )) ;; //引き数で与えられた string から Session IDを取得する ;; 新仕様で、(put = ファイル有りjoin) ってことになって ;; editor id を返すことになったので、sid と共に eid もセーブする (defun redit-client-exec-put (sid eid) (let (sinfo bufname) ;; SessionInfo の生成 (setq sinfo (redit-create-session-info sid eid)) ;; put (ファイル名付きjoin) を行ったバッファで ;; すでにファイルが開かれている(はずな)ので、それをバッファ名とする (setq bufname (buffer-name)) ;; SessionID => BufferName => SessionInfo のテーブル生成 (redit-sinfo-put-sid2buf sid bufname) (redit-sinfo-put-buf2sinfo bufname sinfo) (switch-to-buffer bufname) (redit-debug-message (format "put-ack Session [%d] %s" sid bufname)) (redit-debug-message (format "Your editor id = %d" eid)) )) ;; SessionIDを名前とした、新しいバッファを開く ;; 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-sentinel (proc msg) (cond ((eq (process-status proc) 'exit) (redit-debug-message "Client subprocess exited")) ((eq (process-status proc) 'signal) (redit-debug-message "Client subprocess killed")))) (defun gen-seqno () "generate editor local sequence number." (setq redit-client-seqno (+ redit-client-seqno 1))) ;;(defun redit-line-translate-out (cque rque) ;; "redit line translate for output" ;; (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0)) ;; (setq xcc 0) ;; (setq xrc 0) ;; (setq cignore 0) ;; (setq rignore 0) ;; (while cque ;; (setq cc (car cque)) ;; (while rque ;; (setq rc (car rque)) ;; ;; -------- translation ------------ ;; ;; (if (< (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc)) ;; (if (= (redit-get-command-from-queue cc) redit-insert-command) (setq xrc (- xrc 1))) ;; (if (= (redit-get-command-from-queue cc) redit-delete-line-command) (setq xrc (- xrc 1)))) ;; ;; (if (> (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc)) ;; (if (= (redit-get-command-from-queue rc) redit-insert-command) (setq xcc (+ xcc 1))) ;; (if (= (redit-get-command-from-queue rc) redit-delete-line-command) (setq xcc (- xcc 1)))) ;; ;; (if (= (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc)) ;; (if (= (redit-get-command-from-queue rc) redit-insert-command) (setq xcc (+ xcc 1))) ;; (if (= (redit-get-command-from-queue rc) redit-replace-command) ;; (if (= (redit-get-command-from-queue cc) redit-insert-command) (setq xrc (+ xrc 1))) ;; (if (= (redit-get-command-from-queue cc) redit-replace-command) (setq cignore 1)) ;; (if (= (redit-get-command-from-queue cc) redit-delete-line-command) (setq crc redit-insert-command) (setq cignore 1)))) ;; ;; (if (= (redit-get-command-from-queue rc) redit-delete-line-command) ;; (if (= (redit-get-command-from-queue cc) redit-insert-command) (setq xrc (+ (redit-get-line-from-queue rc) 1))) ;; (if (= (redit-get-command-from-queue cc) redit-replace-command) (setq cignore 1)) ;; (if (= (redit-get-command-from-queue cc) redit-delete-line-command) (setq cignore 1) (setq rignore 1))) ;; ;; ;; -------- translation ------------ ;; ;; (setq rque (cdr rque))) ;; while rque ;; ;; ;; ignore ;; (if (= cignore 1) ;; ;; xxx ;; (setq cignore 0)) ;; (if (= rignore 1) ;; ;; xxx ;; (setq cignore 0)) ;; ;; ;; -------- add after que ------------ ;; (enqueue after-CQ (concat (format "%2d%2d%9d" (redit-get-command-from-queue cc) (redit-get-uid-from-queue cc) (+ (redit-get-line-from-queue cc) xcc)) (redit-get-text-from-queue cc))) ;; ;; -------- add after que ------------ ;; ;; (setq cque (cdr cque))) ;; while cque ;; ) ;; let ;; ) ;; defun ;; ;;(defun redit-line-translate-in (cque rque) ;; "redit line translate for input" ;; (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0)) ;; (setq xcc 0) ;; (setq xrc 0) ;; (setq cignore 0) ;; (setq rignore 0) ;; (while rque ;; (setq rc (car rque)) ;; (setq cignore 0) ;; (setq rignore 0) ;; (while cque ;; (setq cc (car cque)) ;; ;; -------- translation ------------ ;; ;; (if (and (= cignore 1) (= rignore 1)) ;; (if (< (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc)) ;; (if (= (redit-get-command-from-queue rc) redit-insert-command) (setq xcc (+ xcc 1))) ;; (if (= (redit-get-command-from-queue rc) redit-delete-line-command) (setq xcc (- xcc 1)))) ;; ;; (if (> (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc)) ;; (if (= (redit-get-command-from-queue cc) redit-insert-command) (setq xrc (- xrc 1))) ;; (if (= (redit-get-command-from-queue cc) redit-delete-line-command) (setq xrc (+ xrc 1)))) ;; ;; (if (= (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc)) ;; (if (= (redit-get-command-from-queue cc) redit-insert-command) (setq xcc (+ xcc 1))) ;; (if (= (redit-get-command-from-queue cc) redit-replace-command) ;; (if (= (redit-get-command-from-queue rc) redit-insert-command) (setq xcc (+ xcc 1))) ;; (if (= (redit-get-command-from-queue rc) redit-replace-command) (setq cignore 1)) ;; (if (= (redit-get-command-from-queue rc) redit-delete-line-command) (setq crc redit-insert-command) (setq cignore 1)))) ;; (if (= (redit-get-command-from-queue cc) redit-delete-line-command) ;; (if (= (redit-get-command-from-queue rc) redit-insert-command) (setq xcc (+ (redit-get-line-from-queue cc) 1))) ;; (if (= (redit-get-command-from-queue rc) redit-replace-command) (setq crc redit-insert-command) (setq cignore 1)) ;; (if (= (redit-get-command-from-queue rc) redit-delete-line-command) (setq cignore 1) (setq rignore 1)))) ;; ;; ;; -------- translation ------------ ;; ;; (setq cque (cdr cque))) ;; while rque ;; ;; ;; ignore ;; (if (= cignore 1) ;; ;; xxx ;; (setq cignore 0)) ;; (if (= rignore 1) ;; ;; xxx ;; (setq rignore 0)) ;; ;; ;; -------- add after que ------------ ;; (enqueue after-RQ (concat (format "%2d%2d%9d" (redit-get-command-from-queue rc) (redit-get-uid-from-queue rc) (+ (redit-get-line-from-queue rc) xrc)) (redit-get-text-from-queue rc))) ;; ;; -------- add after que ------------ ;; ;; (setq rque (cdr rque))) ;; while cque ;; ) ;; let ;; ) ;; defun ;; for debug ;;(defun redit-client-print-command-queue () ;; "Print command queue." ;; (interactive) ;; ;;(message redit-client-command-queue)) ;; (let (queue) ;; (setq queue redit-client-command-queue) ;; (while (Queue-front queue) ;; (message (Queue-front queue)) ;; (setq queue (cdr (Queue-rear queue))) ;; ))) ;; ;;(defun redit-client-print-recive-queue () ;; "Print command queue." ;; (interactive) ;; (print redit-client-receive-queue)) ;; ;;(defun redit-client-print-send-queue () ;; "Print command queue." ;; (interactive) ;; (print redit-client-send-queue)) ;; (defun is-value-in-range (min value max) (if (and (<= min value) (<= value max)) t nil))