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