(vc-diff-sentinel, vc-diff-internal): Revert some changes in the
[bpt/emacs.git] / lisp / server.el
CommitLineData
55535639 1;;; server.el --- Lisp code for GNU Emacs running as server process
c88ab9ce 2
0d30b337 3;; Copyright (C) 1986, 1987, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
da6657b7 4;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6d74b528 5
630cc463 6;; Author: William Sommerfeld <wesommer@athena.mit.edu>
e4874521 7;; Maintainer: FSF
d7b4d18f 8;; Keywords: processes
630cc463 9
9ae0f972 10;; Changes by peck@sun.com and by rms.
35dfa9b6 11;; Overhaul by Karoly Lorentey <lorentey@elte.hu> for multi-tty support.
9ae0f972 12
13;; This file is part of GNU Emacs.
14
15;; GNU Emacs is free software; you can redistribute it and/or modify
16;; it under the terms of the GNU General Public License as published by
b4aa6026 17;; the Free Software Foundation; either version 3, or (at your option)
9ae0f972 18;; any later version.
19
20;; GNU Emacs is distributed in the hope that it will be useful,
21;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23;; GNU General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
b578f267 26;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
27;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28;; Boston, MA 02110-1301, USA.
9ae0f972 29
630cc463 30;;; Commentary:
9ae0f972 31
b578f267
EN
32;; This Lisp code is run in Emacs when it is to operate as
33;; a server for other processes.
9ae0f972 34
b578f267 35;; Load this library and do M-x server-edit to enable Emacs as a server.
44a56b29
SM
36;; Emacs opens up a socket for communication with clients. If there are no
37;; client buffers to edit, server-edit acts like (switch-to-buffer
38;; (other-buffer))
9ae0f972 39
b578f267
EN
40;; When some other program runs "the editor" to edit a file,
41;; "the editor" can be the Emacs client program ../lib-src/emacsclient.
42;; This program transmits the file names to Emacs through
43;; the server subprocess, and Emacs visits them and lets you edit them.
9ae0f972 44
6d3a46f7 45;; Note that any number of clients may dispatch files to Emacs to be edited.
9ae0f972 46
b578f267 47;; When you finish editing a Server buffer, again call server-edit
64f51134
JPW
48;; to mark that buffer as done for the client and switch to the next
49;; Server buffer. When all the buffers for a client have been edited
b578f267 50;; and exited with server-edit, the client "editor" will return
64f51134 51;; to the program that invoked it.
9ae0f972 52
b578f267
EN
53;; Your editing commands and Emacs's display output go to and from
54;; the terminal in the usual way. Thus, server operation is possible
55;; only when Emacs can talk to the terminal at the time you invoke
56;; the client. This is possible in four cases:
9ae0f972 57
b578f267
EN
58;; 1. On a window system, where Emacs runs in one window and the
59;; program that wants to use "the editor" runs in another.
9ae0f972 60
b578f267
EN
61;; 2. On a multi-terminal system, where Emacs runs on one terminal and the
62;; program that wants to use "the editor" runs on another.
9ae0f972 63
b578f267
EN
64;; 3. When the program that wants to use "the editor" is running
65;; as a subprocess of Emacs.
9ae0f972 66
b578f267
EN
67;; 4. On a system with job control, when Emacs is suspended, the program
68;; that wants to use "the editor" will stop and display
69;; "Waiting for Emacs...". It can then be suspended, and Emacs can be
70;; brought into the foreground for editing. When done editing, Emacs is
71;; suspended again, and the client program is brought into the foreground.
9ae0f972 72
64f51134
JPW
73;; The buffer local variable "server-buffer-clients" lists
74;; the clients who are waiting for this buffer to be edited.
b578f267
EN
75;; The global variable "server-clients" lists all the waiting clients,
76;; and which files are yet to be edited for each.
630cc463 77
0acb1916
SM
78;; Todo:
79
80;; - handle command-line-args-left.
81;; - move most of the args processing and decision making from emacsclient.c
82;; to here.
83;; - fix up handling of the client's environment (place it in the terminal?).
84
630cc463 85;;; Code:
8b3e840e
SM
86
87(eval-when-compile (require 'cl))
88
ab1c7f35
RS
89(defgroup server nil
90 "Emacs running as a server process."
91 :group 'external)
92
337e3c70
JB
93(defcustom server-use-tcp nil
94 "If non-nil, use TCP sockets instead of local sockets."
95 :set #'(lambda (sym val)
96 (unless (featurep 'make-network-process '(:family local))
97 (setq val t)
98 (unless load-in-progress
99 (message "Local sockets unsupported, using TCP sockets")))
100 (when val (random t))
101 (set-default sym val))
102 :group 'server
103 :type 'boolean
104 :version "22.1")
105
106(defcustom server-host nil
107 "The name or IP address to use as host address of the server process.
108If set, the server accepts remote connections; otherwise it is local."
109 :group 'server
110 :type '(choice
111 (string :tag "Name or IP address")
112 (const :tag "Local" nil))
113 :version "22.1")
114(put 'server-host 'risky-local-variable t)
115
0eee7a1d 116(defcustom server-auth-dir (concat user-emacs-directory "server/")
337e3c70
JB
117 "Directory for server authentication files."
118 :group 'server
119 :type 'directory
120 :version "22.1")
121(put 'server-auth-dir 'risky-local-variable t)
122
90caccca 123(defcustom server-raise-frame t
ff348fba 124 "If non-nil, raise frame when switching to a buffer."
90caccca
JB
125 :group 'server
126 :type 'boolean
127 :version "22.1")
128
ab1c7f35 129(defcustom server-visit-hook nil
ff348fba 130 "Hook run when visiting a file for the Emacs server."
ab1c7f35 131 :group 'server
0c851d78 132 :type 'hook)
ab1c7f35
RS
133
134(defcustom server-switch-hook nil
ff348fba 135 "Hook run when switching to a buffer for the Emacs server."
ab1c7f35 136 :group 'server
0c851d78 137 :type 'hook)
ab1c7f35
RS
138
139(defcustom server-done-hook nil
ff348fba 140 "Hook run when done editing a buffer for the Emacs server."
ab1c7f35 141 :group 'server
0c851d78 142 :type 'hook)
f9b3ef88 143
64f51134
JPW
144(defvar server-process nil
145 "The current server process.")
9ae0f972 146
147(defvar server-clients nil
148 "List of current server clients.
448f754f 149Each element is a process.")
0a125897 150
9ae0f972 151(defvar server-buffer-clients nil
5f3c1a63 152 "List of client processes requesting editing of current buffer.")
faf931a8 153(make-variable-buffer-local 'server-buffer-clients)
9ae0f972 154;; Changing major modes should not erase this local.
155(put 'server-buffer-clients 'permanent-local t)
156
33186f32 157(defcustom server-window nil
ff348fba 158 "Specification of the window to use for selecting Emacs server buffers.
ec40ed9f 159If nil, use the selected window.
408784a7 160If it is a function, it should take one argument (a buffer) and
33186f32
DL
161display and select it. A common value is `pop-to-buffer'.
162If it is a window, use that.
163If it is a frame, use the frame's selected window.
164
165It is not meaningful to set this to a specific frame or window with Custom.
166Only programs can do so."
167 :group 'server
bf247b6e 168 :version "22.1"
33186f32
DL
169 :type '(choice (const :tag "Use selected window"
170 :match (lambda (widget value)
171 (not (functionp value)))
172 nil)
ee9272ff 173 (function-item :tag "Display in new frame" switch-to-buffer-other-frame)
33186f32
DL
174 (function-item :tag "Use pop-to-buffer" pop-to-buffer)
175 (function :tag "Other function")))
ec40ed9f 176
ab1c7f35 177(defcustom server-temp-file-regexp "^/tmp/Re\\|/draft$"
ff348fba 178 "Regexp matching names of temporary files.
33186f32
DL
179These are deleted and reused after each edit by the programs that
180invoke the Emacs server."
ab1c7f35
RS
181 :group 'server
182 :type 'regexp)
9ae0f972 183
c6a117f0 184(defcustom server-kill-new-buffers t
ff348fba 185 "Whether to kill buffers when done with them.
c6a117f0 186If non-nil, kill a buffer unless it already existed before editing
f258b525 187it with the Emacs server. If nil, kill only buffers as specified by
c6a117f0 188`server-temp-file-regexp'.
f258b525
GM
189Please note that only buffers that still have a client are killed,
190i.e. buffers visited with \"emacsclient --no-wait\" are never killed in
c6a117f0
GM
191this way."
192 :group 'server
193 :type 'boolean
194 :version "21.1")
195
9ae0f972 196(or (assq 'server-buffer-clients minor-mode-alist)
b7621225 197 (push '(server-buffer-clients " Server") minor-mode-alist))
9ae0f972 198
c6a117f0 199(defvar server-existing-buffer nil
ca0c7250 200 "Non-nil means the buffer existed before the server was asked to visit it.
4dd04714 201This means that the server should not kill the buffer when you say you
ca0c7250 202are done with it in the server.")
c6a117f0
GM
203(make-variable-buffer-local 'server-existing-buffer)
204
03ae35cf
SM
205(defvar server-name "server")
206
fc0dcdef
KL
207(defvar server-socket-dir nil
208 "The directory in which to place the server socket.
209Initialized by `server-start'.")
0c851d78 210
9002956f
KL
211(defun server-clients-with (property value)
212 "Return a list of clients with PROPERTY set to VALUE."
213 (let (result)
448f754f
SM
214 (dolist (proc server-clients result)
215 (when (equal value (process-get proc property))
216 (push proc result)))))
9002956f
KL
217
218(defun server-add-client (proc)
219 "Create a client for process PROC, if it doesn't already have one.
220New clients have no properties."
448f754f 221 (add-to-list 'server-clients proc))
9002956f 222
59e085e0
KL
223(defmacro server-with-environment (env vars &rest body)
224 "Evaluate BODY with environment variables VARS set to those in ENV.
65f64034
KL
225The environment variables are then restored to their previous values.
226
59e085e0
KL
227VARS should be a list of strings.
228ENV should be in the same format as `process-environment'."
65f64034 229 (declare (indent 2))
13ba3740
SM
230 (let ((var (make-symbol "var"))
231 (value (make-symbol "value")))
232 `(let ((process-environment process-environment))
59e085e0 233 (dolist (,var ,vars)
e159b869 234 (let ((,value (getenv-internal ,var ,env)))
13ba3740
SM
235 (push (if (null ,value)
236 ,var
237 (concat ,var "=" ,value))
238 process-environment)))
239 (progn ,@body))))
65f64034 240
448f754f 241(defun server-delete-client (proc &optional noframe)
6ed8eeff 242 "Delete CLIENT, including its buffers, terminals and frames.
de93c791 243If NOFRAME is non-nil, let the frames live. (To be used from
5f3c1a63
KL
244`delete-frame-functions'.)"
245 (server-log (concat "server-delete-client" (if noframe " noframe"))
448f754f 246 proc)
9002956f 247 ;; Force a new lookup of client (prevents infinite recursion).
448f754f
SM
248 (when (memq proc server-clients)
249 (let ((buffers (process-get proc 'buffers)))
9002956f 250
5f3c1a63 251 ;; Kill the client's buffers.
9002956f 252 (dolist (buf buffers)
6ed9e43a
KL
253 (when (buffer-live-p buf)
254 (with-current-buffer buf
6ed9e43a 255 ;; Kill the buffer if necessary.
5f3c1a63
KL
256 (when (and (equal server-buffer-clients
257 (list proc))
6ed9e43a
KL
258 (or (and server-kill-new-buffers
259 (not server-existing-buffer))
5f3c1a63
KL
260 (server-temp-file-p))
261 (not (buffer-modified-p)))
262 (let (flag)
263 (unwind-protect
264 (progn (setq server-buffer-clients nil)
265 (kill-buffer (current-buffer))
266 (setq flag t))
267 (unless flag
268 ;; Restore clients if user pressed C-g in `kill-buffer'.
269 (setq server-buffer-clients (list proc)))))))))
9002956f 270
160f0817
KL
271 ;; Delete the client's frames.
272 (unless noframe
273 (dolist (frame (frame-list))
274 (when (and (frame-live-p frame)
275 (equal proc (frame-parameter frame 'client)))
276 ;; Prevent `server-handle-delete-frame' from calling us
277 ;; recursively.
278 (set-frame-parameter frame 'client nil)
279 (delete-frame frame))))
280
448f754f 281 (setq server-clients (delq proc server-clients))
5f3c1a63 282
9002956f 283 ;; Delete the client's tty.
448f754f 284 (let ((terminal (process-get proc 'terminal)))
977ede64
DN
285 ;; Only delete the terminal if it is non-nil.
286 (when (and terminal (eq (terminal-live-p terminal) t))
6ed8eeff 287 (delete-terminal terminal)))
9002956f 288
9002956f 289 ;; Delete the client's process.
448f754f
SM
290 (if (eq (process-status proc) 'open)
291 (delete-process proc))
9002956f
KL
292
293 (server-log "Deleted" proc))))
294
8b3e840e 295(defun server-log (string &optional client)
6d3a46f7
KL
296 "If a *server* buffer exists, write STRING to it for logging purposes.
297If CLIENT is non-nil, add a description of it to the logged
298message."
337e3c70
JB
299 (when (get-buffer "*server*")
300 (with-current-buffer "*server*"
301 (goto-char (point-max))
302 (insert (current-time-string)
974b73e8
KL
303 (cond
304 ((null client) " ")
305 ((listp client) (format " %s: " (car client)))
306 (t (format " %s: " client)))
337e3c70
JB
307 string)
308 (or (bolp) (newline)))))
9ae0f972 309
310(defun server-sentinel (proc msg)
9002956f 311 "The process sentinel for Emacs server connections."
cbfc02e4
RF
312 ;; If this is a new client process, set the query-on-exit flag to nil
313 ;; for this process (it isn't inherited from the server process).
314 (when (and (eq (process-status proc) 'open)
315 (process-query-on-exit-flag proc))
316 (set-process-query-on-exit-flag proc nil))
757e1681
SM
317 ;; Delete the associated connection file, if applicable.
318 ;; This is actually problematic: the file may have been overwritten by
319 ;; another Emacs server in the mean time, so it's not ours any more.
320 ;; (and (process-contact proc :server)
321 ;; (eq (process-status proc) 'closed)
322 ;; (ignore-errors (delete-file (process-get proc :server-file))))
9002956f
KL
323 (server-log (format "Status changed to %s: %s" (process-status proc) msg) proc)
324 (server-delete-client proc))
0c851d78 325
13ba3740
SM
326(defun server-select-display (display)
327 ;; If the current frame is on `display' we're all set.
328 (unless (equal (frame-parameter (selected-frame) 'display) display)
329 ;; Otherwise, look for an existing frame there and select it.
330 (dolist (frame (frame-list))
331 (when (equal (frame-parameter frame 'display) display)
332 (select-frame frame)))
333 ;; If there's no frame on that display yet, create and select one.
334 (unless (equal (frame-parameter (selected-frame) 'display) display)
335 (let* ((buffer (generate-new-buffer " *server-dummy*"))
336 (frame (make-frame-on-display
337 display
338 ;; Make it display (and remember) some dummy buffer, so
339 ;; we can detect later if the frame is in use or not.
340 `((server-dummmy-buffer . ,buffer)
341 ;; This frame may be deleted later (see
342 ;; server-unselect-display) so we want it to be as
343 ;; unobtrusive as possible.
344 (visibility . nil)))))
345 (select-frame frame)
346 (set-window-buffer (selected-window) buffer)
347 frame))))
348
349(defun server-unselect-display (frame)
350 (when (frame-live-p frame)
351 ;; If the temporary frame is in use (displays something real), make it
352 ;; visible. If not (which can happen if the user's customizations call
353 ;; pop-to-buffer etc.), delete it to avoid preserving the connection after
354 ;; the last real frame is deleted.
355 (if (and (eq (frame-first-window frame)
356 (next-window (frame-first-window frame) 'nomini))
357 (eq (window-buffer (frame-first-window frame))
358 (frame-parameter frame 'server-dummy-buffer)))
359 ;; The temp frame still only shows one buffer, and that is the
360 ;; internal temp buffer.
361 (delete-frame frame)
362 (set-frame-parameter frame 'visibility t))
363 (kill-buffer (frame-parameter frame 'server-dummy-buffer))
364 (set-frame-parameter frame 'server-dummy-buffer nil)))
365
77134727
KL
366(defun server-handle-delete-frame (frame)
367 "Delete the client connection when the emacsclient frame is deleted."
9002956f 368 (let ((proc (frame-parameter frame 'client)))
e519a50b
KL
369 (when (and (frame-live-p frame)
370 proc
160f0817 371 ;; See if this is the last frame for this client.
d5381da2 372 (>= 1 (let ((frame-num 0))
aabf0cb9 373 (dolist (f (frame-list))
160f0817
KL
374 (when (eq proc (frame-parameter f 'client))
375 (setq frame-num (1+ frame-num))))
376 frame-num)))
9002956f 377 (server-log (format "server-handle-delete-frame, frame %s" frame) proc)
de93c791 378 (server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
9002956f 379
6ed8eeff 380(defun server-handle-suspend-tty (terminal)
9002956f 381 "Notify the emacsclient process to suspend itself when its tty device is suspended."
6ed8eeff
KL
382 (dolist (proc (server-clients-with 'terminal terminal))
383 (server-log (format "server-handle-suspend-tty, terminal %s" terminal) proc)
6d3a46f7 384 (condition-case err
6afdd335 385 (server-send-string proc "-suspend \n")
44954c2f
SM
386 (file-error ;The pipe/socket was closed.
387 (ignore-errors (server-delete-client proc))))))
44a56b29 388
0c851d78 389(defun server-unquote-arg (arg)
6afdd335
KL
390 "Remove &-quotation from ARG.
391See `server-quote-arg' and `server-process-filter'."
0c851d78
SM
392 (replace-regexp-in-string
393 "&." (lambda (s)
394 (case (aref s 1)
395 (?& "&")
396 (?- "-")
397 (?n "\n")
398 (t " ")))
399 arg t t))
9ae0f972 400
0b0d3e0b 401(defun server-quote-arg (arg)
9002956f 402 "In ARG, insert a & before each &, each space, each newline, and -.
0b0d3e0b 403Change spaces to underscores, too, so that the return value never
6afdd335
KL
404contains a space.
405
406See `server-unquote-arg' and `server-process-filter'."
0b0d3e0b
KL
407 (replace-regexp-in-string
408 "[-&\n ]" (lambda (s)
409 (case (aref s 0)
410 (?& "&&")
411 (?- "&-")
412 (?\n "&n")
413 (?\s "&_")))
414 arg t t))
415
6afdd335
KL
416(defun server-send-string (proc string)
417 "A wrapper around `proc-send-string' for logging."
418 (server-log (concat "Sent " string) proc)
419 (process-send-string proc string))
420
724629d2
SM
421(defun server-ensure-safe-dir (dir)
422 "Make sure DIR is a directory with no race-condition issues.
423Creates the directory if necessary and makes sure:
424- there's no symlink involved
425- it's owned by us
426- it's not readable/writable by anybody else."
427 (setq dir (directory-file-name dir))
428 (let ((attrs (file-attributes dir)))
429 (unless attrs
337e3c70 430 (letf (((default-file-modes) ?\700)) (make-directory dir t))
724629d2
SM
431 (setq attrs (file-attributes dir)))
432 ;; Check that it's safe for use.
da6657b7 433 (unless (and (eq t (car attrs)) (eql (nth 2 attrs) (user-uid))
337e3c70
JB
434 (or (eq system-type 'windows-nt)
435 (zerop (logand ?\077 (file-modes dir)))))
724629d2
SM
436 (error "The directory %s is unsafe" dir))))
437
7229064d 438;;;###autoload
9ae0f972 439(defun server-start (&optional leave-dead)
440 "Allow this Emacs process to be a server for client processes.
441This starts a server communications subprocess through which
6d3a46f7
KL
442client \"editors\" can send your editing commands to this Emacs
443job. To use the server, set up the program `emacsclient' in the
9ae0f972 444Emacs distribution as your standard \"editor\".
445
bd410bb0
EZ
446Optional argument LEAVE-DEAD (interactively, a prefix arg) means just
447kill any existing server communications subprocess."
9ae0f972 448 (interactive "P")
d6b4b3cf
KL
449 (when (or
450 (not server-clients)
451 (yes-or-no-p
452 "The current server still has clients; delete them? "))
453 ;; It is safe to get the user id now.
454 (setq server-socket-dir (or server-socket-dir
455 (format "/tmp/emacs%d" (user-uid))))
974b73e8
KL
456 (when server-process
457 ;; kill it dead!
458 (ignore-errors (delete-process server-process)))
d6b4b3cf
KL
459 ;; Delete the socket files made by previous server invocations.
460 (condition-case ()
461 (delete-file (expand-file-name server-name server-socket-dir))
462 (error nil))
463 ;; If this Emacs already had a server, clear out associated status.
464 (while server-clients
465 (server-delete-client (car server-clients)))
9f97e26d 466 ;; Now any previous server is properly stopped.
d6b4b3cf
KL
467 (if leave-dead
468 (progn
469 (server-log (message "Server stopped"))
470 (setq server-process nil))
974b73e8
KL
471 (let* ((server-dir (if server-use-tcp server-auth-dir server-socket-dir))
472 (server-file (expand-file-name server-name server-dir)))
473 ;; Make sure there is a safe directory in which to place the socket.
474 (server-ensure-safe-dir server-dir)
475 ;; Remove any leftover socket or authentication file.
476 (ignore-errors (delete-file server-file))
477 (when server-process
478 (server-log (message "Restarting server")))
479 (letf (((default-file-modes) ?\700))
e4019195 480 (add-hook 'suspend-tty-functions 'server-handle-suspend-tty)
974b73e8
KL
481 (add-hook 'delete-frame-functions 'server-handle-delete-frame)
482 (add-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
483 (add-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
484 (setq server-process
485 (apply #'make-network-process
486 :name server-name
487 :server t
488 :noquery t
489 :sentinel 'server-sentinel
490 :filter 'server-process-filter
491 ;; We must receive file names without being decoded.
492 ;; Those are decoded by server-process-filter according
493 ;; to file-name-coding-system.
494 :coding 'raw-text
495 ;; The rest of the args depends on the kind of socket used.
496 (if server-use-tcp
497 (list :family nil
498 :service t
499 :host (or server-host 'local)
500 :plist '(:authenticated nil))
501 (list :family 'local
502 :service server-file
503 :plist '(:authenticated t)))))
504 (unless server-process (error "Could not start server process"))
505 (when server-use-tcp
506 (let ((auth-key
507 (loop
d76e2046
JB
508 ;; The auth key is a 64-byte string of random chars in the
509 ;; range `!'..`~'.
510 for i below 64
511 collect (+ 33 (random 94)) into auth
512 finally return (concat auth))))
974b73e8
KL
513 (process-put server-process :auth-key auth-key)
514 (with-temp-file server-file
515 (set-buffer-multibyte nil)
516 (setq buffer-file-coding-system 'no-conversion)
517 (insert (format-network-address
518 (process-contact server-process :local))
519 " " (int-to-string (emacs-pid))
520 "\n" auth-key)))))))))
33186f32 521
44954c2f
SM
522(defun server-running-p (&optional name)
523 "Test whether server NAME is running."
524 (interactive
525 (list (if current-prefix-arg
526 (read-string "Server name: " nil nil server-name))))
527 (unless name (setq name server-name))
528 (condition-case nil
529 (progn
530 (delete-process
531 (make-network-process
532 :name "server-client-test" :family 'local :server nil :noquery t
533 :service (expand-file-name name server-socket-dir)))
534 t)
535 (file-error nil)))
536
33186f32
DL
537;;;###autoload
538(define-minor-mode server-mode
539 "Toggle Server mode.
540With ARG, turn Server mode on if ARG is positive, off otherwise.
541Server mode runs a process that accepts commands from the
542`emacsclient' program. See `server-start' and Info node `Emacs server'."
543 :global t
544 :group 'server
bf247b6e 545 :version "22.1"
33186f32
DL
546 ;; Fixme: Should this check for an existing server socket and do
547 ;; nothing if there is one (for multiple Emacs sessions)?
548 (server-start (not server-mode)))
9ae0f972 549\f
13ba3740
SM
550(defun server-eval-and-print (expr proc)
551 "Eval EXPR and send the result back to client PROC."
552 (let ((v (eval (car (read-from-string expr)))))
553 (when (and v proc)
554 (with-temp-buffer
555 (let ((standard-output (current-buffer)))
556 (pp v)
557 (let ((text (buffer-substring-no-properties
558 (point-min) (point-max))))
559 (server-send-string
560 proc (format "-print %s\n"
561 (server-quote-arg text)))))))))
562
563(defun server-create-tty-frame (tty type proc)
4419b755 564 (add-to-list 'frame-inherited-parameters 'client)
13ba3740
SM
565 (let ((frame
566 (server-with-environment (process-get proc 'env)
567 '("LANG" "LC_CTYPE" "LC_ALL"
568 ;; For tgetent(3); list according to ncurses(3).
569 "BAUDRATE" "COLUMNS" "ESCDELAY" "HOME" "LINES"
570 "NCURSES_ASSUMED_COLORS" "NCURSES_NO_PADDING"
571 "NCURSES_NO_SETBUF" "TERM" "TERMCAP" "TERMINFO"
572 "TERMINFO_DIRS" "TERMPATH"
573 ;; rxvt wants these
574 "COLORFGBG" "COLORTERM")
575 (make-frame-on-tty tty type
576 ;; Ignore nowait here; we always need to
577 ;; clean up opened ttys when the client dies.
578 `((client . ,proc)
4419b755
SM
579 ;; This is a leftover from an earlier
580 ;; attempt at making it possible for process
581 ;; run in the server process to use the
582 ;; environment of the client process.
583 ;; It has no effect now and to make it work
584 ;; we'd need to decide how to make
585 ;; process-environment interact with client
586 ;; envvars, and then to change the
587 ;; C functions `child_setup' and
588 ;; `getenv_internal' accordingly.
448f754f 589 (environment . ,(process-get proc 'env)))))))
13ba3740 590
e159b869
SM
591 ;; ttys don't use the `display' parameter, but callproc.c does to set
592 ;; the DISPLAY environment on subprocesses.
593 (set-frame-parameter frame 'display
594 (getenv-internal "DISPLAY" (process-get proc 'env)))
13ba3740 595 (select-frame frame)
448f754f 596 (process-put proc 'frame frame)
448f754f 597 (process-put proc 'terminal (frame-terminal frame))
13ba3740
SM
598
599 ;; Display *scratch* by default.
600 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord)
601
602 ;; Reply with our pid.
603 (server-send-string proc (concat "-emacs-pid "
604 (number-to-string (emacs-pid)) "\n"))
605 frame))
606
607(defun server-create-window-system-frame (display nowait proc)
4419b755 608 (add-to-list 'frame-inherited-parameters 'client)
e159b869 609 (if (not (fboundp 'make-frame-on-display))
13ba3740
SM
610 (progn
611 ;; This emacs does not support X.
612 (server-log "Window system unsupported" proc)
613 (server-send-string proc "-window-system-unsupported \n")
614 nil)
615 ;; Flag frame as client-created, but use a dummy client.
616 ;; This will prevent the frame from being deleted when
617 ;; emacsclient quits while also preventing
618 ;; `server-save-buffers-kill-terminal' from unexpectedly
619 ;; killing emacs on that frame.
620 (let* ((params `((client . ,(if nowait 'nowait proc))
4419b755 621 ;; This is a leftover, see above.
13ba3740
SM
622 (environment . ,(process-get proc 'env))))
623 (frame (make-frame-on-display
624 (or display
625 (frame-parameter nil 'display)
626 (getenv "DISPLAY")
627 (error "Please specify display"))
448f754f 628 params)))
13ba3740 629 (server-log (format "%s created" frame) proc)
4419b755
SM
630 ;; XXX We need to ensure the parameters are really set because Emacs
631 ;; forgets unhandled initialization parameters for X frames at
13ba3740
SM
632 ;; the moment.
633 (modify-frame-parameters frame params)
13ba3740 634 (select-frame frame)
448f754f
SM
635 (process-put proc 'frame frame)
636 (process-put proc 'terminal (frame-terminal frame))
13ba3740
SM
637
638 ;; Display *scratch* by default.
639 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord)
640 frame)))
641
642
643(defun server-goto-toplevel (proc)
644 (condition-case nil
645 ;; If we're running isearch, we must abort it to allow Emacs to
646 ;; display the buffer and switch to it.
647 (dolist (buffer (buffer-list))
648 (with-current-buffer buffer
649 (when (bound-and-true-p isearch-mode)
650 (isearch-cancel))))
651 ;; Signaled by isearch-cancel.
652 (quit (message nil)))
653 (when (> (recursion-depth) 0)
654 ;; We're inside a minibuffer already, so if the emacs-client is trying
655 ;; to open a frame on a new display, we might end up with an unusable
656 ;; frame because input from that display will be blocked (until exiting
657 ;; the minibuffer). Better exit this minibuffer right away.
658 ;; Similarly with recursive-edits such as the splash screen.
659 (run-with-timer 0 nil (lexical-let ((proc proc))
660 (lambda () (server-execute-continuation proc))))
661 (top-level)))
662
663;; We use various special properties on process objects:
664;; - `env' stores the info about the environment of the emacsclient process.
665;; - `continuation' is a no-arg function that we need to execute. It contains
666;; commands we wanted to execute in some earlier invocation of the process
667;; filter but that we somehow were unable to process at that time
668;; (e.g. because we first need to throw to the toplevel).
669
670(defun server-execute-continuation (proc)
671 (let ((continuation (process-get proc 'continuation)))
672 (process-put proc 'continuation nil)
673 (if continuation (ignore-errors (funcall continuation)))))
674
337e3c70 675(defun* server-process-filter (proc string)
33186f32 676 "Process a request from the server to edit some files.
6afdd335
KL
677PROC is the server process. STRING consists of a sequence of
678commands prefixed by a dash. Some commands have arguments; these
679are &-quoted and need to be decoded by `server-unquote-arg'. The
680filter parses and executes these commands.
681
682To illustrate the protocol, here is an example command that
683emacsclient sends to create a new X frame (note that the whole
684sequence is sent on a single line):
685
6afdd335
KL
686 -env HOME /home/lorentey
687 -env DISPLAY :0.0
688 ... lots of other -env commands
689 -display :0.0
690 -window-system
691
6afdd335
KL
692The following commands are accepted by the server:
693
974b73e8
KL
694`-auth AUTH-STRING'
695 Authenticate the client using the secret authentication string
a38daa0a 696 AUTH-STRING.
974b73e8 697
59e085e0 698`-env NAME=VALUE'
6afdd335
KL
699 An environment variable on the client side.
700
2828d5f9
KL
701`-dir DIRNAME'
702 The current working directory of the client process.
703
92071250
KL
704`-current-frame'
705 Forbid the creation of new frames.
706
6afdd335
KL
707`-nowait'
708 Request that the next frame created should not be
709 associated with this client.
710
711`-display DISPLAY'
712 Set the display name to open X frames on.
713
714`-position LINE[:COLUMN]'
715 Go to the given line and column number
716 in the next file opened.
717
718`-file FILENAME'
719 Load the given file in the current frame.
720
721`-eval EXPR'
722 Evaluate EXPR as a Lisp expression and return the
723 result in -print commands.
724
725`-window-system'
726 Open a new X frame.
727
728`-tty DEVICENAME TYPE'
729 Open a new tty frame at the client.
730
6afdd335
KL
731`-suspend'
732 Suspend this tty frame. The client sends this string in
733 response to SIGTSTP and SIGTTOU. The server must cease all I/O
734 on this tty until it gets a -resume command.
735
2828d5f9
KL
736`-resume'
737 Resume this tty frame. The client sends this string when it
738 gets the SIGCONT signal and it is the foreground process on its
739 controlling tty.
740
6afdd335
KL
741`-ignore COMMENT'
742 Do nothing, but put the comment in the server
743 log. Useful for debugging.
744
745
746The following commands are accepted by the client:
747
6afdd335
KL
748`-emacs-pid PID'
749 Describes the process id of the Emacs process;
750 used to forward window change signals to it.
751
752`-window-system-unsupported'
753 Signals that the server does not
754 support creating X frames; the client must try again with a tty
755 frame.
756
757`-print STRING'
758 Print STRING on stdout. Used to send values
759 returned by -eval.
760
761`-error DESCRIPTION'
762 Signal an error (but continue processing).
763
764`-suspend'
765 Suspend this terminal, i.e., stop the client process. Sent
766 when the user presses C-z."
767 (server-log (concat "Received " string) proc)
337e3c70
JB
768 ;; First things first: let's check the authentication
769 (unless (process-get proc :authenticated)
770 (if (and (string-match "-auth \\(.*?\\)\n" string)
974b73e8
KL
771 (equal (match-string 1 string) (process-get proc :auth-key)))
772 (progn
773 (setq string (substring string (match-end 0)))
774 (process-put proc :authenticated t)
775 (server-log "Authentication successful" proc))
337e3c70 776 (server-log "Authentication failed" proc)
974b73e8
KL
777 (server-send-string
778 proc (concat "-error " (server-quote-arg "Authentication failed")))
337e3c70
JB
779 (delete-process proc)
780 ;; We return immediately
781 (return-from server-process-filter)))
3f7ef08e
SM
782 (let ((prev (process-get proc 'previous-string)))
783 (when prev
784 (setq string (concat prev string))
785 (process-put proc 'previous-string nil)))
a9298135 786 (condition-case err
0b0d3e0b 787 (progn
9002956f 788 (server-add-client proc)
13ba3740
SM
789 (if (not (string-match "\n" string))
790 ;; Save for later any partial line that remains.
791 (when (> (length string) 0)
792 (process-put proc 'previous-string string))
793
794 ;; In earlier versions of server.el (where we used an `emacsserver'
795 ;; process), there could be multiple lines. Nowadays this is not
796 ;; supported any more.
797 (assert (eq (match-end 0) (length string)))
0b0d3e0b
KL
798 (let ((request (substring string 0 (match-beginning 0)))
799 (coding-system (and default-enable-multibyte-characters
800 (or file-name-coding-system
801 default-file-name-coding-system)))
9002956f
KL
802 nowait ; t if emacsclient does not want to wait for us.
803 frame ; The frame that was opened for the client (if any).
59e085e0 804 display ; Open the frame on this display.
0b0d3e0b 805 dontkill ; t if the client should not be killed.
13ba3740 806 (commands ())
2828d5f9 807 dir
13ba3740
SM
808 (tty-name nil) ;nil, `window-system', or the tty name.
809 tty-type ;string.
0b0d3e0b
KL
810 (files nil)
811 (lineno 1)
812 (columnno 0))
813 ;; Remove this line from STRING.
814 (setq string (substring string (match-end 0)))
9002956f 815 (while (string-match " *[^ ]* " request)
13ba3740
SM
816 (let ((arg (substring request (match-beginning 0)
817 (1- (match-end 0)))))
0b0d3e0b
KL
818 (setq request (substring request (match-end 0)))
819 (cond
13ba3740
SM
820 ;; -version CLIENT-VERSION: obsolete at birth.
821 ((and (equal "-version" arg) (string-match "[^ ]+ " request))
822 (setq request (substring request (match-end 0))))
0b0d3e0b 823
9002956f 824 ;; -nowait: Emacsclient won't wait for a result.
0b0d3e0b
KL
825 ((equal "-nowait" arg) (setq nowait t))
826
92071250 827 ;; -current-frame: Don't create frames.
13ba3740 828 ((equal "-current-frame" arg) (setq tty-name nil))
92071250 829
9002956f 830 ;; -display DISPLAY:
59e085e0 831 ;; Open X frames on the given display instead of the default.
13ba3740
SM
832 ((and (equal "-display" arg)
833 (string-match "\\([^ ]*\\) " request))
8a3a4fd3
DN
834 ;; Only set `display' if X is supported.
835 ;; Emacsclient cannot know if emacs supports X and
836 ;; it will send -display anyway.
837 (when (memq 'x frame-creation-function-alist)
838 (setq display (match-string 1 request)))
839 (setq request (substring request (match-end 0))))
0b0d3e0b 840
9002956f 841 ;; -window-system: Open a new X frame.
0b0d3e0b 842 ((equal "-window-system" arg)
13ba3740
SM
843 (setq dontkill t)
844 (setq tty-name 'window-system))
9002956f
KL
845
846 ;; -resume: Resume a suspended tty frame.
0b0d3e0b 847 ((equal "-resume" arg)
448f754f 848 (lexical-let ((terminal (process-get proc 'terminal)))
0b0d3e0b 849 (setq dontkill t)
13ba3740
SM
850 (push (lambda ()
851 (when (eq (terminal-live-p terminal) t)
852 (resume-tty terminal)))
853 commands)))
0b0d3e0b 854
9002956f
KL
855 ;; -suspend: Suspend the client's frame. (In case we
856 ;; get out of sync, and a C-z sends a SIGTSTP to
857 ;; emacsclient.)
0b0d3e0b 858 ((equal "-suspend" arg)
448f754f 859 (lexical-let ((terminal (process-get proc 'terminal)))
0b0d3e0b 860 (setq dontkill t)
13ba3740
SM
861 (push (lambda ()
862 (when (eq (terminal-live-p terminal) t)
863 (suspend-tty terminal)))
864 commands)))
0b0d3e0b 865
9002956f
KL
866 ;; -ignore COMMENT: Noop; useful for debugging emacsclient.
867 ;; (The given comment appears in the server log.)
13ba3740 868 ((and (equal "-ignore" arg) (string-match "[^ ]* " request))
0b0d3e0b
KL
869 (setq dontkill t
870 request (substring request (match-end 0))))
871
9002956f 872 ;; -tty DEVICE-NAME TYPE: Open a new tty frame at the client.
13ba3740
SM
873 ((and (equal "-tty" arg)
874 (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
875 (setq tty-name (match-string 1 request))
876 (setq tty-type (match-string 2 request))
877 (setq dontkill t)
878 (setq request (substring request (match-end 0))))
879
880 ;; -position LINE[:COLUMN]: Set point to the given
881 ;; position in the next file.
882 ((and (equal "-position" arg)
883 (string-match "\\+\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)? "
884 request))
b4bb3cbc 885 (setq lineno (string-to-number (match-string 1 request))
13ba3740
SM
886 columnno (if (null (match-end 2)) 0
887 (string-to-number (match-string 2 request)))
4e15f072 888 request (substring request (match-end 0))))
0b0d3e0b 889
9002956f 890 ;; -file FILENAME: Load the given file.
13ba3740
SM
891 ((and (equal "-file" arg)
892 (string-match "\\([^ ]+\\) " request))
0b0d3e0b
KL
893 (let ((file (server-unquote-arg (match-string 1 request))))
894 (setq request (substring request (match-end 0)))
895 (if coding-system
896 (setq file (decode-coding-string file coding-system)))
897 (setq file (command-line-normalize-file-name file))
80a426c2 898 (push (list file lineno columnno) files)
13ba3740
SM
899 (server-log (format "New file: %s (%d:%d)"
900 file lineno columnno) proc))
0b0d3e0b
KL
901 (setq lineno 1
902 columnno 0))
903
9002956f 904 ;; -eval EXPR: Evaluate a Lisp expression.
13ba3740
SM
905 ((and (equal "-eval" arg)
906 (string-match "\\([^ ]+\\) " request))
907 (lexical-let ((expr (server-unquote-arg
908 (match-string 1 request))))
0b0d3e0b
KL
909 (setq request (substring request (match-end 0)))
910 (if coding-system
911 (setq expr (decode-coding-string expr coding-system)))
13ba3740
SM
912 (push (lambda () (server-eval-and-print expr proc))
913 commands)
0b0d3e0b
KL
914 (setq lineno 1
915 columnno 0)))
916
59e085e0
KL
917 ;; -env NAME=VALUE: An environment variable.
918 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request))
919 (let ((var (server-unquote-arg (match-string 1 request))))
da8e8fc1 920 ;; XXX Variables should be encoded as in getenv/setenv.
9002956f 921 (setq request (substring request (match-end 0)))
13ba3740
SM
922 (process-put proc 'env
923 (cons var (process-get proc 'env)))))
9002956f 924
2828d5f9
KL
925 ;; -dir DIRNAME: The cwd of the emacsclient process.
926 ((and (equal "-dir" arg) (string-match "\\([^ ]+\\) " request))
927 (setq dir (server-unquote-arg (match-string 1 request)))
928 (setq request (substring request (match-end 0)))
929 (if coding-system
930 (setq dir (decode-coding-string dir coding-system)))
931 (setq dir (command-line-normalize-file-name dir)))
932
0b0d3e0b
KL
933 ;; Unknown command.
934 (t (error "Unknown command: %s" arg)))))
13ba3740
SM
935
936 (setq frame
937 (case tty-name
938 ((nil) (if display (server-select-display display)))
939 ((window-system)
940 (server-create-window-system-frame display nowait proc))
941 (t (server-create-tty-frame tty-name tty-type proc))))
942
943 (process-put proc 'continuation
944 (lexical-let ((proc proc)
945 (files files)
946 (nowait nowait)
947 (commands commands)
948 (dontkill dontkill)
949 (frame frame)
950 (tty-name tty-name))
951 (lambda ()
952 (server-execute proc files nowait commands
953 dontkill frame tty-name))))
954
955 (when (or frame files)
956 (server-goto-toplevel proc))
957
958 (server-execute-continuation proc))))
a9298135 959 ;; condition-case
13ba3740
SM
960 (error (server-return-error proc err))))
961
962(defun server-execute (proc files nowait commands dontkill frame tty-name)
963 (condition-case err
448f754f 964 (let* ((buffers
13ba3740
SM
965 (when files
966 (run-hooks 'pre-command-hook)
448f754f 967 (prog1 (server-visit-files files proc nowait)
13ba3740
SM
968 (run-hooks 'post-command-hook)))))
969
970 (mapc 'funcall (nreverse commands))
971
972 ;; Delete the client if necessary.
973 (cond
974 (nowait
975 ;; Client requested nowait; return immediately.
976 (server-log "Close nowait client" proc)
977 (server-delete-client proc))
978 ((and (not dontkill) (null buffers))
979 ;; This client is empty; get rid of it immediately.
980 (server-log "Close empty client" proc)
981 (server-delete-client proc)))
982 (cond
983 ((or isearch-mode (minibufferp))
984 nil)
985 ((and frame (null buffers))
986 (message "%s" (substitute-command-keys
987 "When done with this frame, type \\[delete-frame]")))
988 ((not (null buffers))
989 (server-switch-buffer (car buffers))
990 (run-hooks 'server-switch-hook)
991 (unless nowait
992 (message "%s" (substitute-command-keys
993 "When done with a buffer, type \\[server-edit]")))))
994 (when (and frame (null tty-name))
995 (server-unselect-display frame)))
996 (error (server-return-error proc err))))
997
998(defun server-return-error (proc err)
999 (ignore-errors
1000 (server-send-string
1001 proc (concat "-error " (server-quote-arg
1002 (error-message-string err))))
1003 (server-log (error-message-string err) proc)
1004 (delete-process proc)))
9ae0f972 1005
6b98185f 1006(defun server-goto-line-column (file-line-col)
6d3a46f7
KL
1007 "Move point to the position indicated in FILE-LINE-COL.
1008FILE-LINE-COL should be a three-element list as described in
1009`server-visit-files'."
6b98185f
RS
1010 (goto-line (nth 1 file-line-col))
1011 (let ((column-number (nth 2 file-line-col)))
1012 (if (> column-number 0)
1013 (move-to-column (1- column-number)))))
1014
448f754f 1015(defun server-visit-files (files proc &optional nowait)
c5b0a355 1016 "Find FILES and return a list of buffers created.
8c493570 1017FILES is an alist whose elements are (FILENAME LINENUMBER COLUMNNUMBER).
448f754f 1018PROC is the client that requested this operation.
dfa35e6b
RS
1019NOWAIT non-nil means this client is not waiting for the results,
1020so don't mark these buffers specially, just visit them normally."
e82e73c2 1021 ;; Bind last-nonmenu-event to force use of keyboard, not mouse, for queries.
44a56b29 1022 (let ((last-nonmenu-event t) client-record)
3a0ce849
RS
1023 ;; Restore the current buffer afterward, but not using save-excursion,
1024 ;; because we don't want to save point in this buffer
1025 ;; if it happens to be one of those specified by the server.
44a56b29
SM
1026 (save-current-buffer
1027 (dolist (file files)
1028 ;; If there is an existing buffer modified or the file is
1029 ;; modified, revert it. If there is an existing buffer with
1030 ;; deleted file, offer to write it.
cd7320d4 1031 (let* ((minibuffer-auto-raise (or server-raise-frame
974b73e8 1032 minibuffer-auto-raise))
c2d0d432 1033 (filen (car file))
44a56b29 1034 (obuf (get-file-buffer filen)))
c398358a 1035 (add-to-history 'file-name-history filen)
44a56b29
SM
1036 (if (and obuf (set-buffer obuf))
1037 (progn
1038 (cond ((file-exists-p filen)
95eefb35 1039 (when (not (verify-visited-file-modtime obuf))
974b73e8 1040 (revert-buffer t nil)))
44a56b29 1041 (t
95eefb35 1042 (when (y-or-n-p
974b73e8
KL
1043 (concat "File no longer exists: " filen
1044 ", write buffer to file? "))
1045 (write-file filen))))
5f3c1a63
KL
1046 (unless server-buffer-clients
1047 (setq server-existing-buffer t))
44a56b29
SM
1048 (server-goto-line-column file))
1049 (set-buffer (find-file-noselect filen))
1050 (server-goto-line-column file)
1051 (run-hooks 'server-visit-hook)))
1052 (unless nowait
1053 ;; When the buffer is killed, inform the clients.
1054 (add-hook 'kill-buffer-hook 'server-kill-buffer nil t)
448f754f 1055 (push proc server-buffer-clients))
c5b0a355
KL
1056 (push (current-buffer) client-record)))
1057 (unless nowait
448f754f
SM
1058 (process-put proc 'buffers
1059 (nconc (process-get proc 'buffers) client-record)))
c5b0a355 1060 client-record))
9ae0f972 1061\f
b392bac9 1062(defun server-buffer-done (buffer &optional for-killing)
9ae0f972 1063 "Mark BUFFER as \"done\" for its client(s).
9184aafb
RS
1064This buries the buffer, then returns a list of the form (NEXT-BUFFER KILLED).
1065NEXT-BUFFER is another server buffer, as a suggestion for what to select next,
8b3e840e
SM
1066or nil. KILLED is t if we killed BUFFER (typically, because it was visiting
1067a temp file).
1068FOR-KILLING if non-nil indicates that we are called from `kill-buffer'."
0c851d78 1069 (let ((next-buffer nil)
9002956f 1070 (killed nil))
448f754f
SM
1071 (dolist (proc server-clients)
1072 (let ((buffers (process-get proc 'buffers)))
8b3e840e 1073 (or next-buffer
9002956f
KL
1074 (setq next-buffer (nth 1 (memq buffer buffers))))
1075 (when buffers ; Ignore bufferless clients.
1076 (setq buffers (delq buffer buffers))
448f754f 1077 ;; Delete all dead buffers from PROC.
9002956f
KL
1078 (dolist (b buffers)
1079 (and (bufferp b)
1080 (not (buffer-live-p b))
1081 (setq buffers (delq b buffers))))
448f754f 1082 (process-put proc 'buffers buffers)
9002956f
KL
1083 ;; If client now has no pending buffers,
1084 ;; tell it that it is done, and forget it entirely.
1085 (unless buffers
448f754f
SM
1086 (server-log "Close" proc)
1087 (server-delete-client proc)))))
337e3c70
JB
1088 (when (and (bufferp buffer) (buffer-name buffer))
1089 ;; We may or may not kill this buffer;
1090 ;; if we do, do not call server-buffer-done recursively
1091 ;; from kill-buffer-hook.
1092 (let ((server-kill-buffer-running t))
1093 (with-current-buffer buffer
1094 (setq server-buffer-clients nil)
1095 (run-hooks 'server-done-hook))
1096 ;; Notice whether server-done-hook killed the buffer.
1097 (if (null (buffer-name buffer))
1098 (setq killed t)
1099 ;; Don't bother killing or burying the buffer
1100 ;; when we are called from kill-buffer.
1101 (unless for-killing
1102 (when (and (not killed)
1103 server-kill-new-buffers
1104 (with-current-buffer buffer
1105 (not server-existing-buffer)))
599f9a5c 1106 (setq killed t)
337e3c70
JB
1107 (bury-buffer buffer)
1108 (kill-buffer buffer))
1109 (unless killed
1110 (if (server-temp-file-p buffer)
1111 (progn
1112 (kill-buffer buffer)
1113 (setq killed t))
1114 (bury-buffer buffer)))))))
9184aafb 1115 (list next-buffer killed)))
9ae0f972 1116
408784a7 1117(defun server-temp-file-p (&optional buffer)
9ae0f972 1118 "Return non-nil if BUFFER contains a file considered temporary.
1119These are files whose names suggest they are repeatedly
1120reused to pass information to another program.
1121
1122The variable `server-temp-file-regexp' controls which filenames
1123are considered temporary."
1124 (and (buffer-file-name buffer)
1125 (string-match server-temp-file-regexp (buffer-file-name buffer))))
1126
1127(defun server-done ()
cc9875f9 1128 "Offer to save current buffer, mark it as \"done\" for clients.
ed9ae328
RS
1129This kills or buries the buffer, then returns a list
1130of the form (NEXT-BUFFER KILLED). NEXT-BUFFER is another server buffer,
1131as a suggestion for what to select next, or nil.
1132KILLED is t if we killed BUFFER, which happens if it was created
1133specifically for the clients and did not exist before their request for it."
408784a7
SM
1134 (when server-buffer-clients
1135 (if (server-temp-file-p)
1136 ;; For a temp file, save, and do make a non-numeric backup
1137 ;; (unless make-backup-files is nil).
1138 (let ((version-control nil)
1139 (buffer-backed-up nil))
1140 (save-buffer))
337e3c70
JB
1141 (when (and (buffer-modified-p)
1142 buffer-file-name
1143 (y-or-n-p (concat "Save file " buffer-file-name "? ")))
1144 (save-buffer)))
408784a7 1145 (server-buffer-done (current-buffer))))
faf931a8 1146
71207de2
RS
1147;; Ask before killing a server buffer.
1148;; It was suggested to release its client instead,
1149;; but I think that is dangerous--the client would proceed
1150;; using whatever is on disk in that file. -- rms.
03d78665 1151(defun server-kill-buffer-query-function ()
9002956f 1152 "Ask before killing a server buffer."
03d78665 1153 (or (not server-buffer-clients)
114a8b8c
KL
1154 (let ((res t))
1155 (dolist (proc server-buffer-clients res)
448f754f
SM
1156 (when (and (memq proc server-clients)
1157 (eq (process-status proc) 'open))
1158 (setq res nil))))
03d78665
RS
1159 (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
1160 (buffer-name (current-buffer))))))
1161
03d78665 1162(defun server-kill-emacs-query-function ()
7540c1e0 1163 "Ask before exiting Emacs it has live clients."
9002956f
KL
1164 (or (not server-clients)
1165 (let (live-client)
448f754f
SM
1166 (dolist (proc server-clients live-client)
1167 (when (memq t (mapcar 'buffer-live-p (process-get
1168 proc 'buffers)))
974b73e8 1169 (setq live-client t))))
9002956f 1170 (yes-or-no-p "This Emacs session has clients; exit anyway? ")))
b392bac9 1171
fb873cfc 1172(defvar server-kill-buffer-running nil
599f9a5c 1173 "Non-nil while `server-kill-buffer' or `server-buffer-done' is running.")
fb873cfc 1174
b392bac9 1175(defun server-kill-buffer ()
6d3a46f7
KL
1176 "Remove the current buffer from its clients' buffer list.
1177Designed to be added to `kill-buffer-hook'."
fb873cfc
RS
1178 ;; Prevent infinite recursion if user has made server-done-hook
1179 ;; call kill-buffer.
1180 (or server-kill-buffer-running
599f9a5c
RS
1181 (and server-buffer-clients
1182 (let ((server-kill-buffer-running t))
1183 (when server-process
1184 (server-buffer-done (current-buffer) t))))))
9ae0f972 1185\f
1186(defun server-edit (&optional arg)
1187 "Switch to next server editing buffer; say \"Done\" for current buffer.
1188If a server buffer is current, it is marked \"done\" and optionally saved.
ed9ae328 1189The buffer is also killed if it did not exist before the clients asked for it.
9ae0f972 1190When all of a client's buffers are marked as \"done\", the client is notified.
1191
1192Temporary files such as MH <draft> files are always saved and backed up,
991298c3
RS
1193no questions asked. (The variable `make-backup-files', if nil, still
1194inhibits a backup; you can set it locally in a particular buffer to
1195prevent a backup for it.) The variable `server-temp-file-regexp' controls
9ae0f972 1196which filenames are considered temporary.
1197
64f51134 1198If invoked with a prefix argument, or if there is no server process running,
9ae0f972 1199starts server process and that is all. Invoked by \\[server-edit]."
9ae0f972 1200 (interactive "P")
6b519504 1201 (cond
95eefb35
JB
1202 ((or arg
1203 (not server-process)
1204 (memq (process-status server-process) '(signal exit)))
1205 (server-mode 1))
1206 (server-clients (apply 'server-switch-buffer (server-done)))
1207 (t (message "No server editing buffers exist"))))
9ae0f972 1208
98a4349c 1209(defun server-switch-buffer (&optional next-buffer killed-one)
9ae0f972 1210 "Switch to another buffer, preferably one that has a client.
6d3a46f7
KL
1211Arg NEXT-BUFFER is a suggestion; if it is a live buffer, use it.
1212
1213KILLED-ONE is t in a recursive call if we have already killed one
1214temp-file server buffer. This means we should avoid the final
1215\"switch to some other buffer\" since we've already effectively
1216done that."
ca0c7250 1217 (if (null next-buffer)
9002956f
KL
1218 (progn
1219 (let ((rest server-clients))
1220 (while (and rest (not next-buffer))
448f754f 1221 (let ((proc (car rest)))
9002956f 1222 ;; Only look at frameless clients.
448f754f
SM
1223 (when (not (process-get proc 'frame))
1224 (setq next-buffer (car (process-get proc 'buffers))))
9002956f
KL
1225 (setq rest (cdr rest)))))
1226 (and next-buffer (server-switch-buffer next-buffer killed-one))
1227 (unless (or next-buffer killed-one (window-dedicated-p (selected-window)))
1228 ;; (switch-to-buffer (other-buffer))
90ee5627 1229 (message "No server buffers remain to edit")))
9002956f 1230 (if (not (buffer-live-p next-buffer))
ca0c7250 1231 ;; If NEXT-BUFFER is a dead buffer, remove the server records for it
9ae0f972 1232 ;; and try the next surviving server buffer.
ca0c7250
SM
1233 (apply 'server-switch-buffer (server-buffer-done next-buffer))
1234 ;; OK, we know next-buffer is live, let's display and select it.
408784a7
SM
1235 (if (functionp server-window)
1236 (funcall server-window next-buffer)
1237 (let ((win (get-buffer-window next-buffer 0)))
1238 (if (and win (not server-window))
1239 ;; The buffer is already displayed: just reuse the window.
90caccca
JB
1240 (progn
1241 (select-window win)
1242 (set-buffer next-buffer))
408784a7 1243 ;; Otherwise, let's find an appropriate window.
60b4b298 1244 (cond ((window-live-p server-window)
408784a7
SM
1245 (select-window server-window))
1246 ((framep server-window)
337e3c70
JB
1247 (unless (frame-live-p server-window)
1248 (setq server-window (make-frame)))
408784a7 1249 (select-window (frame-selected-window server-window))))
337e3c70
JB
1250 (when (window-minibuffer-p (selected-window))
1251 (select-window (next-window nil 'nomini 0)))
408784a7
SM
1252 ;; Move to a non-dedicated window, if we have one.
1253 (when (window-dedicated-p (selected-window))
1254 (select-window
1255 (get-window-with-predicate
1256 (lambda (w)
1257 (and (not (window-dedicated-p w))
6ed8eeff
KL
1258 (equal (frame-terminal (window-frame w))
1259 (frame-terminal (selected-frame)))))
408784a7
SM
1260 'nomini 'visible (selected-window))))
1261 (condition-case nil
1262 (switch-to-buffer next-buffer)
1263 ;; After all the above, we might still have ended up with
1264 ;; a minibuffer/dedicated-window (if there's no other).
90caccca
JB
1265 (error (pop-to-buffer next-buffer)))))))
1266 (when server-raise-frame
1267 (select-frame-set-input-focus (window-frame (selected-window))))))
9ae0f972 1268
59e085e0 1269;;;###autoload
6ed8eeff 1270(defun server-save-buffers-kill-terminal (proc &optional arg)
59e085e0 1271 "Offer to save each buffer, then kill PROC.
b4ca0271 1272
7540c1e0
KL
1273With prefix arg, silently save all file-visiting buffers, then kill.
1274
1275If emacsclient was started with a list of filenames to edit, then
1276only these files will be asked to be saved."
448f754f 1277 (let ((buffers (process-get proc 'buffers)))
59e085e0
KL
1278 ;; If client is bufferless, emulate a normal Emacs session
1279 ;; exit and offer to save all buffers. Otherwise, offer to
1280 ;; save only the buffers belonging to the client.
1281 (save-some-buffers arg
1282 (if buffers
1283 (lambda () (memq (current-buffer) buffers))
1284 t))
1285 (server-delete-client proc)))
b4ca0271 1286
772c5eb7 1287(define-key ctl-x-map "#" 'server-edit)
df4e8a11
DL
1288
1289(defun server-unload-hook ()
6d3a46f7 1290 "Unload the server library."
2e8457a0 1291 (server-mode -1)
e4019195 1292 (remove-hook 'suspend-tty-functions 'server-handle-suspend-tty)
9002956f 1293 (remove-hook 'delete-frame-functions 'server-handle-delete-frame)
df4e8a11
DL
1294 (remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
1295 (remove-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
1296 (remove-hook 'kill-buffer-hook 'server-kill-buffer))
3bb38bc2 1297
2e8457a0 1298(add-hook 'kill-emacs-hook (lambda () (server-mode -1))) ;Cleanup upon exit.
3bb38bc2 1299(add-hook 'server-unload-hook 'server-unload-hook)
16c15321
RM
1300\f
1301(provide 'server)
c88ab9ce 1302
2e8457a0 1303;; arch-tag: 1f7ecb42-f00a-49f8-906d-61995d84c8d6
c88ab9ce 1304;;; server.el ends here