Mercurial > emacs
comparison lisp/server.el @ 84600:6cce7d77ef38
(server-with-environment): Simplify.
(server-select-display, server-unselect-display): Re-add functions that
seem to have been lost in the multi-tty merge.
(server-eval-and-print, server-create-tty-frame)
(server-create-window-system-frame, server-goto-toplevel)
(server-execute, server-return-error): New functions extracted from
server-process-filter.
(server-execute-continuation): New functions.
(server-process-filter): Restructure so that all arguments are analysed
first and then acted upon in a subsequent stage This way
server-goto-toplevel can be executed later, when we know if
it's necessary.
Remove the "-version" and "-version-good" support.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Sun, 16 Sep 2007 04:53:39 +0000 |
parents | dab32bc3edc8 |
children | c38a9291ef0a |
comparison
equal
deleted
inserted
replaced
84599:1d3d8782bd49 | 84600:6cce7d77ef38 |
---|---|
267 The environment variables are then restored to their previous values. | 267 The environment variables are then restored to their previous values. |
268 | 268 |
269 VARS should be a list of strings. | 269 VARS should be a list of strings. |
270 ENV should be in the same format as `process-environment'." | 270 ENV should be in the same format as `process-environment'." |
271 (declare (indent 2)) | 271 (declare (indent 2)) |
272 (let ((old-env (make-symbol "old-env")) | 272 (let ((var (make-symbol "var")) |
273 (var (make-symbol "var")) | 273 (value (make-symbol "value"))) |
274 (value (make-symbol "value")) | 274 `(let ((process-environment process-environment)) |
275 (pair (make-symbol "pair"))) | |
276 `(let ((,old-env process-environment)) | |
277 (dolist (,var ,vars) | 275 (dolist (,var ,vars) |
278 (let ((,value (server-getenv-from ,env ,var))) | 276 (let ((,value (server-getenv-from ,env ,var))) |
279 (setq process-environment | 277 (push (if (null ,value) |
280 (cons (if (null ,value) | 278 ,var |
281 ,var | 279 (concat ,var "=" ,value)) |
282 (concat ,var "=" ,value)) | 280 process-environment))) |
283 process-environment)))) | 281 (progn ,@body)))) |
284 (unwind-protect | |
285 (progn ,@body) | |
286 (setq process-environment ,old-env))))) | |
287 | 282 |
288 (defun server-delete-client (client &optional noframe) | 283 (defun server-delete-client (client &optional noframe) |
289 "Delete CLIENT, including its buffers, terminals and frames. | 284 "Delete CLIENT, including its buffers, terminals and frames. |
290 If NOFRAME is non-nil, let the frames live. (To be used from | 285 If NOFRAME is non-nil, let the frames live. (To be used from |
291 `delete-frame-functions'.)" | 286 `delete-frame-functions'.)" |
369 ;; (and (process-contact proc :server) | 364 ;; (and (process-contact proc :server) |
370 ;; (eq (process-status proc) 'closed) | 365 ;; (eq (process-status proc) 'closed) |
371 ;; (ignore-errors (delete-file (process-get proc :server-file)))) | 366 ;; (ignore-errors (delete-file (process-get proc :server-file)))) |
372 (server-log (format "Status changed to %s: %s" (process-status proc) msg) proc) | 367 (server-log (format "Status changed to %s: %s" (process-status proc) msg) proc) |
373 (server-delete-client proc)) | 368 (server-delete-client proc)) |
369 | |
370 (defun server-select-display (display) | |
371 ;; If the current frame is on `display' we're all set. | |
372 (unless (equal (frame-parameter (selected-frame) 'display) display) | |
373 ;; Otherwise, look for an existing frame there and select it. | |
374 (dolist (frame (frame-list)) | |
375 (when (equal (frame-parameter frame 'display) display) | |
376 (select-frame frame))) | |
377 ;; If there's no frame on that display yet, create and select one. | |
378 (unless (equal (frame-parameter (selected-frame) 'display) display) | |
379 (let* ((buffer (generate-new-buffer " *server-dummy*")) | |
380 (frame (make-frame-on-display | |
381 display | |
382 ;; Make it display (and remember) some dummy buffer, so | |
383 ;; we can detect later if the frame is in use or not. | |
384 `((server-dummmy-buffer . ,buffer) | |
385 ;; This frame may be deleted later (see | |
386 ;; server-unselect-display) so we want it to be as | |
387 ;; unobtrusive as possible. | |
388 (visibility . nil))))) | |
389 (select-frame frame) | |
390 (set-window-buffer (selected-window) buffer) | |
391 frame)))) | |
392 | |
393 (defun server-unselect-display (frame) | |
394 (when (frame-live-p frame) | |
395 ;; If the temporary frame is in use (displays something real), make it | |
396 ;; visible. If not (which can happen if the user's customizations call | |
397 ;; pop-to-buffer etc.), delete it to avoid preserving the connection after | |
398 ;; the last real frame is deleted. | |
399 (if (and (eq (frame-first-window frame) | |
400 (next-window (frame-first-window frame) 'nomini)) | |
401 (eq (window-buffer (frame-first-window frame)) | |
402 (frame-parameter frame 'server-dummy-buffer))) | |
403 ;; The temp frame still only shows one buffer, and that is the | |
404 ;; internal temp buffer. | |
405 (delete-frame frame) | |
406 (set-frame-parameter frame 'visibility t)) | |
407 (kill-buffer (frame-parameter frame 'server-dummy-buffer)) | |
408 (set-frame-parameter frame 'server-dummy-buffer nil))) | |
374 | 409 |
375 (defun server-handle-delete-frame (frame) | 410 (defun server-handle-delete-frame (frame) |
376 "Delete the client connection when the emacsclient frame is deleted." | 411 "Delete the client connection when the emacsclient frame is deleted." |
377 (let ((proc (frame-parameter frame 'client))) | 412 (let ((proc (frame-parameter frame 'client))) |
378 (when (and (frame-live-p frame) | 413 (when (and (frame-live-p frame) |
538 :version "22.1" | 573 :version "22.1" |
539 ;; Fixme: Should this check for an existing server socket and do | 574 ;; Fixme: Should this check for an existing server socket and do |
540 ;; nothing if there is one (for multiple Emacs sessions)? | 575 ;; nothing if there is one (for multiple Emacs sessions)? |
541 (server-start (not server-mode))) | 576 (server-start (not server-mode))) |
542 | 577 |
578 (defun server-eval-and-print (expr proc) | |
579 "Eval EXPR and send the result back to client PROC." | |
580 (let ((v (eval (car (read-from-string expr))))) | |
581 (when (and v proc) | |
582 (with-temp-buffer | |
583 (let ((standard-output (current-buffer))) | |
584 (pp v) | |
585 (let ((text (buffer-substring-no-properties | |
586 (point-min) (point-max)))) | |
587 (server-send-string | |
588 proc (format "-print %s\n" | |
589 (server-quote-arg text))))))))) | |
590 | |
591 (defun server-create-tty-frame (tty type proc) | |
592 (let ((frame | |
593 (server-with-environment (process-get proc 'env) | |
594 '("LANG" "LC_CTYPE" "LC_ALL" | |
595 ;; For tgetent(3); list according to ncurses(3). | |
596 "BAUDRATE" "COLUMNS" "ESCDELAY" "HOME" "LINES" | |
597 "NCURSES_ASSUMED_COLORS" "NCURSES_NO_PADDING" | |
598 "NCURSES_NO_SETBUF" "TERM" "TERMCAP" "TERMINFO" | |
599 "TERMINFO_DIRS" "TERMPATH" | |
600 ;; rxvt wants these | |
601 "COLORFGBG" "COLORTERM") | |
602 (make-frame-on-tty tty type | |
603 ;; Ignore nowait here; we always need to | |
604 ;; clean up opened ttys when the client dies. | |
605 `((client . ,proc) | |
606 (environment . ,(process-get proc 'env)))))) | |
607 (client (server-client proc))) | |
608 | |
609 (set-frame-parameter frame 'display-environment-variable | |
610 (server-getenv-from (process-get proc 'env) "DISPLAY")) | |
611 (select-frame frame) | |
612 (server-client-set client 'frame frame) | |
613 (server-client-set client 'tty (terminal-name frame)) | |
614 (server-client-set client 'terminal (frame-terminal frame)) | |
615 | |
616 ;; Display *scratch* by default. | |
617 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | |
618 | |
619 ;; Reply with our pid. | |
620 (server-send-string proc (concat "-emacs-pid " | |
621 (number-to-string (emacs-pid)) "\n")) | |
622 frame)) | |
623 | |
624 (defun server-create-window-system-frame (display nowait proc) | |
625 (if (not (fboundp 'x-create-frame)) | |
626 (progn | |
627 ;; This emacs does not support X. | |
628 (server-log "Window system unsupported" proc) | |
629 (server-send-string proc "-window-system-unsupported \n") | |
630 nil) | |
631 ;; Flag frame as client-created, but use a dummy client. | |
632 ;; This will prevent the frame from being deleted when | |
633 ;; emacsclient quits while also preventing | |
634 ;; `server-save-buffers-kill-terminal' from unexpectedly | |
635 ;; killing emacs on that frame. | |
636 (let* ((params `((client . ,(if nowait 'nowait proc)) | |
637 (environment . ,(process-get proc 'env)))) | |
638 (frame (make-frame-on-display | |
639 (or display | |
640 (frame-parameter nil 'display) | |
641 (getenv "DISPLAY") | |
642 (error "Please specify display")) | |
643 params)) | |
644 (client (server-client proc))) | |
645 (server-log (format "%s created" frame) proc) | |
646 ;; XXX We need to ensure the parameters are | |
647 ;; really set because Emacs forgets unhandled | |
648 ;; initialization parameters for X frames at | |
649 ;; the moment. | |
650 (modify-frame-parameters frame params) | |
651 (set-frame-parameter frame 'display-environment-variable | |
652 (server-getenv-from (process-get proc 'env) "DISPLAY")) | |
653 (select-frame frame) | |
654 (server-client-set client 'frame frame) | |
655 (server-client-set client 'terminal (frame-terminal frame)) | |
656 | |
657 ;; Display *scratch* by default. | |
658 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | |
659 frame))) | |
660 | |
661 | |
662 (defun server-goto-toplevel (proc) | |
663 (condition-case nil | |
664 ;; If we're running isearch, we must abort it to allow Emacs to | |
665 ;; display the buffer and switch to it. | |
666 (dolist (buffer (buffer-list)) | |
667 (with-current-buffer buffer | |
668 (when (bound-and-true-p isearch-mode) | |
669 (isearch-cancel)))) | |
670 ;; Signaled by isearch-cancel. | |
671 (quit (message nil))) | |
672 (when (> (recursion-depth) 0) | |
673 ;; We're inside a minibuffer already, so if the emacs-client is trying | |
674 ;; to open a frame on a new display, we might end up with an unusable | |
675 ;; frame because input from that display will be blocked (until exiting | |
676 ;; the minibuffer). Better exit this minibuffer right away. | |
677 ;; Similarly with recursive-edits such as the splash screen. | |
678 (run-with-timer 0 nil (lexical-let ((proc proc)) | |
679 (lambda () (server-execute-continuation proc)))) | |
680 (top-level))) | |
681 | |
682 ;; We use various special properties on process objects: | |
683 ;; - `env' stores the info about the environment of the emacsclient process. | |
684 ;; - `continuation' is a no-arg function that we need to execute. It contains | |
685 ;; commands we wanted to execute in some earlier invocation of the process | |
686 ;; filter but that we somehow were unable to process at that time | |
687 ;; (e.g. because we first need to throw to the toplevel). | |
688 | |
689 (defun server-execute-continuation (proc) | |
690 (let ((continuation (process-get proc 'continuation))) | |
691 (process-put proc 'continuation nil) | |
692 (if continuation (ignore-errors (funcall continuation))))) | |
693 | |
543 (defun* server-process-filter (proc string) | 694 (defun* server-process-filter (proc string) |
544 "Process a request from the server to edit some files. | 695 "Process a request from the server to edit some files. |
545 PROC is the server process. STRING consists of a sequence of | 696 PROC is the server process. STRING consists of a sequence of |
546 commands prefixed by a dash. Some commands have arguments; these | 697 commands prefixed by a dash. Some commands have arguments; these |
547 are &-quoted and need to be decoded by `server-unquote-arg'. The | 698 are &-quoted and need to be decoded by `server-unquote-arg'. The |
549 | 700 |
550 To illustrate the protocol, here is an example command that | 701 To illustrate the protocol, here is an example command that |
551 emacsclient sends to create a new X frame (note that the whole | 702 emacsclient sends to create a new X frame (note that the whole |
552 sequence is sent on a single line): | 703 sequence is sent on a single line): |
553 | 704 |
554 -version 21.3.50 xterm | |
555 -env HOME /home/lorentey | 705 -env HOME /home/lorentey |
556 -env DISPLAY :0.0 | 706 -env DISPLAY :0.0 |
557 ... lots of other -env commands | 707 ... lots of other -env commands |
558 -display :0.0 | 708 -display :0.0 |
559 -window-system | 709 -window-system |
560 | 710 |
561 The server normally sends back the single command `-good-version' | |
562 as a response. | |
563 | |
564 The following commands are accepted by the server: | 711 The following commands are accepted by the server: |
565 | 712 |
566 `-auth AUTH-STRING' | 713 `-auth AUTH-STRING' |
567 Authenticate the client using the secret authentication string | 714 Authenticate the client using the secret authentication string |
568 AUTH-STRING. | 715 AUTH-STRING. |
569 | |
570 `-version CLIENT-VERSION' | |
571 Check version numbers between server and client, and signal an | |
572 error if there is a mismatch. The server replies with | |
573 `-good-version' to confirm the match. | |
574 | 716 |
575 `-env NAME=VALUE' | 717 `-env NAME=VALUE' |
576 An environment variable on the client side. | 718 An environment variable on the client side. |
577 | 719 |
578 `-dir DIRNAME' | 720 `-dir DIRNAME' |
619 Do nothing, but put the comment in the server | 761 Do nothing, but put the comment in the server |
620 log. Useful for debugging. | 762 log. Useful for debugging. |
621 | 763 |
622 | 764 |
623 The following commands are accepted by the client: | 765 The following commands are accepted by the client: |
624 | |
625 `-good-version' | |
626 Signals a version match between the client and the server. | |
627 | 766 |
628 `-emacs-pid PID' | 767 `-emacs-pid PID' |
629 Describes the process id of the Emacs process; | 768 Describes the process id of the Emacs process; |
630 used to forward window change signals to it. | 769 used to forward window change signals to it. |
631 | 770 |
657 (server-send-string | 796 (server-send-string |
658 proc (concat "-error " (server-quote-arg "Authentication failed"))) | 797 proc (concat "-error " (server-quote-arg "Authentication failed"))) |
659 (delete-process proc) | 798 (delete-process proc) |
660 ;; We return immediately | 799 ;; We return immediately |
661 (return-from server-process-filter))) | 800 (return-from server-process-filter))) |
662 (when (> (recursion-depth) 0) | |
663 ;; We're inside a minibuffer already, so if the emacs-client is trying | |
664 ;; to open a frame on a new display, we might end up with an unusable | |
665 ;; frame because input from that display will be blocked (until exiting | |
666 ;; the minibuffer). Better exit this minibuffer right away. | |
667 ;; Similarly with recursive-edits such as the splash screen. | |
668 (process-put proc :previous-string string) | |
669 (run-with-timer 0 nil (lexical-let ((proc proc)) | |
670 (lambda () (server-process-filter proc "")))) | |
671 (top-level)) | |
672 (condition-case nil | |
673 ;; If we're running isearch, we must abort it to allow Emacs to | |
674 ;; display the buffer and switch to it. | |
675 (mapc #'(lambda (buffer) | |
676 (with-current-buffer buffer | |
677 (when (bound-and-true-p isearch-mode) | |
678 (isearch-cancel)))) | |
679 (buffer-list)) | |
680 ;; Signaled by isearch-cancel | |
681 (quit (message nil))) | |
682 (let ((prev (process-get proc 'previous-string))) | 801 (let ((prev (process-get proc 'previous-string))) |
683 (when prev | 802 (when prev |
684 (setq string (concat prev string)) | 803 (setq string (concat prev string)) |
685 (process-put proc 'previous-string nil))) | 804 (process-put proc 'previous-string nil))) |
686 (condition-case err | 805 (condition-case err |
687 (progn | 806 (progn |
688 (server-add-client proc) | 807 (server-add-client proc) |
689 ;; If the input is multiple lines, | 808 (if (not (string-match "\n" string)) |
690 ;; process each line individually. | 809 ;; Save for later any partial line that remains. |
691 (while (string-match "\n" string) | 810 (when (> (length string) 0) |
811 (process-put proc 'previous-string string)) | |
812 | |
813 ;; In earlier versions of server.el (where we used an `emacsserver' | |
814 ;; process), there could be multiple lines. Nowadays this is not | |
815 ;; supported any more. | |
816 (assert (eq (match-end 0) (length string))) | |
692 (let ((request (substring string 0 (match-beginning 0))) | 817 (let ((request (substring string 0 (match-beginning 0))) |
693 (coding-system (and default-enable-multibyte-characters | 818 (coding-system (and default-enable-multibyte-characters |
694 (or file-name-coding-system | 819 (or file-name-coding-system |
695 default-file-name-coding-system))) | 820 default-file-name-coding-system))) |
696 (client (server-client proc)) | 821 (client (server-client proc)) |
697 current-frame | |
698 nowait ; t if emacsclient does not want to wait for us. | 822 nowait ; t if emacsclient does not want to wait for us. |
699 frame ; The frame that was opened for the client (if any). | 823 frame ; The frame that was opened for the client (if any). |
700 display ; Open the frame on this display. | 824 display ; Open the frame on this display. |
701 dontkill ; t if the client should not be killed. | 825 dontkill ; t if the client should not be killed. |
702 env | 826 (commands ()) |
703 dir | 827 dir |
828 (tty-name nil) ;nil, `window-system', or the tty name. | |
829 tty-type ;string. | |
704 (files nil) | 830 (files nil) |
705 (lineno 1) | 831 (lineno 1) |
706 (columnno 0)) | 832 (columnno 0)) |
707 ;; Remove this line from STRING. | 833 ;; Remove this line from STRING. |
708 (setq string (substring string (match-end 0))) | 834 (setq string (substring string (match-end 0))) |
709 (while (string-match " *[^ ]* " request) | 835 (while (string-match " *[^ ]* " request) |
710 (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) | 836 (let ((arg (substring request (match-beginning 0) |
837 (1- (match-end 0))))) | |
711 (setq request (substring request (match-end 0))) | 838 (setq request (substring request (match-end 0))) |
712 (cond | 839 (cond |
713 ;; -version CLIENT-VERSION: | 840 ;; -version CLIENT-VERSION: obsolete at birth. |
714 ;; Check version numbers, signal an error if there is a mismatch. | 841 ((and (equal "-version" arg) (string-match "[^ ]+ " request)) |
715 ((and (equal "-version" arg) | 842 (setq request (substring request (match-end 0)))) |
716 (string-match "\\([0-9.]+\\) " request)) | |
717 (let* ((client-version (match-string 1 request)) | |
718 (truncated-emacs-version | |
719 (substring emacs-version 0 (length client-version)))) | |
720 (setq request (substring request (match-end 0))) | |
721 (if (equal client-version truncated-emacs-version) | |
722 (progn | |
723 (server-send-string proc "-good-version \n") | |
724 (server-client-set client 'version client-version)) | |
725 (error (concat "Version mismatch: Emacs is " | |
726 truncated-emacs-version | |
727 ", emacsclient is " client-version))))) | |
728 | 843 |
729 ;; -nowait: Emacsclient won't wait for a result. | 844 ;; -nowait: Emacsclient won't wait for a result. |
730 ((equal "-nowait" arg) (setq nowait t)) | 845 ((equal "-nowait" arg) (setq nowait t)) |
731 | 846 |
732 ;; -current-frame: Don't create frames. | 847 ;; -current-frame: Don't create frames. |
733 ((equal "-current-frame" arg) (setq current-frame t)) | 848 ((equal "-current-frame" arg) (setq tty-name nil)) |
734 | 849 |
735 ;; -display DISPLAY: | 850 ;; -display DISPLAY: |
736 ;; Open X frames on the given display instead of the default. | 851 ;; Open X frames on the given display instead of the default. |
737 ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request)) | 852 ((and (equal "-display" arg) |
853 (string-match "\\([^ ]*\\) " request)) | |
738 (setq display (match-string 1 request) | 854 (setq display (match-string 1 request) |
739 request (substring request (match-end 0)))) | 855 request (substring request (match-end 0)))) |
740 | 856 |
741 ;; -window-system: Open a new X frame. | 857 ;; -window-system: Open a new X frame. |
742 ((equal "-window-system" arg) | 858 ((equal "-window-system" arg) |
743 (unless (server-client-get client 'version) | 859 (setq dontkill t) |
744 (error "Protocol error; make sure to use the correct version of emacsclient")) | 860 (setq tty-name 'window-system)) |
745 (unless current-frame | |
746 (if (fboundp 'x-create-frame) | |
747 (let ((params (if nowait | |
748 ;; Flag frame as client-created, but use a dummy client. | |
749 ;; This will prevent the frame from being deleted when | |
750 ;; emacsclient quits while also preventing | |
751 ;; `server-save-buffers-kill-terminal' from unexpectedly | |
752 ;; killing emacs on that frame. | |
753 (list (cons 'client 'nowait) (cons 'environment env)) | |
754 (list (cons 'client proc) (cons 'environment env))))) | |
755 (setq frame (make-frame-on-display | |
756 (or display | |
757 (frame-parameter nil 'display) | |
758 (getenv "DISPLAY") | |
759 (error "Please specify display")) | |
760 params)) | |
761 (server-log (format "%s created" frame) proc) | |
762 ;; XXX We need to ensure the parameters are | |
763 ;; really set because Emacs forgets unhandled | |
764 ;; initialization parameters for X frames at | |
765 ;; the moment. | |
766 (modify-frame-parameters frame params) | |
767 (set-frame-parameter frame 'display-environment-variable | |
768 (server-getenv-from env "DISPLAY")) | |
769 (select-frame frame) | |
770 (server-client-set client 'frame frame) | |
771 (server-client-set client 'terminal (frame-terminal frame)) | |
772 | |
773 ;; Display *scratch* by default. | |
774 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | |
775 | |
776 (setq dontkill t)) | |
777 ;; This emacs does not support X. | |
778 (server-log "Window system unsupported" proc) | |
779 (server-send-string proc "-window-system-unsupported \n") | |
780 (setq dontkill t)))) | |
781 | 861 |
782 ;; -resume: Resume a suspended tty frame. | 862 ;; -resume: Resume a suspended tty frame. |
783 ((equal "-resume" arg) | 863 ((equal "-resume" arg) |
784 (let ((terminal (server-client-get client 'terminal))) | 864 (lexical-let ((terminal (server-client-get client 'terminal))) |
785 (setq dontkill t) | 865 (setq dontkill t) |
786 (when (eq (terminal-live-p terminal) t) | 866 (push (lambda () |
787 (resume-tty terminal)))) | 867 (when (eq (terminal-live-p terminal) t) |
868 (resume-tty terminal))) | |
869 commands))) | |
788 | 870 |
789 ;; -suspend: Suspend the client's frame. (In case we | 871 ;; -suspend: Suspend the client's frame. (In case we |
790 ;; get out of sync, and a C-z sends a SIGTSTP to | 872 ;; get out of sync, and a C-z sends a SIGTSTP to |
791 ;; emacsclient.) | 873 ;; emacsclient.) |
792 ((equal "-suspend" arg) | 874 ((equal "-suspend" arg) |
793 (let ((terminal (server-client-get client 'terminal))) | 875 (lexical-let ((terminal (server-client-get client 'terminal))) |
794 (setq dontkill t) | 876 (setq dontkill t) |
795 (when (eq (terminal-live-p terminal) t) | 877 (push (lambda () |
796 (suspend-tty terminal)))) | 878 (when (eq (terminal-live-p terminal) t) |
879 (suspend-tty terminal))) | |
880 commands))) | |
797 | 881 |
798 ;; -ignore COMMENT: Noop; useful for debugging emacsclient. | 882 ;; -ignore COMMENT: Noop; useful for debugging emacsclient. |
799 ;; (The given comment appears in the server log.) | 883 ;; (The given comment appears in the server log.) |
800 ((and (equal "-ignore" arg) (string-match "\\([^ ]*\\) " request)) | 884 ((and (equal "-ignore" arg) (string-match "[^ ]* " request)) |
801 (setq dontkill t | 885 (setq dontkill t |
802 request (substring request (match-end 0)))) | 886 request (substring request (match-end 0)))) |
803 | 887 |
804 ;; -tty DEVICE-NAME TYPE: Open a new tty frame at the client. | 888 ;; -tty DEVICE-NAME TYPE: Open a new tty frame at the client. |
805 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) | 889 ((and (equal "-tty" arg) |
806 (let ((tty (server-unquote-arg (match-string 1 request))) | 890 (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) |
807 (type (server-unquote-arg (match-string 2 request)))) | 891 (setq tty-name (match-string 1 request)) |
808 (setq request (substring request (match-end 0))) | 892 (setq tty-type (match-string 2 request)) |
809 (unless (server-client-get client 'version) | 893 (setq dontkill t) |
810 (error "Protocol error; make sure you use the correct version of emacsclient")) | 894 (setq request (substring request (match-end 0)))) |
811 (unless current-frame | 895 |
812 (server-with-environment env | 896 ;; -position LINE[:COLUMN]: Set point to the given |
813 '("LANG" "LC_CTYPE" "LC_ALL" | 897 ;; position in the next file. |
814 ;; For tgetent(3); list according to ncurses(3). | 898 ((and (equal "-position" arg) |
815 "BAUDRATE" "COLUMNS" "ESCDELAY" "HOME" "LINES" | 899 (string-match "\\+\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)? " |
816 "NCURSES_ASSUMED_COLORS" "NCURSES_NO_PADDING" | 900 request)) |
817 "NCURSES_NO_SETBUF" "TERM" "TERMCAP" "TERMINFO" | 901 (setq lineno (string-to-number (match-string 1 request)) |
818 "TERMINFO_DIRS" "TERMPATH" | 902 columnno (if (null (match-end 2)) 0 |
819 ;; rxvt wants these | 903 (string-to-number (match-string 2 request))) |
820 "COLORFGBG" "COLORTERM") | |
821 (setq frame (make-frame-on-tty tty type | |
822 ;; Ignore nowait here; we always need to clean | |
823 ;; up opened ttys when the client dies. | |
824 `((client . ,proc) | |
825 (environment . ,env))))) | |
826 | |
827 (set-frame-parameter frame 'display-environment-variable | |
828 (server-getenv-from env "DISPLAY")) | |
829 (select-frame frame) | |
830 (server-client-set client 'frame frame) | |
831 (server-client-set client 'tty (terminal-name frame)) | |
832 (server-client-set client 'terminal (frame-terminal frame)) | |
833 | |
834 ;; Display *scratch* by default. | |
835 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord) | |
836 | |
837 ;; Reply with our pid. | |
838 (server-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) | |
839 (setq dontkill t)))) | |
840 | |
841 ;; -position LINE: Go to the given line in the next file. | |
842 ((and (equal "-position" arg) (string-match "\\(\\+[0-9]+\\) " request)) | |
843 (setq lineno (string-to-number (substring (match-string 1 request) 1)) | |
844 request (substring request (match-end 0)))) | 904 request (substring request (match-end 0)))) |
845 | 905 |
846 ;; -position LINE:COLUMN: Set point to the given position in the next file. | |
847 ((and (equal "-position" arg) (string-match "\\+\\([0-9]+\\):\\([0-9]+\\) " request)) | |
848 (setq lineno (string-to-number (match-string 1 request)) | |
849 columnno (string-to-number (match-string 2 request)) | |
850 request (substring request (match-end 0)))) | |
851 | |
852 ;; -file FILENAME: Load the given file. | 906 ;; -file FILENAME: Load the given file. |
853 ((and (equal "-file" arg) (string-match "\\([^ ]+\\) " request)) | 907 ((and (equal "-file" arg) |
908 (string-match "\\([^ ]+\\) " request)) | |
854 (let ((file (server-unquote-arg (match-string 1 request)))) | 909 (let ((file (server-unquote-arg (match-string 1 request)))) |
855 (setq request (substring request (match-end 0))) | 910 (setq request (substring request (match-end 0))) |
856 (if coding-system | 911 (if coding-system |
857 (setq file (decode-coding-string file coding-system))) | 912 (setq file (decode-coding-string file coding-system))) |
858 (setq file (command-line-normalize-file-name file)) | 913 (setq file (command-line-normalize-file-name file)) |
859 (push (list file lineno columnno) files) | 914 (push (list file lineno columnno) files) |
860 (server-log (format "New file: %s (%d:%d)" file lineno columnno) proc)) | 915 (server-log (format "New file: %s (%d:%d)" |
916 file lineno columnno) proc)) | |
861 (setq lineno 1 | 917 (setq lineno 1 |
862 columnno 0)) | 918 columnno 0)) |
863 | 919 |
864 ;; -eval EXPR: Evaluate a Lisp expression. | 920 ;; -eval EXPR: Evaluate a Lisp expression. |
865 ((and (equal "-eval" arg) (string-match "\\([^ ]+\\) " request)) | 921 ((and (equal "-eval" arg) |
866 (let ((expr (server-unquote-arg (match-string 1 request)))) | 922 (string-match "\\([^ ]+\\) " request)) |
923 (lexical-let ((expr (server-unquote-arg | |
924 (match-string 1 request)))) | |
867 (setq request (substring request (match-end 0))) | 925 (setq request (substring request (match-end 0))) |
868 (if coding-system | 926 (if coding-system |
869 (setq expr (decode-coding-string expr coding-system))) | 927 (setq expr (decode-coding-string expr coding-system))) |
870 (let ((v (eval (car (read-from-string expr))))) | 928 (push (lambda () (server-eval-and-print expr proc)) |
871 (when (and (not frame) v) | 929 commands) |
872 (with-temp-buffer | |
873 (let ((standard-output (current-buffer))) | |
874 (pp v) | |
875 (server-send-string | |
876 proc (format "-print %s\n" | |
877 (server-quote-arg | |
878 (buffer-substring-no-properties (point-min) | |
879 (point-max))))))))) | |
880 (setq lineno 1 | 930 (setq lineno 1 |
881 columnno 0))) | 931 columnno 0))) |
882 | 932 |
883 ;; -env NAME=VALUE: An environment variable. | 933 ;; -env NAME=VALUE: An environment variable. |
884 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request)) | 934 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request)) |
885 (let ((var (server-unquote-arg (match-string 1 request)))) | 935 (let ((var (server-unquote-arg (match-string 1 request)))) |
886 ;; XXX Variables should be encoded as in getenv/setenv. | 936 ;; XXX Variables should be encoded as in getenv/setenv. |
887 (setq request (substring request (match-end 0))) | 937 (setq request (substring request (match-end 0))) |
888 (setq env (cons var env)))) | 938 (process-put proc 'env |
939 (cons var (process-get proc 'env))))) | |
889 | 940 |
890 ;; -dir DIRNAME: The cwd of the emacsclient process. | 941 ;; -dir DIRNAME: The cwd of the emacsclient process. |
891 ((and (equal "-dir" arg) (string-match "\\([^ ]+\\) " request)) | 942 ((and (equal "-dir" arg) (string-match "\\([^ ]+\\) " request)) |
892 (setq dir (server-unquote-arg (match-string 1 request))) | 943 (setq dir (server-unquote-arg (match-string 1 request))) |
893 (setq request (substring request (match-end 0))) | 944 (setq request (substring request (match-end 0))) |
895 (setq dir (decode-coding-string dir coding-system))) | 946 (setq dir (decode-coding-string dir coding-system))) |
896 (setq dir (command-line-normalize-file-name dir))) | 947 (setq dir (command-line-normalize-file-name dir))) |
897 | 948 |
898 ;; Unknown command. | 949 ;; Unknown command. |
899 (t (error "Unknown command: %s" arg))))) | 950 (t (error "Unknown command: %s" arg))))) |
900 | 951 |
901 (let (buffers) | 952 (setq frame |
902 (when files | 953 (case tty-name |
903 (run-hooks 'pre-command-hook) | 954 ((nil) (if display (server-select-display display))) |
904 (setq buffers (server-visit-files files client nowait)) | 955 ((window-system) |
905 (run-hooks 'post-command-hook)) | 956 (server-create-window-system-frame display nowait proc)) |
906 | 957 (t (server-create-tty-frame tty-name tty-type proc)))) |
907 ;; Delete the client if necessary. | 958 |
908 (cond | 959 (process-put proc 'continuation |
909 (nowait | 960 (lexical-let ((proc proc) |
910 ;; Client requested nowait; return immediately. | 961 (files files) |
911 (server-log "Close nowait client" proc) | 962 (nowait nowait) |
912 (server-delete-client proc)) | 963 (commands commands) |
913 ((and (not dontkill) (null buffers)) | 964 (dontkill dontkill) |
914 ;; This client is empty; get rid of it immediately. | 965 (frame frame) |
915 (server-log "Close empty client" proc) | 966 (tty-name tty-name)) |
916 (server-delete-client proc))) | 967 (lambda () |
917 (cond | 968 (server-execute proc files nowait commands |
918 ((or isearch-mode (minibufferp)) | 969 dontkill frame tty-name)))) |
919 nil) | 970 |
920 ((and frame (null buffers)) | 971 (when (or frame files) |
921 (message "%s" (substitute-command-keys | 972 (server-goto-toplevel proc)) |
922 "When done with this frame, type \\[delete-frame]"))) | 973 |
923 ((not (null buffers)) | 974 (server-execute-continuation proc)))) |
924 (server-switch-buffer (car buffers)) | |
925 (run-hooks 'server-switch-hook) | |
926 (unless nowait | |
927 (message "%s" (substitute-command-keys | |
928 "When done with a buffer, type \\[server-edit]")))))))) | |
929 | |
930 ;; Save for later any partial line that remains. | |
931 (when (> (length string) 0) | |
932 (process-put proc 'previous-string string))) | |
933 ;; condition-case | 975 ;; condition-case |
934 (error (ignore-errors | 976 (error (server-return-error proc err)))) |
935 (server-send-string | 977 |
936 proc (concat "-error " (server-quote-arg (error-message-string err)))) | 978 (defun server-execute (proc files nowait commands dontkill frame tty-name) |
937 (setq string "") | 979 (condition-case err |
938 (server-log (error-message-string err) proc) | 980 (let* ((client (server-client proc)) |
939 (delete-process proc))))) | 981 (buffers |
982 (when files | |
983 (run-hooks 'pre-command-hook) | |
984 (prog1 (server-visit-files files client nowait) | |
985 (run-hooks 'post-command-hook))))) | |
986 | |
987 (mapc 'funcall (nreverse commands)) | |
988 | |
989 ;; Delete the client if necessary. | |
990 (cond | |
991 (nowait | |
992 ;; Client requested nowait; return immediately. | |
993 (server-log "Close nowait client" proc) | |
994 (server-delete-client proc)) | |
995 ((and (not dontkill) (null buffers)) | |
996 ;; This client is empty; get rid of it immediately. | |
997 (server-log "Close empty client" proc) | |
998 (server-delete-client proc))) | |
999 (cond | |
1000 ((or isearch-mode (minibufferp)) | |
1001 nil) | |
1002 ((and frame (null buffers)) | |
1003 (message "%s" (substitute-command-keys | |
1004 "When done with this frame, type \\[delete-frame]"))) | |
1005 ((not (null buffers)) | |
1006 (server-switch-buffer (car buffers)) | |
1007 (run-hooks 'server-switch-hook) | |
1008 (unless nowait | |
1009 (message "%s" (substitute-command-keys | |
1010 "When done with a buffer, type \\[server-edit]"))))) | |
1011 (when (and frame (null tty-name)) | |
1012 (server-unselect-display frame))) | |
1013 (error (server-return-error proc err)))) | |
1014 | |
1015 (defun server-return-error (proc err) | |
1016 (ignore-errors | |
1017 (server-send-string | |
1018 proc (concat "-error " (server-quote-arg | |
1019 (error-message-string err)))) | |
1020 (server-log (error-message-string err) proc) | |
1021 (delete-process proc))) | |
940 | 1022 |
941 (defun server-goto-line-column (file-line-col) | 1023 (defun server-goto-line-column (file-line-col) |
942 "Move point to the position indicated in FILE-LINE-COL. | 1024 "Move point to the position indicated in FILE-LINE-COL. |
943 FILE-LINE-COL should be a three-element list as described in | 1025 FILE-LINE-COL should be a three-element list as described in |
944 `server-visit-files'." | 1026 `server-visit-files'." |