comparison lisp/packages/gnuserv.el @ 36:c53a95d3c46d r19-15b101

Import from CVS: tag r19-15b101
author cvs
date Mon, 13 Aug 2007 08:53:38 +0200
parents ec9a17fef872
children 56c54cf7c5b6
comparison
equal deleted inserted replaced
35:279432d5c479 36:c53a95d3c46d
3 ; This file is part of GNU Emacs. 3 ; This file is part of GNU Emacs.
4 ; 4 ;
5 ; Copying is permitted under those conditions described by the GNU 5 ; Copying is permitted under those conditions described by the GNU
6 ; General Public License. 6 ; General Public License.
7 ; 7 ;
8 ; Copyright (C) 1989-1994 Free Software Foundation, Inc. 8 ; Copyright (C) 1989-1996 Free Software Foundation, Inc.
9 ; 9 ;
10 ; Author: Andy Norman (ange@hplb.hpl.hp.com) based on 10 ; Author: Andy Norman (ange@hplb.hpl.hp.com) based on
11 ; 'lisp/server.el' from the 18.52 GNU Emacs distribution. 11 ; 'lisp/server.el' from the 18.52 GNU Emacs distribution.
12 ; 12 ;
13 ; Please mail bugs and suggestions to the author at the above address. 13 ; Please mail bugs and suggestions to the author at the above address.
51 ; Ben Wing <wing@666.com> sometime in 1995 51 ; Ben Wing <wing@666.com> sometime in 1995
52 ; Updated to allow `gnuattach'-type connections to the existing TTY 52 ; Updated to allow `gnuattach'-type connections to the existing TTY
53 ; 53 ;
54 ; Ben Wing <wing@666.com> May/1996 54 ; Ben Wing <wing@666.com> May/1996
55 ; patch to get TTY terminal type correct. 55 ; patch to get TTY terminal type correct.
56 ;
57 ; Jan Vroonhof <vroonhof@math.ethz.ch> July/1996
58 ; ported the server-temp-file-regexp feature from server.el
59 ; ported server hooks from server.el
60 ; ported kill-*-query functions from server.el (and made it optional)
61 ; synced other behaviour with server.el
56 62
57 63
58 64
59 (defconst gnuserv-rcs-header-id "!Header: gnuserv.el,v 2.1 95/02/16 12:00:16 arup alpha !") 65 (defconst gnuserv-rcs-header-id "!Header: gnuserv.el,v 2.1 95/02/16 12:00:16 arup alpha !")
60 66
72 If nil, then a new frame is created for each file edited. 78 If nil, then a new frame is created for each file edited.
73 This variable has no effect in XEmacs versions older than 19.9.") 79 This variable has no effect in XEmacs versions older than 19.9.")
74 80
75 (defvar server-done-function 'kill-buffer 81 (defvar server-done-function 'kill-buffer
76 "*A function of one argument, a buffer, which removes the buffer after editing. 82 "*A function of one argument, a buffer, which removes the buffer after editing.
77 Functions such as 'kill-buffer' and 'bury-buffer' are good values.") 83 Functions such as 'kill-buffer' and 'bury-buffer' are good values. See also
84 `server-done-temp-file-function'")
85
86 (defvar server-done-temp-file-function 'kill-buffer
87 "*A function of one argument, a buffer, which removes the buffer after editing a
88 temporary file. Functions such as 'kill-buffer' and 'bury-buffer' are
89 good values. See also `server-done-function'")
78 90
79 (defvar server-program "gnuserv" 91 (defvar server-program "gnuserv"
80 "*The program to use as the edit server") 92 "*The program to use as the edit server")
93
94
95 (defvar server-visit-hook nil
96 "*List of hooks to call when visiting a file for the Emacs server.")
97
98 ;; defined by server.el but obsolete?
99 ;; (defvar server-switch-hook nil
100 ;; "*List of hooks to call when switching to a buffer for the Emacs server.")
101
102 (defvar server-done-hook nil
103 "*List of hooks to call when done editing a buffer for the Emacs server.")
104
81 105
82 (defvar server-process nil 106 (defvar server-process nil
83 "The current server process") 107 "The current server process")
84 108
85 (defvar server-string "" 109 (defvar server-string ""
95 "List of current server clients. 119 "List of current server clients.
96 Each element is (CLIENTID BUFFER...) where CLIENTID is an integer 120 Each element is (CLIENTID BUFFER...) where CLIENTID is an integer
97 that can be given to the server process to identify a client. 121 that can be given to the server process to identify a client.
98 When a buffer is killed, it is removed from this list.") 122 When a buffer is killed, it is removed from this list.")
99 123
124 (defvar server-kill-quietly nil
125 "If this variable is set then don't confirm kills of buffers with
126 clients attached")
127
128
100 (defvar server-buffer-clients nil 129 (defvar server-buffer-clients nil
101 "List of client ids for clients requesting editing of the current buffer.") 130 "List of client ids for clients requesting editing of the current buffer.")
131
132 (defvar server-temp-file-regexp "^/tmp/Re\\|/draft$"
133 "*Regexp which should match filenames of temporary files
134 which are deleted and reused after each edit
135 by the programs that invoke the emacs server.")
136
137 (defvar server-make-temp-file-backup nil
138 "Non-nil makes the server backup temporary files also")
102 139
103 (make-variable-buffer-local 'server-buffer-clients) 140 (make-variable-buffer-local 'server-buffer-clients)
104 (setq-default server-buffer-clients nil) 141 (setq-default server-buffer-clients nil)
105 (or (assq 'server-buffer-clients minor-mode-alist) 142 (or (assq 'server-buffer-clients minor-mode-alist)
106 (setq minor-mode-alist (cons '(server-buffer-clients " Server") 143 (setq minor-mode-alist (cons '(server-buffer-clients " Server")
107 minor-mode-alist))) 144 minor-mode-alist)))
145
146 (defun server-temp-file-p (buffer)
147 "Return non-nil if BUFFER contains a file considered temporary.
148 These are files whose names suggest they are repeatedly
149 reused to pass information to another program.
150
151 The variable `server-temp-file-regexp' controls which filenames
152 are considered temporary."
153 (and (buffer-file-name buffer)
154 (string-match server-temp-file-regexp (buffer-file-name buffer))))
155
108 156
109 (defun server-log (string) 157 (defun server-log (string)
110 "If a *server* buffer exists, write STRING to it for logging purposes." 158 "If a *server* buffer exists, write STRING to it for logging purposes."
111 (if (get-buffer "*server*") 159 (if (get-buffer "*server*")
112 (save-excursion 160 (save-excursion
198 (process-kill-without-query server-process))) 246 (process-kill-without-query server-process)))
199 247
200 ;; make gnuserv-start an alias to server-start, for backward compatibility 248 ;; make gnuserv-start an alias to server-start, for backward compatibility
201 (fset 'server-start (function gnuserv-start)) 249 (fset 'server-start (function gnuserv-start))
202 250
203 251 ; Can gnuserv handle commands in close succesion? (See server.el line 283) JV
204 (defun server-write-to-client (client form) 252 (defun server-write-to-client (client form)
205 "Write the given form to the given client via the server process." 253 "Write the given form to the given client via the server process."
206 (if (and client 254 (if (and client
207 (eq (process-status server-process) 'run)) 255 (eq (process-status server-process) 'run))
208 (let* ((result (format "%s" form)) 256 (let* ((result (format "%s" form))
247 (defun server-tty-find-file (tty termtype pid file) 295 (defun server-tty-find-file (tty termtype pid file)
248 (let ((device (make-tty-device tty termtype pid ))) 296 (let ((device (make-tty-device tty termtype pid )))
249 (select-frame (make-frame nil device)) 297 (select-frame (make-frame nil device))
250 (if (not file) 298 (if (not file)
251 (switch-to-buffer (get-buffer-create "*scratch*")) 299 (switch-to-buffer (get-buffer-create "*scratch*"))
252 (find-file file)))) 300 (find-file file)))
301 (run-hooks 'server-visit-hook))
253 302
254 (defun server-find-file (file) 303 (defun server-find-file (file)
255 "Edit file FILENAME. 304 "Edit file FILENAME.
256 Switch to a buffer visiting file FILENAME, 305 Switch to a buffer visiting file FILENAME,
257 creating one if none already exists." 306 creating one if none already exists."
302 (if (screenp gnuserv-frame) 351 (if (screenp gnuserv-frame)
303 (progn (select-screen gnuserv-frame) 352 (progn (select-screen gnuserv-frame)
304 (find-file file)) 353 (find-file file))
305 (select-screen (create-screen (find-file-noselect file))))) 354 (select-screen (create-screen (find-file-noselect file)))))
306 355
307 (t (find-file file))))) ;; emacs18+ 356 (t (find-file file)))) ;; emacs18+
357 (run-hooks 'server-visit-hook))
308 358
309 359
310 (defun server-edit-files-quickly (list) 360 (defun server-edit-files-quickly (list)
311 "For each (line-number . file) pair in LIST, edit the file at line-number. 361 "For each (line-number . file) pair in LIST, edit the file at line-number.
312 Unlike (server-edit-files), no information is saved about clients waiting on 362 Unlike (server-edit-files), no information is saved about clients waiting on
412 (server-write-to-client (car client) nil) ;nope, tell client 462 (server-write-to-client (car client) nil) ;nope, tell client
413 (setq server-clients (delq client server-clients)))) 463 (setq server-clients (delq client server-clients))))
414 (setq old-clients (cdr old-clients)))))))) 464 (setq old-clients (cdr old-clients))))))))
415 465
416 466
467 ;; Ask before killing a server buffer.
468 ;; It was suggested to release its client instead,
469 ;; but I think that is dangerous--the client would proceed
470 ;; using whatever is on disk in that file. -- rms.
471 (defun server-kill-buffer-query-function ()
472 (or server-kill-quietly
473 (not server-buffer-clients)
474 (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
475 (buffer-name (current-buffer))))))
476
477 (add-hook 'kill-buffer-query-functions
478 'server-kill-buffer-query-function)
479
480 (defun server-kill-emacs-query-function ()
481 (let (live-client
482 (tail server-clients))
483 ;; See if any clients have any buffers that are still alive.
484 (while tail
485 (if (memq t (mapcar 'stringp (mapcar 'buffer-name (cdr (car tail)))))
486 (setq live-client t))
487 (setq tail (cdr tail)))
488 (or server-kill-quietly
489 (not live-client)
490 (yes-or-no-p "Server buffers still have clients; exit anyway? "))))
491
492 (add-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
493
494
417 (defun server-kill-all-local-variables () 495 (defun server-kill-all-local-variables ()
418 "Eliminate all the buffer-local variable values of the current buffer. 496 "Eliminate all the buffer-local variable values of the current buffer.
419 This buffer will then see the default values of all variables. 497 This buffer will then see the default values of all variables.
420 NOTE: This function has been modified to ignore the variable 498 NOTE: This function has been modified to ignore the variable
421 server-buffer-clients." 499 server-buffer-clients."
439 517
440 (defun server-buffer-done (buffer) 518 (defun server-buffer-done (buffer)
441 "Mark BUFFER as \"done\" for its client(s). 519 "Mark BUFFER as \"done\" for its client(s).
442 Buries the buffer, and returns another server buffer as a suggestion for the 520 Buries the buffer, and returns another server buffer as a suggestion for the
443 new current buffer." 521 new current buffer."
522 ; Note we do NOT return a list with a killed flag, doesn't seem usefull to me. JV
444 (let ((next-buffer nil) 523 (let ((next-buffer nil)
445 (old-clients server-clients)) 524 (old-clients server-clients))
446 (while old-clients 525 (while old-clients
447 (let ((client (car old-clients))) 526 (let ((client (car old-clients)))
448 (or next-buffer 527 (or next-buffer
449 (setq next-buffer (nth 1 (memq buffer client)))) 528 (setq next-buffer (nth 1 (memq buffer client))))
450 (delq buffer client) 529 (delq buffer client)
530 ;; Delete all dead buffers from CLIENT. (Why? JV , copyed from server.el)
531 (let ((tail client))
532 (while tail
533 (and (bufferp (car tail))
534 (null (buffer-name (car tail)))
535 (delq (car tail) client))
536 (setq tail (cdr tail))))
451 ;; If client now has no pending buffers, 537 ;; If client now has no pending buffers,
452 ;; tell it that it is done, and forget it entirely. 538 ;; tell it that it is done, and forget it entirely.
453 (if (cdr client) 539 (if (cdr client)
454 nil 540 nil
455 (if (buffer-name buffer) 541 (if (buffer-name buffer)
456 (save-excursion 542 (save-excursion
457 (set-buffer buffer) 543 (set-buffer buffer)
458 (setq server-buffer-clients nil))) 544 (setq server-buffer-clients nil)
545 (run-hooks 'server-done-hook)))
459 ; Order is important here -- 546 ; Order is important here --
460 ; server-kill-buffer tries to notify clients that 547 ; server-kill-buffer tries to notify clients that
461 ; they are done, too, but if we try and notify twice, 548 ; they are done, too, but if we try and notify twice,
462 ; we are h0zed -- Hunter Kelly 3/3/97 549 ; we are h0zed -- Hunter Kelly 3/3/97
463 (setq server-clients (delq client server-clients)) 550 (setq server-clients (delq client server-clients))
464 (funcall server-done-function buffer) 551 (if (server-temp-file-p buffer)
552 (funcall server-done-temp-file-function buffer)
553 (funcall server-done-function buffer))
465 (server-write-to-client (car client) nil))) 554 (server-write-to-client (car client) nil)))
466 (setq old-clients (cdr old-clients))) 555 (setq old-clients (cdr old-clients)))
467 next-buffer)) 556 next-buffer))
468 557
469 558
478 "Offer to save current buffer and mark it as \"done\" for clients. 567 "Offer to save current buffer and mark it as \"done\" for clients.
479 Also bury it, and return a suggested new current buffer." 568 Also bury it, and return a suggested new current buffer."
480 (let ((buffer (current-buffer))) 569 (let ((buffer (current-buffer)))
481 (if server-buffer-clients 570 (if server-buffer-clients
482 (progn 571 (progn
483 (if (mh-draft-p buffer) 572 (if (mh-draft-p buffer);; Does this comflict with temp-file ? JV
484 (progn (save-buffer) 573 (progn (save-buffer)
485 (write-region (point-min) (point-max) 574 (write-region (point-min) (point-max)
486 (concat buffer-file-name "~")) 575 (concat buffer-file-name "~"))
487 (kill-buffer buffer)) 576 (kill-buffer buffer))
488 (if (and (buffer-modified-p) 577 (if (server-temp-file-p buffer)
489 (y-or-n-p (concat "Save file " buffer-file-name "? "))) 578 ;; For a temp file, save, and do NOT make a non-numeric backup
490 (save-buffer buffer))) 579 ;; Why does server.el explicitly back up temporary files?
580 (let ((version-control nil)
581 (buffer-backed-up (not server-make-temp-file-backup)))
582 (save-buffer))
583 (if (and (buffer-modified-p)
584 (y-or-n-p (concat "Save file " buffer-file-name "? ")))
585 (save-buffer buffer))))
491 (server-buffer-done buffer))))) 586 (server-buffer-done buffer)))))
492 587
493 588
494 (defun server-edit (&optional arg) 589 (defun server-edit (&optional arg)
495 "Switch to next server editing buffer and mark current one as \"done\". 590 "Switch to next server editing
496 If a server buffer is current, it is marked \"done\" and optionally saved. 591 buffer and mark current one as \"done\". If a server buffer is
497 MH <draft> files are always saved and backed up, no questions asked. 592 current, it is marked \"done\" and optionally saved. MH <draft> files
498 When all of a client's buffers are marked as \"done\", the client is notified. 593 are always saved and backed up, no questions asked. Files that match
594 server-temp-file-regexp are considered temporary and are saved
595 unconditionally and
596 backed up if server-make-temp-file-backup is non-nil. When all of a
597 client's buffers are marked as \"done\", the client is notified.
499 598
500 If invoked with a prefix argument, or if there is no server process running, 599 If invoked with a prefix argument, or if there is no server process running,
501 starts server process and that is all. Invoked by \\[server-edit]. 600 starts server process and that is all. Invoked by \\[server-edit].
502 601
503 If `server-kill-last-frame' is t, then the final frame will be killed." 602 If `server-kill-last-frame' is t, then the final frame will be killed."
505 (if (or arg 604 (if (or arg
506 (not server-process) 605 (not server-process)
507 (memq (process-status server-process) '(signal exit))) 606 (memq (process-status server-process) '(signal exit)))
508 (server-start nil) 607 (server-start nil)
509 (if server-buffer-clients 608 (if server-buffer-clients
510 (progn (server-switch-buffer (server-done)) 609 (progn (server-done-and-switch)
511 (cond ((fboundp 'console-type) ;; XEmacs 19.14+ 610 (cond ((fboundp 'console-type) ;; XEmacs 19.14+
512 (or (and (equal (console-type) 'x) 611 (or (and (equal (console-type) 'x)
513 gnuserv-frame 612 gnuserv-frame
514 (frame-live-p gnuserv-frame)) 613 (frame-live-p gnuserv-frame))
515 (condition-case () 614 (condition-case ()
532 (delete-screen)))) 631 (delete-screen))))
533 (error 632 (error
534 "(server-edit): Use only on buffers created by external programs.") 633 "(server-edit): Use only on buffers created by external programs.")
535 ))) 634 )))
536 635
537 (defun server-switch-buffer (next-buffer) 636 (defun server-switch-buffer-internal (next-buffer always)
538 "Switch to NEXT-BUFFER if a live buffer, otherwise switch to another buffer 637 "Switch to NEXT-BUFFER if a live buffer, otherwise switch to another buffer
539 with gnuserv clients. If no such buffer is available, simply choose another 638 with gnuserv clients. If no such buffer is available, we switch to
540 one." 639 another normal buffer if `always' is non-nil!"
640 ;; switching
541 (if next-buffer 641 (if next-buffer
542 (if (and (bufferp next-buffer) 642 (if (and (bufferp next-buffer)
543 (buffer-name next-buffer)) 643 (buffer-name next-buffer))
544 (switch-to-buffer next-buffer) 644 (switch-to-buffer next-buffer)
545 ;; If NEXT-BUFFER is a dead buffer, 645 ;; If NEXT-BUFFER is a dead buffer,
546 ;; remove the server records for it 646 ;; remove the server records for it
547 ;; and try the next surviving server buffer. 647 ;; and try the next surviving server buffer.
548 (server-switch-buffer 648 (server-switch-buffer-internal
549 (server-buffer-done next-buffer))) 649 (server-buffer-done next-buffer) always))
550 (if server-clients 650 (if server-clients
551 (server-switch-buffer (nth 1 (car server-clients))) 651 (server-switch-buffer-internal (nth 1 (car server-clients)) always)
552 (switch-to-buffer (other-buffer))))) 652 (if always
653 (switch-to-buffer (other-buffer))))))
654
655 ;; For compatability
656 (defun server-switch-buffer (next-buffer)
657 (server-switch-buffer-internal next-buffer t))
658
659 ;; The below function calles server-done and switches to the next
660 ;; sensible buffer. This implementation works regardless of the values
661 ;; of server-*-function and doens't need the tail recursion
662 ;; variable passing of server.el. It is more transparant too. JV
663 (defun server-done-and-switch ()
664 "Be done with the current buffer and switch to another server buffer
665 if there is one, otherwise just switch buffer"
666 (let ((old-current (current-buffer)))
667 (server-switch-buffer-internal (server-done) nil)
668 (if (eq old-current (current-buffer))
669 (switch-to-buffer (other-buffer)))))
553 670
554 (global-set-key "\C-x#" 'server-edit) 671 (global-set-key "\C-x#" 'server-edit)
555 672
556 (provide 'gnuserv) 673 (provide 'gnuserv)
557 674