6
|
1 ;; $Id$
|
13
|
2 (defcustom redit-client-program "/Users/gongo/src/cr/REP_project/emacs/redit_client.pl"
|
0
|
3 "The program to use as the remote-edit client."
|
|
4 :group 'redit
|
|
5 :type 'string)
|
|
6
|
6
|
7 ;; 送受信されるコマンドは
|
|
8 ;; 2 + 2 + 9 + data
|
|
9 ;; command_number + buffer_number + line_number + data
|
0
|
10
|
6
|
11 (eval-when-compile (require 'cl))
|
0
|
12
|
|
13 (defvar redit-client-process nil
|
|
14 "Remote-edit client process.")
|
|
15
|
|
16 (defvar redit-client-buffer nil
|
|
17 "Remote-edit client's buffer.")
|
|
18
|
|
19 (defvar redit-client-buffer-name nil
|
|
20 "Remote-edit client's buffer-name.")
|
|
21
|
|
22 (defvar redit-client-buffer-number nil
|
|
23 "Remote-edit client's buffer-number.")
|
|
24
|
|
25 (defvar redit-client-editor-id "0"
|
|
26 "Remote-edit client's editor-id.")
|
|
27
|
2
|
28 (defvar redit-client-session-id 0
|
|
29 "Remote-edit client's session-id.")
|
|
30
|
6
|
31 ;; editor local sequence number
|
0
|
32 (defvar redit-client-seqno 0
|
7
|
33 "Remote-edit client's editor-id.")
|
0
|
34
|
|
35 (defvar redit-client-line-max-in-server nil
|
|
36 "Value of point-max in server's buffer.")
|
|
37
|
|
38 (defvar redit-client-previous-edited-line 1
|
|
39 "Current cursor line of remote-edit client.")
|
|
40
|
|
41 (defvar redit-client-after-edited-line 1
|
|
42 "Current cursor line of remote-edit client.")
|
|
43
|
|
44 (defvar redit-client-previous-line 1
|
|
45 "Behind cursor line of remote-edit client.")
|
|
46
|
|
47 (defvar redit-max-string-length 1004
|
|
48 "Read-Write max length of string.")
|
|
49
|
15
|
50 ; REP が使用する文字コード
|
|
51 (defvar rep-string-encoding 'utf-8)
|
|
52
|
0
|
53 (defvar redit-open-command "1")
|
|
54 (defvar redit-open-ack "2")
|
|
55 (defvar redit-read-command "3")
|
|
56 (defvar redit-read-ack "4")
|
|
57 (defvar redit-read-finish-ack "5")
|
6
|
58 (defvar redit-write-command "6") ;; insert
|
0
|
59 (defvar redit-write-still-ack "7")
|
|
60 (defvar redit-write-finish-ack "8")
|
|
61 (defvar redit-delete-line-command "9")
|
|
62 (defvar redit-delete-line-ack "10")
|
|
63 (defvar redit-close-command "11")
|
|
64 (defvar redit-close-ack "12")
|
|
65 (defvar redit-replace-command "13")
|
|
66
|
|
67 ;; REP Session
|
2
|
68 (defvar redit-join-command "41")
|
|
69 (defvar redit-join-ack-command "42")
|
|
70 (defvar redit-get-command "43")
|
|
71 (defvar redit-get-ack-command "44")
|
|
72 (defvar redit-put-command "45")
|
|
73 (defvar redit-put-ack-command "46")
|
|
74 (defvar redit-select-command "47")
|
|
75 (defvar redit-select-ack-command "48")
|
|
76 (defvar redit-register-command "49")
|
|
77 (defvar redit-register-ack-command "50")
|
|
78 (defvar redit-deregister-command "51")
|
|
79 (defvar redit-deregister-ack-command "52")
|
|
80 (defvar redit-quit-command "53")
|
|
81 (defvar redit-quit-ack-command "54")
|
0
|
82
|
6
|
83 ;; Queue struct
|
13
|
84 ;; (defstruct Queue (front nil) (rear nil))
|
|
85 ;; (setq redit-client-command-queue (make-Queue))
|
|
86 ;; (setq redit-client-receive-queue (make-Queue))
|
|
87 ;; (setq redit-client-send-queue (make-Queue))
|
5
|
88
|
6
|
89 ;; line translated queue
|
13
|
90 ;; (setq after-CQ (make-Queue))
|
|
91 ;; (setq after-RQ (make-Queue))
|
|
92
|
|
93
|
|
94 ;; Fix Me
|
|
95 ;; 適当に作ってしまったので。
|
|
96 ;; 一応コマンドは認識してます。
|
|
97 ;; エンディアンとか考える必要あるん?
|
|
98 (defun pack-int-loop (num count)
|
|
99 (if (> count 0)
|
|
100 (concat
|
|
101 (pack-int-loop (/ num 256) (- count 1))
|
|
102 (char-to-string (% num 256)))))
|
|
103
|
|
104 (defun pack-int (num)
|
|
105 (pack-int-loop num 4))
|
|
106
|
|
107
|
|
108 (defun unpack-int (pkt start end)
|
|
109 (string-to-char (substring pkt start end)))
|
5
|
110
|
0
|
111 (defun redit-client-start (host)
|
|
112 "Allow this Emacs process to be a remote-edit client for client processes."
|
|
113 (interactive "P")
|
|
114 (if redit-client-process
|
|
115 (progn
|
|
116 (set-process-sentinel redit-client-process nil)
|
6
|
117 (condition-case () ;; エラーが起こるとプロセスを消す
|
0
|
118 (delete-process redit-client-process) (error nil))))
|
7
|
119 (if (setq host (read-string "Hostname: ")) ;; minibufferでホスト名を入力させる
|
0
|
120 (let ((process-connection-type nil))
|
6
|
121 ;; クライアントプロセス(redit-client)内のプログラムをスタートさせる。
|
|
122 ;; 引き数として host が与えられる
|
0
|
123 (setq redit-client-process
|
|
124 (start-process "reditclient" nil redit-client-program host))
|
13
|
125
|
|
126
|
6
|
127 ;; redit-client-process の状態が変化すると redit-client-sentinel を呼ぶ
|
0
|
128 (set-process-sentinel redit-client-process 'redit-client-sentinel)
|
6
|
129 ;; redit-client-process からのデータ入力は redit-client-process-filter
|
|
130 ;; を介する
|
0
|
131 (set-process-filter redit-client-process 'redit-client-process-filter)
|
6
|
132 ;; redit-client-process からの入出力を 8-bit codes で取扱う。
|
0
|
133 (set-process-coding-system redit-client-process
|
|
134 'raw-text 'raw-text)
|
6
|
135 ;; emacs が終了すると redit-client-process も終了する
|
|
136 (set-process-query-on-exit-flag redit-client-process nil)
|
|
137
|
|
138 ;; フック変数 before-change-functions, after-change-functions
|
|
139 ;; をバッファローカルにする
|
|
140 ;; not necessary since Emacs 21.1
|
|
141 ;; (make-local-hook 'before-change-functions)
|
|
142 ;; (make-local-hook 'after-change-functions)
|
0
|
143
|
|
144 (message "Remote edit client started.")) (error "redit-client connection refused.")))
|
|
145
|
7
|
146 ;; (redit-join-command ())
|
|
147 (defun redit-join-command (host)
|
0
|
148 "Allow this Emacs process to be a remote-edit session manager for client processes."
|
|
149 (interactive "P")
|
|
150 (if redit-client-process
|
|
151 (progn
|
|
152 (set-process-sentinel redit-client-process nil)
|
6
|
153 (condition-case () ;;
|
0
|
154 (delete-process redit-client-process) (error nil))))
|
|
155 (if (setq host (read-string "Hostname: "))
|
|
156 (let ((process-connection-type nil))
|
13
|
157 ;;(setq redit-client-process
|
|
158 ;;(start-process "reditclient" nil redit-client-program host))
|
|
159
|
|
160 ;; lisp で通信ver
|
|
161 (setq redit-client-process (open-network-stream
|
|
162 "redit-client"
|
|
163 nil
|
|
164 "localhost"
|
|
165 8766))
|
|
166
|
0
|
167 (set-process-sentinel redit-client-process 'redit-client-sentinel)
|
|
168 (set-process-filter redit-client-process 'redit-client-process-filter)
|
|
169 (set-process-coding-system redit-client-process
|
|
170 'raw-text 'raw-text)
|
6
|
171
|
|
172 (set-process-query-on-exit-flag redit-client-process nil)
|
|
173
|
|
174 ;; not necessary since Emacs 21.1
|
|
175 ;; (make-local-hook 'before-change-functions)
|
|
176 ;; (make-local-hook 'after-change-functions)
|
7
|
177
|
|
178 ;; FIXME
|
|
179 ;; concat my hostname this command?
|
|
180 (process-send-string
|
|
181 redit-client-process
|
13
|
182 ;;Perl を使わずに、直接SessionManagerに送ってるので
|
|
183 ;;文字列じゃなくて pack して送信
|
|
184 ;;(concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-join-command) 0 0 (gen-seqno) 0 0) "\n")))
|
|
185 (concat
|
|
186 (pack-int (string-to-number redit-join-command))
|
|
187 (pack-int 0)
|
|
188 (pack-int 0)
|
|
189 (pack-int 0)
|
|
190 (pack-int 0) (pack-int 0))
|
|
191 ))
|
0
|
192 (error "redit-client connection refused.")))
|
|
193
|
6
|
194 ;; (redit-get-command)
|
|
195 (defun redit-get-command ()
|
0
|
196 "get. alias redit-join-command and redit-select-command."
|
6
|
197 (interactive)
|
|
198 (redit-join-command ())
|
|
199 (redit-select-command ()))
|
0
|
200
|
6
|
201 ;; select : select session
|
|
202 ;; ユーザの入力を受け取って、selectコマンドを構成し、通信プロセスに渡す
|
|
203 ;; (redit-select-command ()
|
|
204 (defun redit-select-command (session-name)
|
0
|
205 "select session"
|
|
206 (interactive "P")
|
|
207 (if (setq session-name (read-string "session name:"))
|
6
|
208 (progn
|
|
209 (setq redit-client-session-id (string-to-number session-name))
|
|
210 (process-send-string
|
|
211 redit-client-process
|
|
212 (concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-select-command) redit-client-session-id redit-client-editor-id (gen-seqno) 0 0) session-name "\n"))
|
|
213 )
|
0
|
214 (error "invalid session name.")
|
|
215 )
|
|
216 )
|
|
217
|
6
|
218 ;; (defun redit-put-command ()
|
|
219 ;; "put"
|
|
220 ;; (interactive)
|
|
221 ;; )
|
|
222 (defun redit-put-command (session-name)
|
2
|
223 "put session"
|
|
224 (interactive "P")
|
|
225 (if (setq session-name (read-string "put session name:"))
|
6
|
226 (process-send-string
|
|
227 redit-client-process
|
|
228 (concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-put-command) redit-client-session-id redit-client-editor-id (gen-seqno) 0 0) session-name "\n"))
|
2
|
229 (error "invalid session name.")
|
|
230 )
|
0
|
231 )
|
|
232
|
6
|
233 (defun redit-register-command (session-name)
|
0
|
234 "register"
|
|
235 (interactive "P")
|
|
236 (if (setq session-name (read-string "session name:"))
|
6
|
237 (process-send-string
|
|
238 redit-client-process
|
|
239 (concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-register-command) redit-client-session-id redit-client-editor-id (gen-seqno) 0 0) session-name "\n"))
|
0
|
240 (error "invalid session name.")
|
|
241 )
|
|
242 )
|
|
243
|
6
|
244 (defun redit-deregister-command ()
|
0
|
245 "deregister"
|
|
246 (interactive)
|
|
247 )
|
|
248
|
6
|
249 (defun redit-quit-command ()
|
0
|
250 "quit"
|
|
251 (interactive)
|
|
252 )
|
|
253
|
|
254 (defun redit-client-open (file)
|
|
255 (interactive "P")
|
|
256 (if redit-client-process
|
|
257 (if (setq file (read-string "Filename: "))
|
|
258 (progn
|
6
|
259 ;; redit-client-process の input に文字列を送信する
|
0
|
260 (process-send-string
|
|
261 redit-client-process
|
6
|
262 ;; redit-open-command (01) と file を連結させる
|
0
|
263 (concat redit-open-command file))
|
6
|
264 ;; redit-client-process から出力を得るまでループ
|
0
|
265 (while (eq nil (accept-process-output redit-client-process)))))
|
|
266 (error "redit-client is not running.")))
|
|
267
|
6
|
268 ;; redit-client-process にreadコマンドとバッファ番号、行番号を送り、
|
|
269 ;; サーバからの出力を得る
|
0
|
270 (defun redit-client-read-line (linenum)
|
|
271 (if redit-client-process
|
|
272 (save-excursion
|
|
273 (progn
|
|
274 (process-send-string
|
|
275 redit-client-process
|
6
|
276 (format "%10d%10d%10d%10d%10d%10d\n" (string-to-number redit-read-command) redit-client-session-id redit-client-editor-id (gen-seqno) linenum 0))
|
0
|
277 (while (eq nil
|
|
278 (accept-process-output redit-client-process)))))
|
|
279 (error "redit-client is not running.")))
|
|
280
|
6
|
281 ;; linenumで指定された行の編集をサーバへ送る
|
|
282 ;; redit-client-process にwriteコマンドとバッファ番号、行番号、行の内容を送り、
|
|
283 ;; Ack を受け取る
|
0
|
284 (defun redit-client-write-line (linenum isnewline)
|
|
285 (if redit-client-process
|
|
286 (save-excursion
|
6
|
287 (let ((beginp) (endp) (length))
|
|
288 ;; write lines on server buffer
|
|
289 (setq beginp
|
10
|
290 (progn (goto-line linenum) (beginning-of-line) (point)))
|
6
|
291 (setq endp
|
|
292 (progn (goto-line linenum) (end-of-line) (point)))
|
15
|
293 ; (setq length (- endp beginp))
|
|
294 ; rep-string-encoding に変換してから長さを求める
|
|
295 (setq length (string-bytes (encode-coding-string (buffer-substring beginp endp) rep-string-encoding)))
|
5
|
296
|
6
|
297 ;; トークンが回ってくるのを待つ場合は、
|
|
298 ;; すぐに process-send-string せずに
|
|
299 ;; 編集情報を保存するだけにとどめる
|
13
|
300 ;;(enqueue
|
|
301 ;;redit-client-command-queue
|
|
302 ;;(concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-write-command) redit-client-session-id redit-client-editor-id (gen-seqno) linenum length)
|
|
303 ;;(buffer-substring beginp endp)
|
|
304 ;;(if (eq isnewline t) "\n")
|
|
305 ;;"\n"))
|
10
|
306
|
6
|
307 ;; redit-client-process へ
|
|
308 ;; command_num + buffer_num + line_num + string
|
|
309 ;; の文字列を送る
|
7
|
310 (process-send-string
|
6
|
311 redit-client-process
|
|
312 (concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-write-command) redit-client-session-id redit-client-editor-id (gen-seqno) linenum length)
|
15
|
313 ; (buffer-substring beginp endp)
|
|
314 ; rep-string-encoding に変換
|
|
315 (encode-coding-string (buffer-substring beginp endp) rep-string-encoding)
|
6
|
316 (if (eq isnewline t) "\n")
|
|
317 "\n"))
|
11
|
318 (sleep-for 0.3)
|
6
|
319 ))
|
0
|
320 (error "redit-client is not running.")))
|
|
321
|
6
|
322 ;; linenum で指定した行の削除命令を redit-client-process に送信する
|
0
|
323 (defun redit-client-delete-line (linenum)
|
|
324 (if redit-client-process
|
|
325 (save-restriction
|
5
|
326
|
6
|
327 ;; トークンが回ってくるのを待つ場合は、
|
|
328 ;; すぐに process-send-string せずに
|
|
329 ;; 編集情報を保存するだけにとどめる
|
13
|
330 ;;(enqueue redit-client-command-queue
|
|
331 ;;(concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-delete-line-command) redit-client-session-id redit-client-editor-id (gen-seqno) linenum 0) "\n"))
|
|
332
|
6
|
333 ;; write lines on server buffer
|
0
|
334 (process-send-string
|
|
335 redit-client-process
|
2
|
336 (concat (format "%10d%10d%10d%10d%10d%10d" (string-to-number redit-delete-line-command) redit-client-session-id redit-client-editor-id (gen-seqno) linenum 0) "\n"))
|
13
|
337 (sleep-for 0.3)
|
6
|
338 )
|
0
|
339 (error "redit-client is not running.")))
|
|
340
|
6
|
341 ;; redit-client-process へcloseコマンドを送る
|
0
|
342 (defun redit-client-close ()
|
|
343 "Save File and exit Remote-edit client."
|
|
344 (interactive)
|
|
345 (let ((line redit-client-previous-line))
|
|
346 (redit-client-write-line line nil)
|
|
347 (process-send-string
|
|
348 redit-client-process
|
8
|
349 (concat (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) "\n"))))
|
0
|
350
|
6
|
351 ;; redit-client-process を終了させる
|
0
|
352 (defun redit-client-kill ()
|
|
353 "Stop Remote-Edit client process."
|
|
354 (interactive)
|
|
355 (if redit-client-process
|
|
356 (kill-process redit-client-process))
|
|
357 (if redit-client-buffer
|
|
358 (kill-buffer redit-client-buffer))
|
|
359 (kill-all-local-variables))
|
|
360
|
6
|
361 ;; proc == redit-client-process
|
|
362 ;; string == redit-client-process からの output
|
0
|
363 (defun redit-client-process-filter (proc string)
|
6
|
364 ;; バッファローカルなフックリスト before-change-functions から
|
|
365 ;; redit-client-before-change-function を取り除く. after も同じ
|
7
|
366 ;; proc からの出力に hook しないように
|
0
|
367 (remove-hook 'before-change-functions
|
|
368 'redit-client-before-change-function t)
|
|
369 (remove-hook 'after-change-functions
|
|
370 'redit-client-after-change-function t)
|
7
|
371
|
2
|
372 (let ((command (rep-get-command-from-pkt string)))
|
6
|
373 ;; command がどの命令かを判断し、対応した処理をする。case みたい
|
0
|
374 (cond
|
6
|
375 ;; FIXME
|
2
|
376 ((if (= command (string-to-number redit-open-ack))
|
7
|
377 (if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
6
|
378 (redit-client-exec-open-ack string))))
|
0
|
379
|
6
|
380 ((if (= command (string-to-number redit-read-ack))
|
|
381 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
382 (redit-client-exec-read-ack string))))
|
0
|
383
|
2
|
384 ((if (= command (string-to-number redit-write-still-ack))
|
6
|
385 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
386 (redit-client-exec-write-still-ack string))))
|
0
|
387
|
2
|
388 ((if (= command (string-to-number redit-delete-line-ack))
|
6
|
389 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
390 (redit-client-exec-delete-line-ack string))))
|
0
|
391
|
2
|
392 ((if (= command (string-to-number redit-close-ack))
|
6
|
393 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
394 (redit-client-exec-close-ack string))))
|
0
|
395
|
2
|
396 ((if (= command (string-to-number redit-write-command))
|
6
|
397 (if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
398 (redit-client-exec-write-line string))))
|
0
|
399
|
6
|
400 ;; from Session Manager
|
|
401 ;; join ack (editor id)
|
2
|
402 ((if (= command (string-to-number redit-join-ack-command))
|
0
|
403 (redit-client-exec-join string)))
|
2
|
404
|
6
|
405 ;; put ack (editor id)
|
2
|
406 ((if (= command (string-to-number redit-put-ack-command))
|
0
|
407 (redit-client-exec-put string)))
|
2
|
408
|
6
|
409 ;; select ack
|
|
410 ;; TODO : start editing
|
2
|
411 ((if (= command (string-to-number redit-select-ack-command))
|
7
|
412 (redit-client-exec-select)))
|
|
413
|
6
|
414 ;; get
|
2
|
415 ((if (= command (string-to-number redit-get-command))
|
6
|
416 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
417 (redit-client-exec-get string))))
|
|
418 ;; register
|
2
|
419 ((if (= command (string-to-number redit-register-command))
|
6
|
420 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
421 (redit-client-exec-register string))))
|
|
422 ;; deregister
|
2
|
423 ((if (= command (string-to-number redit-deregister-command))
|
6
|
424 (if (= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
425 (redit-client-exec-deregister string))))
|
0
|
426
|
6
|
427 ;; delete line
|
2
|
428 ((if (= command (string-to-number redit-delete-line-command))
|
6
|
429 (if (/= redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
430 (redit-client-exec-delete-line string))))
|
7
|
431 ;;((string-equal string ""))
|
|
432 ))
|
0
|
433
|
7
|
434 (add-hook 'before-change-functions
|
|
435 'redit-client-before-change-function t t)
|
|
436 (add-hook 'after-change-functions
|
|
437 'redit-client-after-change-function t t)
|
6
|
438 )
|
7
|
439
|
6
|
440 ;; window-scroll-functions に hook される。
|
|
441 ;; window がスクロールする度に呼ばれる
|
0
|
442 (defun redit-client-update-function (window window-start)
|
|
443 (if (equal (window-buffer) redit-client-buffer)
|
|
444 (save-excursion
|
|
445 (remove-hook 'before-change-functions
|
|
446 'redit-client-before-change-function t)
|
|
447 (remove-hook 'after-change-functions
|
|
448 'redit-client-after-change-function t)
|
6
|
449 ;; read part.
|
0
|
450 (while (and (= (point-max)
|
|
451 (window-end nil t))
|
|
452 (> redit-client-line-max-in-server
|
|
453 (real-count-lines (window-end nil t))))
|
6
|
454 ;; (count-lines (window-end nil t))))
|
0
|
455 (redit-client-read-line (real-count-lines (window-end nil t))))
|
|
456
|
|
457 (if (not (= (count-lines (point-min) (window-end nil t))
|
|
458 (real-count-lines (window-end nil t))))
|
|
459 (redit-client-read-line
|
|
460 (progn (goto-line redit-client-line-max-in-server)
|
|
461 (real-count-lines (point)))))
|
|
462
|
|
463 (if (< redit-client-line-max-in-server
|
|
464 (real-count-lines (window-end nil t)))
|
|
465 (progn (goto-line (window-end nil t))
|
|
466 (delete-region
|
|
467 (progn (beginning-of-line) (backward-char) (point))
|
|
468 (progn (forward-char) (end-of-line) (point)))))
|
|
469
|
|
470 (add-hook 'before-change-functions
|
|
471 'redit-client-before-change-function t t)
|
|
472 (add-hook 'after-change-functions
|
|
473 'redit-client-after-change-function t t))))
|
|
474
|
6
|
475 ;; currentp の位置の行数を返す
|
0
|
476 (defun real-count-lines (currentp)
|
|
477 (+ (count-lines (point-min) currentp)
|
|
478 (if (= (save-excursion (goto-char currentp) (current-column))
|
|
479 0)
|
|
480 1 0)))
|
|
481
|
|
482 (defun limited-save-excursion (&rest exprs)
|
|
483 (let ((saved-point (point)))
|
|
484 (while exprs
|
|
485 (eval (car exprs))
|
|
486 (setq exprs (cdr exprs)))
|
|
487 (goto-char saved-point)))
|
|
488
|
6
|
489 ;; before-change-functions に hook される
|
|
490 ;; バッファに変更があるたびに呼ばれる。バッファが変更される前に呼ばれる。
|
|
491 ;; begin と end には変更前の変更部分の始まりと終わりの point が入る
|
0
|
492 (defun redit-client-before-change-function (begin end)
|
6
|
493 (let ((beginl (real-count-lines begin)) ;; begin の行番号
|
|
494 (endl (real-count-lines end)) ;; end の行番号
|
|
495 (currline)) ;; currline = nil
|
10
|
496
|
|
497 (message "before-change-function")
|
|
498
|
|
499 ;; 前回の編集した行と今回の編集した行が
|
|
500 ;; 違っていたら前回の編集をサーバへ送る
|
0
|
501 (if (not (= beginl redit-client-previous-edited-line))
|
|
502 (redit-client-write-line redit-client-previous-edited-line nil))
|
10
|
503
|
|
504 ;; 削除処理で起こる。
|
|
505 ;; (ex. BackSpaceによる行そのものの削除, C-Space C-wなどのカット, ...)
|
0
|
506 (if (< beginl endl)
|
|
507 (progn
|
|
508 (setq currline endl)
|
6
|
509 ;; endlからbeginlまで行の削除命令を出す
|
0
|
510 (while (> currline beginl)
|
|
511 (redit-client-delete-line endl)
|
|
512 (setq currline (- currline 1)))))))
|
10
|
513
|
6
|
514 ;; after-change-functions に hook される
|
|
515 ;; バッファに変更があるたびに呼ばれる。バッファが変更された後に呼ばれる
|
|
516 ;; begin と end には変更後の変更部分の始まりと終わりの point が入る
|
0
|
517 (defun redit-client-after-change-function (begin end length)
|
|
518 (let ((beginl (real-count-lines begin))
|
|
519 (endl (real-count-lines end))
|
|
520 (currline))
|
10
|
521
|
|
522 (message "after-change-function")
|
|
523
|
|
524 ;; 挿入処理で起こる。
|
|
525 ;; (ex. 改行, C-y などのペースト, ...)
|
0
|
526 (if (< beginl endl)
|
|
527 (progn
|
|
528 (setq currline beginl)
|
6
|
529 ;; beginlからendlまで挿入命令を出す
|
|
530 (while (<= currline endl)
|
10
|
531 (progn (redit-client-write-line currline nil)
|
0
|
532 (setq currline (+ currline 1))))))
|
|
533 (setq redit-client-previous-edited-line endl)))
|
7
|
534
|
6
|
535 ;; 引き数で与えられた string (line_num + text_data) から
|
|
536 ;; 指定された行を削除し、そこに text_data を挿入する
|
0
|
537 (defun redit-client-exec-write-line (string)
|
7
|
538 (let ((linenum (rep-get-line-number-from-pkt string)) ;; 行番号
|
|
539 (text (rep-get-text-from-pkt string))) ;; テキストデータ
|
|
540 (if (< (real-count-lines (point-max)) linenum)
|
|
541 (progn
|
8
|
542 (call-interactively 'end-of-buffer) (newline)))
|
7
|
543 (goto-line linenum)
|
|
544 (delete-region (progn (beginning-of-line) (point)) ;; 行の頭から
|
|
545 (progn (end-of-line) (point))) ;; 行の末尾まで削除
|
|
546 (insert text) ;; テキストデータを挿入
|
10
|
547 (message (concat "recv = " text ", line = " (number-to-string linenum)))
|
7
|
548 ))
|
0
|
549
|
6
|
550 ;; 引き数 string (line_num + text_data) で指定された行を削除する
|
0
|
551 (defun redit-client-exec-delete-line (string)
|
7
|
552 (let ((linenum (rep-get-line-number-from-pkt string)))
|
|
553 (goto-line linenum)
|
|
554 ;; 行頭から末尾までのテキストを削除
|
|
555 (delete-region (progn (beginning-of-line) (point))
|
|
556 (progn (end-of-line) (point)))
|
|
557 ;; 指定された行自体を削除
|
|
558 ;; 指定された行番号は別の行の番号を表すことになる
|
|
559 (if (= (point) (point-max))
|
|
560 (delete-backward-char 1)
|
|
561 (delete-char 1)))
|
|
562 )
|
0
|
563
|
6
|
564 ;; 引き数 string (buf_num + line_num + text_data)
|
0
|
565 (defun redit-client-exec-open-ack (string)
|
7
|
566 (save-excursion
|
|
567 (let ((bufnum (rep-get-editor-id-from-pkt string))
|
|
568 (linenum (rep-get-line-number-from-pkt string)))
|
|
569 (make-variable-buffer-local 'redit-client-buffer-name)
|
|
570 (make-variable-buffer-local 'redit-client-editor-id)
|
|
571 (setq redit-client-buffer-name
|
8
|
572 (rep-get-text-from-pkt string))
|
7
|
573 (setq redit-client-buffer (get-buffer-create redit-client-buffer-name))
|
|
574 ;; プロセスとバッファを関連づける
|
|
575 (set-process-buffer redit-client-process redit-client-buffer)
|
|
576 (switch-to-buffer redit-client-buffer) ;; windowのバッファを変更する
|
|
577 (make-variable-buffer-local 'redit-client-previous-edited-line)
|
|
578 (make-variable-buffer-local 'redit-client-after-edited-line)
|
|
579 (make-variable-buffer-local 'redit-client-line-max-in-server)
|
|
580 (make-variable-buffer-local 'redit-client-previous-line)
|
|
581 (setq redit-client-line-max-in-server linenum)
|
|
582 (setq redit-client-editor-id bufnum)
|
|
583 (setq redit-client-previous-edited-line 1)
|
|
584 (setq redit-client-after-edited-line 1)
|
|
585 (setq redit-client-previous-line 1)
|
|
586 ;;(add-hook 'before-change-functions
|
|
587 ;;'redit-client-before-change-function t t)
|
|
588 ;;(add-hook 'after-change-functions
|
|
589 ;;'redit-client-after-change-function t t)
|
0
|
590
|
7
|
591 ;; not necessary since Emacs 21.1
|
|
592 ;; (make-local-hook 'window-scroll-functions)
|
6
|
593
|
7
|
594 ;; window がスクロールする度に呼ばれる関数群
|
|
595 (add-hook 'window-scroll-functions
|
|
596 'redit-client-update-function t t))))
|
6
|
597
|
|
598 ;; string (line_num + text_data) で指定された行に
|
|
599 ;; text_data を挿入する
|
0
|
600 (defun redit-client-exec-read-ack (string)
|
7
|
601 (save-excursion
|
|
602 (let ((lines (rep-get-line-number-from-pkt string)))
|
|
603 ;; redit-client-buffer をカレントバッファにする
|
|
604 (set-buffer redit-client-buffer)
|
|
605 (goto-line lines)
|
|
606 (beginning-of-line) ;; 行の始めへ移動
|
|
607 ;; (delete-region (progn (beginning-of-line) (point))
|
|
608 ;; (progn (end-of-line) (point)))
|
|
609 (insert (rep-get-text-from-pkt string))))) ;; テキストデータを挿入
|
0
|
610
|
6
|
611 ;; redit-client-line-max-in-server に行番号を入れてる(だけ)
|
0
|
612 (defun redit-client-exec-write-still-ack (string)
|
7
|
613 (save-excursion
|
|
614 (set-buffer redit-client-buffer)
|
|
615 (let ((linenum (rep-get-line-number-from-pkt string )))
|
|
616 (setq redit-client-line-max-in-server linenum))))
|
0
|
617
|
|
618 (defun redit-client-exec-delete-line-ack (string)
|
7
|
619 (save-excursion
|
|
620 (set-buffer redit-client-buffer)
|
|
621 (let ((linenum (rep-get-line-number-from-pkt string)))
|
|
622 (setq redit-client-line-max-in-server linenum))))
|
0
|
623
|
6
|
624 ;; プロセスとバッファ、ローカル変数を削除する
|
0
|
625 (defun redit-client-exec-close-ack (string)
|
7
|
626 (if redit-client-process
|
|
627 (kill-process redit-client-process))
|
|
628 (if redit-client-buffer
|
|
629 (kill-buffer redit-client-buffer))
|
|
630 (kill-all-local-variables))
|
6
|
631
|
|
632 ;; 引き数で与えられた string から Editor IDを取得する
|
|
633 (defun redit-client-exec-join (string)
|
7
|
634 (setq redit-client-editor-id (rep-get-editor-id-from-pkt string))
|
|
635 (insert (concat "eid = " (number-to-string redit-client-editor-id) "\n"))
|
|
636 (insert (rep-get-text-from-pkt string)))
|
0
|
637
|
6
|
638 ;; 引き数で与えられた string から Session IDを取得する
|
2
|
639 (defun redit-client-exec-put (string)
|
7
|
640 (setq redit-client-session-id (rep-get-session-id-from-pkt string))
|
|
641 (insert (concat "put session id = " (number-to-string redit-client-session-id) "\n")))
|
2
|
642
|
6
|
643 ;; SessionIDを名前とした、新しいバッファを開く
|
|
644 ;; FIXME
|
|
645 ;; SessionIDではなく、Session Nameが望ましい?
|
|
646 ;; バッファを開いた後、Sessionで開いてるファイルの中身を表示するべき
|
|
647 (defun redit-client-exec-select ()
|
7
|
648 (switch-to-buffer (get-buffer-create
|
|
649 (number-to-string redit-client-session-id))))
|
6
|
650
|
|
651 ;; プロセスの状態を見て、対応したメッセージを表示
|
0
|
652 (defun redit-client-sentinel (proc msg)
|
7
|
653 (cond ((eq (process-status proc) 'exit)
|
|
654 (message "Client subprocess exited"))
|
|
655 ((eq (process-status proc) 'signal)
|
|
656 (message "Client subprocess killed"))))
|
0
|
657
|
|
658 (defun gen-seqno ()
|
7
|
659 "generate editor local sequence number."
|
|
660 (setq redit-client-seqno (+ redit-client-seqno 1)))
|
0
|
661
|
|
662 (defun rep-get-command-from-pkt (pkt)
|
13
|
663 ;;(string-to-number (substring pkt 0 10)))
|
|
664 (unpack-int pkt 3 4))
|
2
|
665 (defun rep-get-session-id-from-pkt (pkt)
|
13
|
666 ;;(string-to-number (substring pkt 10 20)))
|
|
667 (unpack-int pkt 7 8))
|
2
|
668 (defun rep-get-editor-id-from-pkt (pkt)
|
13
|
669 ;;(string-to-number (substring pkt 20 30)))
|
|
670 (unpack-int pkt 11 12))
|
0
|
671 (defun rep-get-sequence-id-from-pkt (pkt)
|
13
|
672 ;;(string-to-number (substring pkt 30 40)))
|
|
673 (unpack-int pkt 15 16))
|
0
|
674 (defun rep-get-line-number-from-pkt (pkt)
|
13
|
675 ;;(string-to-number (substring pkt 40 50)))
|
|
676 (unpack-int pkt 19 20))
|
0
|
677 (defun rep-get-text-size-from-pkt (pkt)
|
13
|
678 ;;(string-to-number (substring pkt 50 60)))
|
|
679 (unpack-int pkt 23 24))
|
0
|
680 (defun rep-get-text-from-pkt (pkt)
|
6
|
681 (let ((size (rep-get-text-size-from-pkt pkt)))
|
13
|
682 (substring (decode-coding-string pkt 'euc-jp) 27 (+ 27 size))))
|
6
|
683
|
|
684 ;; enqueue item in queue
|
13
|
685 ;; (defun enqueue (queue item)
|
|
686 ;; (let ((new-cell (list item)))
|
|
687 ;; (if (Queue-front queue)
|
|
688 ;; ;; 最終セルを書き換える
|
|
689 ;; (setf (cdr (Queue-rear queue)) new-cell)
|
|
690 ;; ;; キューは空の状態
|
|
691 ;; (setf (Queue-front queue) new-cell))
|
|
692 ;; (setf (Queue-rear queue) new-cell)))
|
5
|
693
|
6
|
694 ;; deque last queue
|
13
|
695 ;; (defun dequeue (queue)
|
|
696 ;; (if (Queue-front queue)
|
|
697 ;; (prog1
|
|
698 ;; (pop (Queue-front queue))
|
|
699 ;; (unless (Queue-front queue)
|
|
700 ;; ;; キューは空になった
|
|
701 ;; (setf (Queue-rear queue) nil)))))
|
5
|
702
|
6
|
703 ;;
|
|
704 ;; USER
|
|
705 ;; | i | r | d
|
|
706 ;; ---|--------------------
|
|
707 ;; T i | 0\+1 | 0\+1 | 0\+1
|
|
708 ;; O ---|--------------------
|
|
709 ;; K r | +1\0 | 0\X | i\X
|
|
710 ;; E ---|--------------------
|
|
711 ;; N d | +1\0 | X\i | X\X
|
|
712 ;;
|
5
|
713 (defun dequeue-all (queue)
|
|
714 "clean queue"
|
|
715 (while (Queue-front queue)
|
|
716 (dequeue queue)))
|
|
717
|
|
718 (defun redit-line-translate-out (cque rque)
|
|
719 "redit line translate for output"
|
|
720 (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0))
|
6
|
721 (setq xcc 0)
|
|
722 (setq xrc 0)
|
|
723 (setq cignore 0)
|
|
724 (setq rignore 0)
|
|
725 (while cque
|
|
726 (setq cc (car cque))
|
|
727 (while rque
|
|
728 (setq rc (car rque))
|
|
729 ;; -------- translation ------------
|
5
|
730
|
8
|
731 (if (< (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc))
|
|
732 (if (= (redit-get-command-from-queue cc) (string-to-number redit-write-command)) (setq xrc (- xrc 1)))
|
|
733 (if (= (redit-get-command-from-queue cc) (string-to-number redit-delete-line-command)) (setq xrc (- xrc 1))))
|
5
|
734
|
8
|
735 (if (> (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc))
|
|
736 (if (= (redit-get-command-from-queue rc) (string-to-number redit-write-command)) (setq xcc (+ xcc 1)))
|
|
737 (if (= (redit-get-command-from-queue rc) (string-to-number redit-delete-line-command)) (setq xcc (- xcc 1))))
|
5
|
738
|
8
|
739 (if (= (+ (redit-get-line-from-queue cc) xcc) (+ (redit-get-line-from-queue rc) xrc))
|
|
740 (if (= (redit-get-command-from-queue rc) (string-to-number redit-write-command)) (setq xcc (+ xcc 1)))
|
|
741 (if (= (redit-get-command-from-queue rc) (string-to-number redit-replace-command))
|
|
742 (if (= (redit-get-command-from-queue cc) (string-to-number redit-write-command)) (setq xrc (+ xrc 1)))
|
|
743 (if (= (redit-get-command-from-queue cc) (string-to-number redit-replace-command)) (setq cignore 1))
|
|
744 (if (= (redit-get-command-from-queue cc) (string-to-number redit-delete-line-command)) (setq crc redit-write-command) (setq cignore 1))))
|
5
|
745
|
8
|
746 (if (= (redit-get-command-from-queue rc) (string-to-number redit-delete-line-command))
|
|
747 (if (= (redit-get-command-from-queue cc) (string-to-number redit-write-command)) (setq xrc (+ (redit-get-line-from-queue rc) 1)))
|
|
748 (if (= (redit-get-command-from-queue cc) (string-to-number redit-replace-command)) (setq cignore 1))
|
|
749 (if (= (redit-get-command-from-queue cc) (string-to-number redit-delete-line-command)) (setq cignore 1) (setq rignore 1)))
|
5
|
750
|
6
|
751 ;; -------- translation ------------
|
5
|
752
|
6
|
753 (setq rque (cdr rque))) ;; while rque
|
5
|
754
|
6
|
755 ;; ignore
|
|
756 (if (= cignore 1)
|
|
757 ;; xxx
|
|
758 (setq cignore 0))
|
|
759 (if (= rignore 1)
|
|
760 ;; xxx
|
|
761 (setq cignore 0))
|
5
|
762
|
6
|
763 ;; -------- add after que ------------
|
8
|
764 (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)))
|
6
|
765 ;; -------- add after que ------------
|
5
|
766
|
6
|
767 (setq cque (cdr cque))) ;; while cque
|
|
768 ) ;; let
|
|
769 ) ;; defun
|
5
|
770
|
|
771 (defun redit-line-translate-in (cque rque)
|
|
772 "redit line translate for input"
|
|
773 (let ((cc) (rc) (xcc) (xrc) (ccc) (crc) (cignore 0) (rignore 0))
|
6
|
774 (setq xcc 0)
|
|
775 (setq xrc 0)
|
5
|
776 (setq cignore 0)
|
|
777 (setq rignore 0)
|
6
|
778 (while rque
|
|
779 (setq rc (car rque))
|
|
780 (setq cignore 0)
|
|
781 (setq rignore 0)
|
|
782 (while cque
|
|
783 (setq cc (car cque))
|
|
784 ;; -------- translation ------------
|
5
|
785
|
6
|
786 (if (and (= cignore 1) (= rignore 1))
|
8
|
787 (if (< (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc))
|
|
788 (if (= (redit-get-command-from-queue rc) (string-to-number redit-write-command)) (setq xcc (+ xcc 1)))
|
|
789 (if (= (redit-get-command-from-queue rc) (string-to-number redit-delete-line-command)) (setq xcc (- xcc 1))))
|
5
|
790
|
8
|
791 (if (> (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc))
|
|
792 (if (= (redit-get-command-from-queue cc) (string-to-number redit-write-command)) (setq xrc (- xrc 1)))
|
|
793 (if (= (redit-get-command-from-queue cc) (string-to-number redit-delete-line-command)) (setq xrc (+ xrc 1))))
|
5
|
794
|
8
|
795 (if (= (+ (redit-get-line-from-queue rc) xrc) (+ (redit-get-line-from-queue cc) xcc))
|
|
796 (if (= (redit-get-command-from-queue cc) (string-to-number redit-write-command)) (setq xcc (+ xcc 1)))
|
|
797 (if (= (redit-get-command-from-queue cc) (string-to-number redit-replace-command))
|
|
798 (if (= (redit-get-command-from-queue rc) (string-to-number redit-write-command)) (setq xcc (+ xcc 1)))
|
|
799 (if (= (redit-get-command-from-queue rc) (string-to-number redit-replace-command)) (setq cignore 1))
|
|
800 (if (= (redit-get-command-from-queue rc) (string-to-number redit-delete-line-command)) (setq crc redit-write-command) (setq cignore 1))))
|
|
801 (if (= (redit-get-command-from-queue cc) (string-to-number redit-delete-line-command))
|
|
802 (if (= (redit-get-command-from-queue rc) (string-to-number redit-write-command)) (setq xcc (+ (redit-get-line-from-queue cc) 1)))
|
|
803 (if (= (redit-get-command-from-queue rc) (string-to-number redit-replace-command)) (setq crc redit-write-command) (setq cignore 1))
|
|
804 (if (= (redit-get-command-from-queue rc) (string-to-number redit-delete-line-command)) (setq cignore 1) (setq rignore 1))))
|
5
|
805
|
6
|
806 ;; -------- translation ------------
|
5
|
807
|
6
|
808 (setq cque (cdr cque))) ;; while rque
|
5
|
809
|
6
|
810 ;; ignore
|
|
811 (if (= cignore 1)
|
|
812 ;; xxx
|
|
813 (setq cignore 0))
|
|
814 (if (= rignore 1)
|
|
815 ;; xxx
|
|
816 (setq rignore 0))
|
5
|
817
|
6
|
818 ;; -------- add after que ------------
|
8
|
819 (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)))
|
6
|
820 ;; -------- add after que ------------
|
5
|
821
|
6
|
822 (setq rque (cdr rque))) ;; while cque
|
|
823 ) ;; let
|
|
824 ) ;; defun
|
5
|
825
|
6
|
826 ;; for debug
|
5
|
827 (defun redit-client-print-command-queue ()
|
|
828 "Print command queue."
|
|
829 (interactive)
|
7
|
830 ;;(message redit-client-command-queue))
|
|
831 (let ((queue redit-client-command-queue))
|
|
832 (while (Queue-front queue)
|
|
833 (message (Queue-front queue))
|
|
834 (setq queue (cdr (Queue-rear queue)))
|
|
835 )
|
|
836 ))
|
5
|
837
|
|
838 (defun redit-client-print-recive-queue ()
|
|
839 "Print command queue."
|
|
840 (interactive)
|
|
841 (print redit-client-receive-queue))
|
|
842
|
|
843 (defun redit-client-print-send-queue ()
|
|
844 "Print command queue."
|
|
845 (interactive)
|
8
|
846 (print redit-client-send-queue))
|
|
847
|
|
848 (defun redit-get-command-from-queue (queue)
|
|
849 (nth 0 (Queue-front queue)))
|
|
850 (defun redit-get-line-from-queue (queue)
|
|
851 (nth 1 (Queue-front queue)))
|
|
852 (defun redit-get-uid-from-queue (queue)
|
|
853 (nth 2 (Queue-front queue)))
|
|
854 (defun redit-get-text-from-queue (queue)
|
15
|
855 (nth 3 (Queue-front queue)))
|