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