Mercurial > hg > xemacs-beta
comparison lisp/packages/gnuserv.el @ 151:59463afc5666 r20-3b2
Import from CVS: tag r20-3b2
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:37:19 +0200 |
parents | 538048ae2ab8 |
children | 25f70ba0133c |
comparison
equal
deleted
inserted
replaced
150:8ebb1c0f0f6f | 151:59463afc5666 |
---|---|
1 ;;; gnuserv.el --- Lisp interface code between Emacs and gnuserv | 1 ;;; gnuserv.el --- Lisp interface code between Emacs and gnuserv |
2 ;; Copyright (C) 1989-1997 Free Software Foundation, Inc. | 2 ;; Copyright (C) 1989-1997 Free Software Foundation, Inc. |
3 | 3 |
4 ;; Version: 3.1 | 4 ;; Version: 3.2 |
5 ;; Author: Andy Norman (ange@hplb.hpl.hp.com), originally based on server.el | 5 ;; Author: Andy Norman (ange@hplb.hpl.hp.com), originally based on server.el |
6 ;; Hrvoje Niksic <hniksic@srce.hr> | 6 ;; Hrvoje Niksic <hniksic@srce.hr> |
7 ;; Keywords: environment, processes, terminals | 7 ;; Keywords: environment, processes, terminals |
8 | 8 |
9 ;; This file is part of XEmacs. | 9 ;; This file is part of XEmacs. |
75 | 75 |
76 | 76 |
77 ;;; Code: | 77 ;;; Code: |
78 | 78 |
79 (defconst gnuserv-rcs-version | 79 (defconst gnuserv-rcs-version |
80 "$Id: gnuserv.el,v 1.8 1997/05/18 03:40:06 steve Exp $") | 80 "$Id: gnuserv.el,v 1.9 1997/05/23 01:36:30 steve Exp $") |
81 | 81 |
82 (defgroup gnuserv nil | 82 (defgroup gnuserv nil |
83 "The gnuserv suite of programs to talk to Emacs from outside." | 83 "The gnuserv suite of programs to talk to Emacs from outside." |
84 :group 'environment | 84 :group 'environment |
85 :group 'processes | 85 :group 'processes |
152 The hook functions are called after the file has been visited, with the | 152 The hook functions are called after the file has been visited, with the |
153 current buffer set to the visiting buffer." | 153 current buffer set to the visiting buffer." |
154 :type 'hook | 154 :type 'hook |
155 :group 'gnuserv) | 155 :group 'gnuserv) |
156 | 156 |
157 (defcustom gnuserv-init-hook nil | |
158 "*Hook run after the server is started." | |
159 :type 'hook | |
160 :group 'gnuserv) | |
161 | |
162 (defcustom gnuserv-shutdown-hook nil | |
163 "*Hook run before the server exits." | |
164 :type 'hook | |
165 :group 'gnuserv) | |
166 | |
157 (defcustom gnuserv-kill-quietly nil | 167 (defcustom gnuserv-kill-quietly nil |
158 "*Non-nil means to kill buffers with clients attached without requiring confirmation." | 168 "*Non-nil means to kill buffers with clients attached without requiring confirmation." |
159 :type 'boolean | 169 :type 'boolean |
160 :group 'gnuserv) | 170 :group 'gnuserv) |
161 | 171 |
228 | 238 |
229 ;; We want the client-infested buffers to have some modeline | 239 ;; We want the client-infested buffers to have some modeline |
230 ;; identification, so we'll make a "minor mode". | 240 ;; identification, so we'll make a "minor mode". |
231 (defvar gnuserv-minor-mode nil) | 241 (defvar gnuserv-minor-mode nil) |
232 (make-variable-buffer-local 'gnuserv-mode) | 242 (make-variable-buffer-local 'gnuserv-mode) |
233 (pushnew '(gnuserv-minor-mode " Server") minor-mode-alist) | 243 (pushnew '(gnuserv-minor-mode " Server") minor-mode-alist |
244 :test 'equal) | |
234 | 245 |
235 | 246 |
236 ;; Sample gnuserv-frame functions | 247 ;; Sample gnuserv-frame functions |
237 | 248 |
238 (defun gnuserv-main-frame-function (type) | 249 (defun gnuserv-main-frame-function (type) |
261 gnuserv-special-frame) | 272 gnuserv-special-frame) |
262 | 273 |
263 | 274 |
264 ;;; Communication functions | 275 ;;; Communication functions |
265 | 276 |
277 ;; We used to restart the server here, but it's too risky -- if | |
278 ;; something goes awry, it's too easy to wind up in a loop. | |
266 (defun gnuserv-sentinel (proc msg) | 279 (defun gnuserv-sentinel (proc msg) |
267 (case (process-status proc) | 280 (case (process-status proc) |
268 (exit (message "Gnuserv subprocess exited; restarting") | 281 (exit |
269 ;; This will also kill all the existing clients. | 282 (message |
270 (gnuserv-start-1)) | 283 (substitute-command-keys |
271 (closed (message "Gnuserv subprocess closed")) | 284 "Gnuserv subprocess exited; restart with `\\[gnuserv-start]'")) |
272 (signal (message "Gnuserv subprocess killed")))) | 285 (gnuserv-prepare-shutdown)) |
273 | 286 (signal |
287 (message | |
288 (substitute-command-keys | |
289 "Gnuserv subprocess killed; restart with `\\[gnuserv-start]'")) | |
290 (gnuserv-prepare-shutdown)) | |
291 (closed | |
292 (message | |
293 (substitute-command-keys | |
294 "Gnuserv subprocess closed; restart with `\\[gnuserv-start]'")) | |
295 (gnuserv-prepare-shutdown)))) | |
296 | |
297 ;; This function reads client requests from our current server. Every | |
298 ;; client is identified by a unique ID within the server | |
299 ;; (incidentally, the same ID is the file descriptor the server uses | |
300 ;; to communicate to client). | |
301 ;; | |
302 ;; The request string can arrive in several chunks. As the request | |
303 ;; ends with \C-d, we check for that character at the end of string. | |
304 ;; If not found, keep reading, and concatenating to former strings. | |
305 ;; So, if at first read we receive "5 (gn", that text will be stored | |
306 ;; to gnuserv-string. If we then receive "us)\C-d", the two will be | |
307 ;; concatenated, `current-client' will be set to 5, and `(gnus)' form | |
308 ;; will be evaluated. | |
309 ;; | |
310 ;; Server will send the following: | |
311 ;; | |
312 ;; "ID <text>\C-d" (no quotes) | |
313 ;; | |
314 ;; ID - file descriptor of the given client; | |
315 ;; <text> - the actual contents of the request. | |
274 (defun gnuserv-process-filter (proc string) | 316 (defun gnuserv-process-filter (proc string) |
275 "Process gnuserv client requests to execute Emacs commands." | 317 "Process gnuserv client requests to execute Emacs commands." |
276 (setq gnuserv-string (concat gnuserv-string string)) | 318 (setq gnuserv-string (concat gnuserv-string string)) |
277 ;; C-d means end of request. | 319 ;; C-d means end of request. |
278 (when (string-match "\C-d$" gnuserv-string) | 320 (when (string-match "\C-d$" gnuserv-string) |
296 (setq gnuserv-string ""))) | 338 (setq gnuserv-string ""))) |
297 (t | 339 (t |
298 (error "%s: invalid response from gnuserv" gnuserv-string) | 340 (error "%s: invalid response from gnuserv" gnuserv-string) |
299 (setq gnuserv-string ""))))) | 341 (setq gnuserv-string ""))))) |
300 | 342 |
343 ;; This function is somewhat of a misnomer. Actually, we write to the | |
344 ;; server (using `process-send-string' to gnuserv-process), which | |
345 ;; interprets what we say and forwards it to the client. The | |
346 ;; incantation server understands is (from gnuserv.c): | |
347 ;; | |
348 ;; "FD/LEN:<text>\n" (no quotes) | |
349 ;; FD - file descriptor of the given client (which we obtained from | |
350 ;; the server earlier); | |
351 ;; LEN - length of the stuff we are about to send; | |
352 ;; <text> - the actual contents of the request. | |
301 (defun gnuserv-write-to-client (client-id form) | 353 (defun gnuserv-write-to-client (client-id form) |
302 "Write the given form to the given client via the gnuserv process." | 354 "Write the given form to the given client via the gnuserv process." |
303 (when (eq (process-status gnuserv-process) 'run) | 355 (when (eq (process-status gnuserv-process) 'run) |
304 (let* ((result (format "%s" form)) | 356 (let* ((result (format "%s" form)) |
305 (s (format "%s/%d:%s\n" client-id | 357 (s (format "%s/%d:%s\n" client-id |
306 (length result) result))) | 358 (length result) result))) |
307 (process-send-string gnuserv-process s)))) | 359 (process-send-string gnuserv-process s)))) |
308 | 360 |
309 | |
310 ;; The following two functions are helper functions, used by | 361 ;; The following two functions are helper functions, used by |
311 ;; gnuclient. | 362 ;; gnuclient. |
312 | 363 |
313 (defun gnuserv-eval (form) | 364 (defun gnuserv-eval (form) |
314 "Evaluate form and return result to client." | 365 "Evaluate form and return result to client." |
323 (eval form)) | 374 (eval form)) |
324 | 375 |
325 | 376 |
326 ;; "Execute" a client connection, called by gnuclient. This is the | 377 ;; "Execute" a client connection, called by gnuclient. This is the |
327 ;; backbone of gnuserv.el. | 378 ;; backbone of gnuserv.el. |
328 (defun gnuserv-edit-files (type list &optional flags) | 379 (defun gnuserv-edit-files (type list &rest flags) |
329 "For each (line-number . file) pair in LIST, edit the file at line-number. | 380 "For each (line-number . file) pair in LIST, edit the file at line-number. |
330 The visited buffers are memorized, so that when \\[gnuserv-edit] is invoked | 381 The visited buffers are memorized, so that when \\[gnuserv-edit] is invoked |
331 in such a buffer, or when it is killed, or the client's device deleted, the | 382 in such a buffer, or when it is killed, or the client's device deleted, the |
332 client will be invoked that the edit is finished. | 383 client will be invoked that the edit is finished. |
333 | 384 |
334 TYPE should either be a (tty TTY TERM PID) list, or (x DISPLAY) list. | 385 TYPE should either be a (tty TTY TERM PID) list, or (x DISPLAY) list. |
335 If FLAGS is `quick', just edit the files in Emacs. | 386 If a flag is `quick', just edit the files in Emacs. |
336 If FLAGS is `view', view the files read-only." | 387 If a flag is `view', view the files read-only." |
337 (or (not flags) | 388 (let (quick view) |
338 (memq flags '(quick view)) | 389 (mapc (lambda (flag) |
339 (error "Invalid flag %s" flags)) | 390 (case flag |
340 (let* ((old-device-num (length (device-list))) | 391 (quick (setq quick t)) |
341 (new-frame nil) | 392 (view (setq view t)) |
342 (dest-frame (if (functionp gnuserv-frame) | 393 (t (error "Invalid flag %s" flag)))) |
343 (funcall gnuserv-frame (car type)) | 394 flags) |
344 gnuserv-frame)) | 395 (let* ((old-device-num (length (device-list))) |
345 ;; The gnuserv-frame dependencies are ugly. | 396 (new-frame nil) |
346 (device (cond ((frame-live-p dest-frame) | 397 (dest-frame (if (functionp gnuserv-frame) |
347 (frame-device dest-frame)) | 398 (funcall gnuserv-frame (car type)) |
348 ((null dest-frame) | 399 gnuserv-frame)) |
349 (case (car type) | 400 ;; The gnuserv-frame dependencies are ugly. |
350 (tty (apply 'make-tty-device (cdr type))) | 401 (device (cond ((frame-live-p dest-frame) |
351 (x (make-x-device (cadr type))) | 402 (frame-device dest-frame)) |
352 (t (error "Invalid device type")))) | 403 ((null dest-frame) |
353 (t | 404 (case (car type) |
354 (selected-device)))) | 405 (tty (apply 'make-tty-device (cdr type))) |
355 (frame (cond ((frame-live-p dest-frame) | 406 (x (make-x-device (cadr type))) |
356 dest-frame) | 407 (t (error "Invalid device type")))) |
357 ((null dest-frame) | 408 (t |
358 (setq new-frame (make-frame nil device)) | 409 (selected-device)))) |
359 new-frame) | 410 (frame (cond ((frame-live-p dest-frame) |
360 (t (selected-frame)))) | 411 dest-frame) |
361 (client (make-gnuclient :id gnuserv-current-client | 412 ((null dest-frame) |
362 :device device | 413 (setq new-frame (make-frame nil device)) |
363 :frame new-frame))) | 414 new-frame) |
364 (setq gnuserv-current-client nil) | 415 (t (selected-frame)))) |
365 ;; If the device was created by this client, push it to the list. | 416 (client (make-gnuclient :id gnuserv-current-client |
366 (and (/= old-device-num (length (device-list))) | 417 :device device |
367 (push device gnuserv-devices)) | 418 :frame new-frame))) |
368 ;; Visit all the listed files. | 419 (setq gnuserv-current-client nil) |
369 (while list | 420 ;; If the device was created by this client, push it to the list. |
370 (let ((line (caar list)) (path (cdar list))) | 421 (and (/= old-device-num (length (device-list))) |
371 (select-frame frame) | 422 (push device gnuserv-devices)) |
372 ;; Visit the file. | 423 (and (frame-iconified-p frame) |
373 (funcall (if (eq flags 'view) | 424 (deiconify-frame frame)) |
374 gnuserv-view-file-function | 425 ;; Visit all the listed files. |
375 gnuserv-find-file-function) | 426 (while list |
376 path) | 427 (let ((line (caar list)) (path (cdar list))) |
377 (goto-line line) | 428 (select-frame frame) |
378 (run-hooks 'gnuserv-visit-hook) | 429 ;; Visit the file. |
379 ;; Don't memorize the quick and view buffers. | 430 (funcall (if view |
380 (when (null flags) | 431 gnuserv-view-file-function |
381 (pushnew (current-buffer) (gnuclient-buffers client)) | 432 gnuserv-find-file-function) |
382 (setq gnuserv-minor-mode t)) | 433 path) |
383 (pop list))) | 434 (goto-line line) |
384 (cond ((and flags (device-on-window-system-p device)) | 435 (run-hooks 'gnuserv-visit-hook) |
385 ;; Exit if on X device, and quick or view. | 436 ;; Don't memorize the quick and view buffers. |
386 ;; NOTE: if the client is to finish now, it must absolutely | 437 (unless (or quick view) |
387 ;; /not/ be included to the list of clients. This way the | 438 (pushnew (current-buffer) (gnuclient-buffers client)) |
388 ;; client-ids should be unique. | 439 (setq gnuserv-minor-mode t)) |
389 (gnuserv-write-to-client (gnuclient-id client) nil)) | 440 (pop list))) |
390 (t | 441 (cond |
391 ;; Else, the client gets a vote. | 442 ((and (or quick view) |
392 (push client gnuserv-clients) | 443 (device-on-window-system-p device)) |
393 ;; Explain buffer exit options. If dest-frame is nil, the | 444 ;; Exit if on X device, and quick or view. NOTE: if the |
394 ;; user can exit via `delete-frame'. OTOH, if FLAGS are | 445 ;; client is to finish now, it must absolutely /not/ be |
395 ;; nil and there are some buffers, the user can exit via | 446 ;; included to the list of clients. This way the client-ids |
396 ;; `gnuserv-edit'. | 447 ;; should be unique. |
397 (if (and (null flags) | 448 (gnuserv-write-to-client (gnuclient-id client) nil)) |
398 (gnuclient-buffers client)) | 449 (t |
399 (message (substitute-command-keys | 450 ;; Else, the client gets a vote. |
400 "Type `\\[gnuserv-edit]' to finish editing")) | 451 (push client gnuserv-clients) |
401 (or dest-frame | 452 ;; Explain buffer exit options. If dest-frame is nil, the |
402 (message (substitute-command-keys | 453 ;; user can exit via `delete-frame'. OTOH, if FLAGS are nil |
403 "Type `\\[delete-frame]' to finish editing")))))))) | 454 ;; and there are some buffers, the user can exit via |
455 ;; `gnuserv-edit'. | |
456 (if (and (not (or quick view)) | |
457 (gnuclient-buffers client)) | |
458 (message (substitute-command-keys | |
459 "Type `\\[gnuserv-edit]' to finish editing")) | |
460 (or dest-frame | |
461 (message (substitute-command-keys | |
462 "Type `\\[delete-frame]' to finish editing"))))))))) | |
404 | 463 |
405 | 464 |
406 ;;; Functions that hook into Emacs in various way to enable operation | 465 ;;; Functions that hook into Emacs in various way to enable operation |
407 | 466 |
408 ;; Defined later. | 467 ;; Defined later. |
409 (add-hook 'kill-emacs-hook 'gnuserv-kill-all-clients t) | 468 (add-hook 'kill-emacs-hook 'gnuserv-kill-all-clients t) |
410 | 469 |
411 ;; A helper function; used by others. | 470 ;; A helper function; used by others. Try avoiding it whenever |
471 ;; possible, because it is slow, and conses a list. Use | |
472 ;; `gnuserv-buffer-p' when appropriate, for instance. | |
412 (defun gnuserv-buffer-clients (buffer) | 473 (defun gnuserv-buffer-clients (buffer) |
413 "Returns a list of clients to which BUFFER belongs." | 474 "Returns a list of clients to which BUFFER belongs." |
414 (let ((client gnuserv-clients) | 475 (let ((client gnuserv-clients) |
415 res) | 476 res) |
416 (while client | 477 (while client |
417 (if (memq buffer (gnuclient-buffers (car client))) | 478 (if (memq buffer (gnuclient-buffers (car client))) |
418 (push (car client) res)) | 479 (push (car client) res)) |
419 (pop client)) | 480 (pop client)) |
420 res)) | 481 res)) |
482 | |
483 ;; Like `gnuserv-buffer-clients', but returns a boolean; doesn't | |
484 ;; collect a list. | |
485 (defun gnuserv-buffer-p (buffer) | |
486 (member* buffer gnuserv-clients | |
487 :test 'memq | |
488 :key 'gnuclient-buffers)) | |
421 | 489 |
422 ;; This function makes sure that a killed buffer is deleted off the | 490 ;; This function makes sure that a killed buffer is deleted off the |
423 ;; list for the particular client. | 491 ;; list for the particular client. |
424 ;; | 492 ;; |
425 ;; This hooks into `kill-buffer-hook'. It is *not* a replacement for | 493 ;; This hooks into `kill-buffer-hook'. It is *not* a replacement for |
441 | 509 |
442 ;; Ask for confirmation before killing a buffer that belongs to a | 510 ;; Ask for confirmation before killing a buffer that belongs to a |
443 ;; living client. | 511 ;; living client. |
444 (defun gnuserv-kill-buffer-query-function () | 512 (defun gnuserv-kill-buffer-query-function () |
445 (or gnuserv-kill-quietly | 513 (or gnuserv-kill-quietly |
446 (not (gnuserv-buffer-clients (current-buffer))) | 514 (not (gnuserv-buffer-p (current-buffer))) |
447 (yes-or-no-p | 515 (yes-or-no-p |
448 (format "Buffer %s belongs to gnuserv client(s); kill anyway? " | 516 (format "Buffer %s belongs to gnuserv client(s); kill anyway? " |
449 (current-buffer))))) | 517 (current-buffer))))) |
450 | 518 |
451 (add-hook 'kill-buffer-query-functions | 519 (add-hook 'kill-buffer-query-functions |
536 | 604 |
537 | 605 |
538 ;;; Higher-level functions | 606 ;;; Higher-level functions |
539 | 607 |
540 ;; Choose a `next' server buffer, according to several criteria, and | 608 ;; Choose a `next' server buffer, according to several criteria, and |
541 ;; return it. If none appropriate are found, return nil. | 609 ;; return it. If none are found, return nil. |
542 (defun gnuserv-next-buffer () | 610 (defun gnuserv-next-buffer () |
543 (let* ((frame (selected-frame)) | 611 (let* ((frame (selected-frame)) |
544 (device (selected-device)) | 612 (device (selected-device)) |
545 client) | 613 client) |
546 (cond | 614 (cond |
553 ((and | 621 ((and |
554 (memq (selected-device) gnuserv-devices) | 622 (memq (selected-device) gnuserv-devices) |
555 (setq client | 623 (setq client |
556 (car (member* device gnuserv-clients :key 'gnuclient-device)))) | 624 (car (member* device gnuserv-clients :key 'gnuclient-device)))) |
557 (car (gnuclient-buffers client))) | 625 (car (gnuclient-buffers client))) |
558 ;; Else, try to find just any client, and return its first buffer. | 626 ;; Else, try to find any client with at least one buffer, and |
559 (gnuserv-clients | 627 ;; return its first buffer. |
560 (car (gnuclient-buffers (car gnuserv-clients)))) | 628 ((setq client |
561 ;; Oh, give up. | 629 (car (member-if-not 'null gnuserv-clients |
630 :key 'gnuserv-buffers))) | |
631 (car (gnuclient-buffers client))) | |
632 ;; Oh, give up. | |
562 (t nil)))) | 633 (t nil)))) |
563 | 634 |
564 (defun gnuserv-buffer-done (buffer) | 635 (defun gnuserv-buffer-done (buffer) |
565 "Mark BUFFER as \"done\" for its client(s). | 636 "Mark BUFFER as \"done\" for its client(s). |
566 Calls `gnuserv-done-function' and returns another gnuserv buffer as a | 637 Does the save/backup queries first, and calls `gnuserv-done-function'." |
567 suggestion for the new current buffer." | |
568 ;; Check whether this is the real thing. | 638 ;; Check whether this is the real thing. |
569 (unless (gnuserv-buffer-clients buffer) | 639 (unless (gnuserv-buffer-p buffer) |
570 (error "%s does not belong to a gnuserv client" buffer)) | 640 (error "%s does not belong to a gnuserv client" buffer)) |
571 ;; Backup/ask query. | 641 ;; Backup/ask query. |
572 (if (gnuserv-temp-file-p buffer) | 642 (if (gnuserv-temp-file-p buffer) |
573 ;; For a temp file, save, and do NOT make a non-numeric backup | 643 ;; For a temp file, save, and do NOT make a non-numeric backup |
574 ;; Why does server.el explicitly back up temporary files? | 644 ;; Why does server.el explicitly back up temporary files? |
576 (buffer-backed-up (not gnuserv-make-temp-file-backup))) | 646 (buffer-backed-up (not gnuserv-make-temp-file-backup))) |
577 (save-buffer)) | 647 (save-buffer)) |
578 (if (and (buffer-modified-p) | 648 (if (and (buffer-modified-p) |
579 (y-or-n-p (concat "Save file " buffer-file-name "? "))) | 649 (y-or-n-p (concat "Save file " buffer-file-name "? "))) |
580 (save-buffer buffer))) | 650 (save-buffer buffer))) |
581 (gnuserv-buffer-done-1 buffer) | 651 (gnuserv-buffer-done-1 buffer)) |
582 (gnuserv-next-buffer)) | |
583 | 652 |
584 ;; Called by `gnuserv-start-1' to clean everything. Hooked into | 653 ;; Called by `gnuserv-start-1' to clean everything. Hooked into |
585 ;; `kill-emacs-hook', too. | 654 ;; `kill-emacs-hook', too. |
586 (defun gnuserv-kill-all-clients () | 655 (defun gnuserv-kill-all-clients () |
587 "Kill all the gnuserv clients. Ruthlessly." | 656 "Kill all the gnuserv clients. Ruthlessly." |
588 (mapc 'gnuserv-kill-client gnuserv-clients)) | 657 (mapc 'gnuserv-kill-client gnuserv-clients)) |
589 | 658 |
590 ;; Actually start the process. Kills all the clients before-hand. | 659 ;; This serves to run the hook and reset |
591 (defun gnuserv-start-1 (&optional leave-dead) | 660 ;; `allow-deletion-of-last-visible-frame'. |
661 (defun gnuserv-prepare-shutdown () | |
662 (setq allow-deletion-of-last-visible-frame nil) | |
663 (run-hooks 'gnuserv-shutdown-hook)) | |
664 | |
665 ;; This is a user-callable function, too. | |
666 (defun gnuserv-shutdown () | |
667 "Shutdown the gnuserv server, if one is currently running. | |
668 All the clients will be disposed of via the normal methods." | |
669 (interactive) | |
592 (gnuserv-kill-all-clients) | 670 (gnuserv-kill-all-clients) |
593 (when gnuserv-process | 671 (when gnuserv-process |
594 (set-process-sentinel gnuserv-process nil) | 672 (set-process-sentinel gnuserv-process nil) |
673 (gnuserv-prepare-shutdown) | |
595 (condition-case () | 674 (condition-case () |
596 (delete-process gnuserv-process) | 675 (delete-process gnuserv-process) |
597 (error nil))) | 676 (error nil)) |
677 (setq gnuserv-process nil) | |
678 (message "Killed server"))) | |
679 | |
680 ;; Actually start the process. Kills all the clients before-hand. | |
681 (defun gnuserv-start-1 (&optional leave-dead) | |
682 ;; Shutdown the existing server, if any. | |
683 (gnuserv-shutdown) | |
598 ;; If we already had a server, clear out associated status. | 684 ;; If we already had a server, clear out associated status. |
599 (unless leave-dead | 685 (unless leave-dead |
600 (setq gnuserv-string "") | 686 (setq gnuserv-string "" |
601 (setq gnuserv-current-client nil) | 687 gnuserv-current-client nil) |
602 (let ((process-connection-type t)) | 688 (let ((process-connection-type t)) |
603 (setq gnuserv-process | 689 (setq gnuserv-process |
604 (start-process "gnuserv" nil gnuserv-program))) | 690 (start-process "gnuserv" nil gnuserv-program))) |
605 (set-process-sentinel gnuserv-process 'gnuserv-sentinel) | 691 (set-process-sentinel gnuserv-process 'gnuserv-sentinel) |
606 (set-process-filter gnuserv-process 'gnuserv-process-filter) | 692 (set-process-filter gnuserv-process 'gnuserv-process-filter) |
607 (process-kill-without-query gnuserv-process))) | 693 (process-kill-without-query gnuserv-process) |
694 (setq allow-deletion-of-last-visible-frame t) | |
695 (run-hooks 'gnuserv-init-hook))) | |
608 | 696 |
609 | 697 |
610 ;;; User-callable functions: | 698 ;;; User-callable functions: |
699 | |
700 ;;;###autoload | |
701 (defun gnuserv-running-p () | |
702 "Return non-nil if a gnuserv process is running from this XEmacs session." | |
703 (not (not gnuserv-process))) | |
611 | 704 |
612 ;;;###autoload | 705 ;;;###autoload |
613 (defun gnuserv-start (&optional leave-dead) | 706 (defun gnuserv-start (&optional leave-dead) |
614 "Allow this Emacs process to be a server for client processes. | 707 "Allow this Emacs process to be a server for client processes. |
615 This starts a gnuserv communications subprocess through which | 708 This starts a gnuserv communications subprocess through which |
616 client \"editors\" (gnuclient and gnudoit) can send editing commands to | 709 client \"editors\" (gnuclient and gnudoit) can send editing commands to |
617 this Emacs job. See the gnuserv(1) manual page for more details. | 710 this Emacs job. See the gnuserv(1) manual page for more details. |
618 | 711 |
619 Prefix arg means just kill any existing server communications subprocess." | 712 Prefix arg means just kill any existing server communications subprocess." |
620 (interactive "P") | 713 (interactive "P") |
621 ;; kill it dead! | |
622 (and gnuserv-process | 714 (and gnuserv-process |
623 (not leave-dead) | 715 (not leave-dead) |
624 (message "Restarting gnuserv")) | 716 (message "Restarting gnuserv")) |
625 (gnuserv-start-1 leave-dead)) | 717 (gnuserv-start-1 leave-dead)) |
626 | 718 |
627 ;;;###autoload | 719 (defun gnuserv-edit (&optional count) |
628 (defun gnuserv-edit (&optional arg) | |
629 "Mark the current gnuserv editing buffer as \"done\", and switch to next one. | 720 "Mark the current gnuserv editing buffer as \"done\", and switch to next one. |
630 | 721 |
631 The `gnuserv-done-function' is used to dispose of the buffer after marking it | 722 Run with a numeric prefix argument, repeat the operation that number |
632 as done; it is `kill-buffer' by default. | 723 of times. If given a universal prefix argument, close all the buffers |
724 of this buffer's clients. | |
725 | |
726 The `gnuserv-done-function' (bound to `kill-buffer' by default) is | |
727 called to dispose of the buffer after marking it as done. | |
633 | 728 |
634 Files that match `gnuserv-temp-file-regexp' are considered temporary and | 729 Files that match `gnuserv-temp-file-regexp' are considered temporary and |
635 are saved unconditionally and backed up if `gnuserv-make-temp-file-backup' | 730 are saved unconditionally and backed up if `gnuserv-make-temp-file-backup' |
636 is non-nil. They are disposed of using `gnuserv-done-temp-file-function'. | 731 is non-nil. They are disposed of using `gnuserv-done-temp-file-function' |
637 | 732 (also bound to `kill-buffer' by default). |
638 When all of a client's buffers are marked as \"done\", the client is notified. | 733 |
639 | 734 When all of a client's buffers are marked as \"done\", the client is notified." |
640 If invoked with a prefix argument, or if there is no gnuserv process | |
641 running, only starts server process. Invoked with \\[gnuserv-edit]." | |
642 (interactive "P") | 735 (interactive "P") |
643 (if (or arg (not gnuserv-process) | 736 (when (null count) |
644 (memq (process-status gnuserv-process) '(signal exit))) | 737 (setq count 1)) |
645 (gnuserv-start) | 738 (cond ((numberp count) |
646 (switch-to-buffer (or (gnuserv-buffer-done (current-buffer)) | 739 (let (next) |
647 (current-buffer))))) | 740 (while (natnump (decf count)) |
648 | 741 (gnuserv-buffer-done (current-buffer)) |
649 ;;;###autoload | 742 (setq next (gnuserv-next-buffer)) |
743 (when next | |
744 (switch-to-buffer next))))) | |
745 (count | |
746 (let* ((buf (current-buffer)) | |
747 (clients (gnuserv-buffer-clients buf))) | |
748 (unless clients | |
749 (error "%s does not belong to a gnuserv client" buf)) | |
750 (mapc 'gnuserv-kill-client (gnuserv-buffer-clients buf)))))) | |
751 | |
650 (global-set-key "\C-x#" 'gnuserv-edit) | 752 (global-set-key "\C-x#" 'gnuserv-edit) |
651 | 753 |
652 (provide 'gnuserv) | 754 (provide 'gnuserv) |
653 | 755 |
654 ;;; gnuserv.el ends here | 756 ;;; gnuserv.el ends here |