Mercurial > hg > xemacs-beta
diff lisp/packages/gnuserv.el @ 195:a2f645c6b9f8 r20-3b24
Import from CVS: tag r20-3b24
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:59:05 +0200 |
parents | f53b5ca2e663 |
children | acd284d43ca1 |
line wrap: on
line diff
--- a/lisp/packages/gnuserv.el Mon Aug 13 09:58:32 2007 +0200 +++ b/lisp/packages/gnuserv.el Mon Aug 13 09:59:05 2007 +0200 @@ -1,9 +1,9 @@ ;;; gnuserv.el --- Lisp interface code between Emacs and gnuserv ;; Copyright (C) 1989-1997 Free Software Foundation, Inc. -;; Version: 3.10 +;; Version: 3.9 ;; Author: Andy Norman (ange@hplb.hpl.hp.com), originally based on server.el -;; Hrvoje Niksic <hniksic@srce.hr>, rewritten from scratch in May 1997 +;; Hrvoje Niksic <hniksic@srce.hr> ;; Maintainer: Jan Vroonhof <vroonhof@math.ethz.ch>, ;; Hrvoje Niksic <hniksic@srce.hr> ;; Keywords: environment, processes, terminals @@ -63,6 +63,12 @@ ;; Mukherjee, Ben Wing and Jan Vroonhof. It was completely rewritten ;; (labeled as version 3) by Hrvoje Niksic in May 1997. +;; Jan Vroonhof <vroonhof@math.ethz.ch> July/1996 +;; ported the server-temp-file-regexp feature from server.el +;; ported server hooks from server.el +;; ported kill-*-query functions from server.el (and made it optional) +;; synced other behaviour with server.el +;; ;; Jan Vroonhof ;; Customized. ;; @@ -72,9 +78,6 @@ ;; ;; Mike Scheidler <c23mts@eng.delcoelect.com> July, 1997 ;; Added 'Done' button to the menubar. -;; -;; Hrvoje Niksic <hniksic@srce.hr> Sep/1997 -;; More pervasive changes. ;;; Code: @@ -89,8 +92,7 @@ ;; Provide the old variables as aliases, to avoid breaking .emacs ;; files. However, they are obsolete and should be converted to the ;; new forms. This ugly crock must be before the variable -;; declaration, or the scheme fails. I'd prefer if we could junk this -;; sh*t, but I guess the users will appreciate compatibility. Uh... +;; declaration, or the scheme fails. (define-obsolete-variable-alias 'server-frame 'gnuserv-frame) (define-obsolete-variable-alias 'server-done-function @@ -107,50 +109,29 @@ 'gnuserv-done-hook) (define-obsolete-variable-alias 'server-kill-quietly 'gnuserv-kill-quietly) +(define-obsolete-variable-alias 'server-temp-file-regexp + 'gnuserv-temp-file-regexp) +(define-obsolete-variable-alias 'server-make-temp-file-backup + 'gnuserv-make-temp-file-backup) ;;;###autoload -(defcustom gnuserv-frame 'new - "*Determines what frame will be used to display all edited files. -Legal values are: - `new' -- a new frame will be created for each file edited; - `current' -- the currently selected frame will be used; - `main' -- \"main\" Emacs frame will be used; - `visible' -- a visible frame will be used, or a new one created; - `special' -- a special Gnuserv frame will be created, and used for - all gnuserv-edited files; - frame -- that particular frame will be used. - -If gnuclient is called using the `-nw' method (from a TTY device), the - behaviour will be as if gnuserv-frame were `new'. -This variable is read by `gnuserv-frame-default-function'. If you - change `gnuserv-frame-function' to anything else, this variable will - have no effect." +(defcustom gnuserv-frame nil + "*The frame to be used to display all edited files. +If nil, then a new frame is created for each file edited. +If t, then the currently selected frame will be used. +If a function, then this will be called with a symbol `x' or `tty' as the +only argument, and its return value will be interpreted as above." :tag "Gnuserv Frame" - ;; Compatibility - :type '(radio (const :tag "Create new frame each time" new) - (const :tag "Use currently selected frame" current) - (const :tag "Use main Emacs frame" main) - (const :tag "Use visible frame, otherwise create new" visible) - (const :tag "Create special Gnuserv frame and use it" special)) - :group 'gnuserv) - -(defcustom gnuserv-frame-properties nil - "*Properties of the frame in which gnuclient buffers are displayed. -Note that this is in effect only for frames created by -`gnuserv-frame-default-function'." - :type '(repeat (group :inline t - (symbol :tag "Property") - (sexp :tag "Value"))) - :group 'gnuserv) - -(defcustom gnuserv-frame-function 'gnuserv-frame-default-function - "*Function to return the appropriate frame for use by gnuclient. -The function will be called with two arguments: the first one as - described by `gnuserv-frame', and the second one as the device to - create the frame on. -The function must return a valid frame object." - :type 'function - :group 'gnuserv) + :type '(radio (const :tag "Create new frame each time" nil) + (const :tag "Use selected frame" t) + (function-item :tag "Use main Emacs frame" + gnuserv-main-frame-function) + (function-item :tag "Use visible frame, otherwise create new" + gnuserv-visible-frame-function) + (function-item :tag "Create special Gnuserv frame and use it" + gnuserv-special-frame-function) + (function :tag "Other")) + :group 'gnuserv) (defcustom gnuserv-done-function 'kill-buffer "*Function used to remove a buffer after editing. @@ -161,6 +142,15 @@ (function :tag "Other")) :group 'gnuserv) +(defcustom gnuserv-done-temp-file-function 'kill-buffer + "*Function used to remove a temporary buffer after editing. +It is called with one BUFFER argument. Functions such as `kill-buffer' and +`bury-buffer' are good values. See also `gnuserv-done-temp-file-function'." + :type '(radio (function-item kill-buffer) + (function-item bury-buffer) + (function :tag "Other")) + :group 'gnuserv) + (defcustom gnuserv-find-file-function 'find-file "*Function to visit a file with. It takes one argument, a file name to visit." @@ -207,6 +197,17 @@ :type 'boolean :group 'gnuserv) +(defcustom gnuserv-temp-file-regexp "^/tmp/Re\\|/draft$" + "*Regexp which should match filenames of temporary files deleted +and reused by the programs that invoke the Emacs server." + :type 'regexp + :group 'gnuserv) + +(defcustom gnuserv-make-temp-file-backup nil + "*Non-nil makes the server backup temporary files also." + :type 'boolean + :group 'gnuserv) + ;;; Internal variables: @@ -229,7 +230,7 @@ (device nil) (frame nil)) -(defvar gnuserv-process nil +(defvar gnuserv-process nil "The current gnuserv process.") (defvar gnuserv-string "" @@ -245,53 +246,43 @@ (defvar gnuserv-devices nil "List of devices created by clients.") -;; We want the client-infested buffers to have some modeline -;; identification, so we'll make a "minor mode". We don't use -;; `add-minor-mode', as we don't want it to be togglable. -(defvar gnuserv-minor-mode nil) - -(make-variable-buffer-local 'gnuserv-mode) -(pushnew '(gnuserv-minor-mode " Server") minor-mode-alist :test 'equal) - (defvar gnuserv-special-frame nil "Frame created specially for Server.") +;; We want the client-infested buffers to have some modeline +;; identification, so we'll make a "minor mode". +(defvar gnuserv-minor-mode nil) +(make-variable-buffer-local 'gnuserv-mode) +(pushnew '(gnuserv-minor-mode " Server") minor-mode-alist + :test 'equal) + -;; Creating gnuserv frame. +;; Sample gnuserv-frame functions + +(defun gnuserv-main-frame-function (type) + "Returns a sensible value for the main Emacs frame." + (if (eq type 'x) + (car (frame-list)) + nil)) -(defun gnuserv-frame-default-function (arg device) - "Default function to create Gnuserv frames. -See the documentation of `gnuserv-frame' for instructions how to -customize it." - ;; If we are on TTY, act as if `new' was given. - (if (not (device-on-window-system-p)) - (gnuserv-frame-default-function 'new device) - (cond - ((or (eq arg 'new) - ;; nil for back-compat - (eq arg nil)) - (make-frame gnuserv-frame-properties device)) - ((or (eq arg 'current) - ;; t for back-compat - (eq arg t)) - (selected-frame)) - ((eq arg 'main) - (car (frame-list))) - ((eq arg 'visible) - (cond ((car (filtered-frame-list 'frame-totally-visible-p device))) - ((car (filtered-frame-list (lambda (frame) - ;; eq t as in not 'hidden - (eq (frame-visible-p frame) t)) - device))) - (t (make-frame gnuserv-frame-properties device)))) - ((eq arg 'special) - (unless (frame-live-p gnuserv-special-frame) - (setq gnuserv-special-frame - (make-frame gnuserv-frame-properties device)))) - ((frame-live-p arg) - arg) - (t - (error "Invalid argument %s" arg))))) +(defun gnuserv-visible-frame-function (type) + "Returns a frame if there is a frame that is truly visible, nil otherwise. +This is meant in the X sense, so it will not return frames that are on another +visual screen. Totally visible frames are preferred. If none found, return nil." + (if (eq type 'x) + (cond ((car (filtered-frame-list 'frame-totally-visible-p + (selected-device)))) + ((car (filtered-frame-list (lambda (frame) + ;; eq t as in not 'hidden + (eq t (frame-visible-p frame))) + (selected-device))))) + nil)) + +(defun gnuserv-special-frame-function (type) + "Creates a special frame for Gnuserv and returns it on later invocations." + (unless (frame-live-p gnuserv-special-frame) + (setq gnuserv-special-frame (make-frame))) + gnuserv-special-frame) ;;; Communication functions @@ -411,17 +402,29 @@ (t (error "Invalid flag %s" flag)))) flags) (let* ((old-device-num (length (device-list))) - (old-frame-num (length (frame-list))) - (device (case (car type) + (new-frame nil) + (dest-frame (if (functionp gnuserv-frame) + (funcall gnuserv-frame (car type)) + gnuserv-frame)) + ;; The gnuserv-frame dependencies are ugly. + (device (cond ((frame-live-p dest-frame) + (frame-device dest-frame)) + ((null dest-frame) + (case (car type) (tty (apply 'make-tty-device (cdr type))) (x (make-x-device (cadr type))) (t (error "Invalid device type")))) - (frame (funcall gnuserv-frame-function gnuserv-frame device)) + (t + (selected-device)))) + (frame (cond ((frame-live-p dest-frame) + dest-frame) + ((null dest-frame) + (setq new-frame (make-frame nil device)) + new-frame) + (t (selected-frame)))) (client (make-gnuclient :id gnuserv-current-client :device device - :frame (if (= (length (frame-list)) - old-frame-num) - nil frame)))) + :frame new-frame))) (setq gnuserv-current-client nil) ;; If the device was created by this client, push it to the list. (and (/= old-device-num (length (device-list))) @@ -432,7 +435,6 @@ (while list (let ((line (caar list)) (path (cdar list))) (select-frame frame) - (raise-frame frame) ;; Visit the file. (funcall (if view gnuserv-view-file-function @@ -444,9 +446,10 @@ (pushnew (current-buffer) (gnuclient-buffers client)) (setq gnuserv-minor-mode t) ;; Add the "Done" button to the menubar, only in this buffer. - (when (boundp 'current-menubar) - (set-buffer-menubar current-menubar) - (add-menu-button nil ["Done" gnuserv-edit t]))) + (if (boundp 'current-menubar) + (progn (set-buffer-menubar current-menubar) + (add-menu-button nil ["Done" gnuserv-edit t])) + )) (run-hooks 'gnuserv-visit-hook) (pop list))) (cond @@ -460,19 +463,19 @@ (t ;; Else, the client gets a vote. (push client gnuserv-clients) - ;; Explain buffer exit options. If client-frame is non-nil, - ;; the user can exit via `delete-frame'. OTOH, if FLAGS are - ;; nil and there are some buffers, the user can exit via + ;; Explain buffer exit options. If dest-frame is nil, the + ;; user can exit via `delete-frame'. OTOH, if FLAGS are nil + ;; and there are some buffers, the user can exit via ;; `gnuserv-edit'. (if (and (not (or quick view)) (gnuclient-buffers client)) (message "%s" (substitute-command-keys "Type `\\[gnuserv-edit]' to finish editing")) - (and (gnuclient-frame client) - (message "%s" - (substitute-command-keys - "Type `\\[delete-frame]' to finish editing"))))))))) + (or dest-frame + (message "%s" + (substitute-command-keys + "Type `\\[delete-frame]' to finish editing"))))))))) ;;; Functions that hook into Emacs in various way to enable operation @@ -486,9 +489,10 @@ (defun gnuserv-buffer-clients (buffer) "Returns a list of clients to which BUFFER belongs." (let (res) - (dolist (client gnuserv-clients res) + (dolist (client gnuserv-clients) (when (memq buffer (gnuclient-buffers client)) - (push client res))))) + (push client res))) + res)) ;; Like `gnuserv-buffer-clients', but returns a boolean; doesn't ;; collect a list. @@ -549,6 +553,16 @@ (add-hook 'delete-device-hook 'gnuserv-check-device) +(defun gnuserv-temp-file-p (buffer) + "Return non-nil if BUFFER contains a file considered temporary. +These are files whose names suggest they are repeatedly +reused to pass information to another program. + +The variable `gnuserv-temp-file-regexp' controls which filenames +are considered temporary." + (and (buffer-file-name buffer) + (string-match gnuserv-temp-file-regexp (buffer-file-name buffer)))) + (defun gnuserv-kill-client (client &optional leave-frame) "Kill the gnuclient CLIENT. This will do away with all the associated buffers. If LEAVE-FRAME, @@ -594,7 +608,10 @@ ;; Delete the menu button. (if (boundp 'current-menubar) (delete-menu-item '("Done"))) - (funcall gnuserv-done-function buffer))) + (funcall (if (gnuserv-temp-file-p buffer) + gnuserv-done-temp-file-function + gnuserv-done-function) + buffer))) ;;; Higher-level functions @@ -633,9 +650,15 @@ (unless (gnuserv-buffer-p buffer) (error "%s does not belong to a gnuserv client" buffer)) ;; Backup/ask query. - (if (and (buffer-modified-p) - (y-or-n-p (concat "Save file " buffer-file-name "? "))) - (save-buffer buffer)) + (if (gnuserv-temp-file-p buffer) + ;; For a temp file, save, and do NOT make a non-numeric backup + ;; Why does server.el explicitly back up temporary files? + (let ((version-control nil) + (buffer-backed-up (not gnuserv-make-temp-file-backup))) + (save-buffer)) + (if (and (buffer-modified-p) + (y-or-n-p (concat "Save file " buffer-file-name "? "))) + (save-buffer buffer))) (gnuserv-buffer-done-1 buffer)) ;; Called by `gnuserv-start-1' to clean everything. Hooked into @@ -692,9 +715,10 @@ ;;;###autoload (defun gnuserv-start (&optional leave-dead) "Allow this Emacs process to be a server for client processes. - This starts a gnuserv communications subprocess through which - client \"editors\" (gnuclient and gnudoit) can send editing commands to - this Emacs job. See the gnuserv(1) manual page for more details. +This starts a gnuserv communications subprocess through which +client \"editors\" (gnuclient and gnudoit) can send editing commands to +this Emacs job. See the gnuserv(1) manual page for more details. + Prefix arg means just kill any existing server communications subprocess." (interactive "P") (and gnuserv-process @@ -703,14 +727,21 @@ (gnuserv-start-1 leave-dead)) (defun gnuserv-edit (&optional count) - "Mark the current gnuserv buffer as \"done\", and switch to next one. + "Mark the current gnuserv editing buffer as \"done\", and switch to next one. + Run with a numeric prefix argument, repeat the operation that number - of times. If given a universal prefix argument, close all the buffers - of this buffer's clients. -The `gnuserv-done-function' (`kill-buffer' by default) is called to - dispose of the buffer after marking it as done. -When all of a client's buffers are marked as \"done\", the client is - notified." +of times. If given a universal prefix argument, close all the buffers +of this buffer's clients. + +The `gnuserv-done-function' (bound to `kill-buffer' by default) is +called to dispose of the buffer after marking it as done. + +Files that match `gnuserv-temp-file-regexp' are considered temporary and +are saved unconditionally and backed up if `gnuserv-make-temp-file-backup' +is non-nil. They are disposed of using `gnuserv-done-temp-file-function' +(also bound to `kill-buffer' by default). + +When all of a client's buffers are marked as \"done\", the client is notified." (interactive "P") (when (null count) (setq count 1))