Mercurial > emacs
comparison lisp/server.el @ 83044:52039abab942
Verify the version of Emacsclient.
lib-src/emacsclient.c (main): Send the version number of emacsclient
to the Emacs process, and exit with error if Emacs does not accept it.
lisp/server.el (server-with-errors-reported): Removed.
(server-process-filter): Cleaned up error handling.
Compare the version of emacsclient with emacs-version;
signal an error if they do not match.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-84
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Fri, 20 Feb 2004 01:22:10 +0000 |
parents | 78a785f205ea |
children | a871be7b26a5 |
comparison
equal
deleted
inserted
replaced
83043:78a785f205ea | 83044:52039abab942 |
---|---|
347 :version "21.4" | 347 :version "21.4" |
348 ;; Fixme: Should this check for an existing server socket and do | 348 ;; Fixme: Should this check for an existing server socket and do |
349 ;; nothing if there is one (for multiple Emacs sessions)? | 349 ;; nothing if there is one (for multiple Emacs sessions)? |
350 (server-start (not server-mode))) | 350 (server-start (not server-mode))) |
351 | 351 |
352 (defmacro server-with-errors-reported (&rest forms) | |
353 "Evaluate FORMS; if an error occurs, report it to the client | |
354 and return nil. Otherwise, return the result of the last form. | |
355 For use in server-process-filter only." | |
356 `(condition-case err | |
357 (progn ,@forms) | |
358 (error (ignore-errors | |
359 (process-send-string | |
360 proc (concat "-error " (error-message-string err))) | |
361 (setq request ""))))) | |
362 | |
363 (defun server-process-filter (proc string) | 352 (defun server-process-filter (proc string) |
364 "Process a request from the server to edit some files. | 353 "Process a request from the server to edit some files. |
365 PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"." | 354 PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"." |
366 (server-log string proc) | 355 (server-log string proc) |
367 (let ((prev (process-get proc 'previous-string))) | 356 (let ((prev (process-get proc 'previous-string))) |
368 (when prev | 357 (when prev |
369 (setq string (concat prev string)) | 358 (setq string (concat prev string)) |
370 (process-put proc 'previous-string nil))) | 359 (process-put proc 'previous-string nil))) |
371 ;; If the input is multiple lines, | 360 (condition-case err |
372 ;; process each line individually. | 361 ;; If the input is multiple lines, |
373 (while (string-match "\n" string) | 362 ;; process each line individually. |
374 (let ((request (substring string 0 (match-beginning 0))) | 363 (while (string-match "\n" string) |
375 (coding-system (and default-enable-multibyte-characters | 364 (let ((request (substring string 0 (match-beginning 0))) |
376 (or file-name-coding-system | 365 (coding-system (and default-enable-multibyte-characters |
377 default-file-name-coding-system))) | 366 (or file-name-coding-system |
378 client nowait eval newframe display | 367 default-file-name-coding-system))) |
379 registered ; t if the client is already added to server-clients. | 368 client nowait eval newframe display version-checked |
380 (files nil) | 369 registered ; t if the client is already added to server-clients. |
381 (lineno 1) | 370 (files nil) |
382 (columnno 0)) | 371 (lineno 1) |
383 ;; Remove this line from STRING. | 372 (columnno 0)) |
384 (setq string (substring string (match-end 0))) | 373 ;; Remove this line from STRING. |
385 (setq client (cons proc nil)) | 374 (setq string (substring string (match-end 0))) |
386 (while (string-match "[^ ]* " request) | 375 (setq client (cons proc nil)) |
387 (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) | 376 (while (string-match "[^ ]* " request) |
388 (setq request (substring request (match-end 0))) | 377 (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) |
389 (cond | |
390 ((equal "-nowait" arg) (setq nowait t)) | |
391 ((equal "-eval" arg) (setq eval t)) | |
392 | |
393 ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request)) | |
394 (setq display (match-string 1 request) | |
395 request (substring request (match-end 0)))) | |
396 | |
397 ;; Open a new X frame. | |
398 ((equal "-window-system" arg) | |
399 (server-with-errors-reported | |
400 (let ((frame (make-frame-on-display | |
401 (or display | |
402 (frame-parameter nil 'display) | |
403 (getenv "DISPLAY") | |
404 (error "Please specify display"))))) | |
405 (push (list proc frame) server-frames) | |
406 (select-frame frame) | |
407 ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right. | |
408 (push client server-clients) | |
409 (setq registered t | |
410 newframe t)))) | |
411 | |
412 ;; Open a new tty frame at the client. ARG is the name of the pseudo tty. | |
413 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) | |
414 (let ((tty (server-unquote-arg (match-string 1 request))) | |
415 (type (server-unquote-arg (match-string 2 request)))) | |
416 (setq request (substring request (match-end 0))) | 378 (setq request (substring request (match-end 0))) |
417 (server-with-errors-reported | 379 (cond |
418 (let ((frame (make-frame-on-tty tty type))) | 380 ;; Check version numbers. |
419 (push (list (car client) (frame-tty-name frame)) server-ttys) | 381 ((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request)) |
420 (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) | 382 (let* ((client-version (match-string 1 request)) |
421 (select-frame frame) | 383 (truncated-emacs-version (substring emacs-version 0 (length client-version)))) |
422 ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. | 384 (setq request (substring request (match-end 0))) |
423 (push client server-clients) | 385 (if (equal client-version truncated-emacs-version) |
424 (setq registered t | 386 (progn |
425 newframe t))))) | 387 (process-send-string proc "-good-version \n") |
426 | 388 (setq version-checked t)) |
427 ;; ARG is a line number option. | 389 (error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version))))) |
428 ((string-match "\\`\\+[0-9]+\\'" arg) | 390 |
429 (setq lineno (string-to-int (substring arg 1)))) | 391 ((equal "-nowait" arg) (setq nowait t)) |
430 | 392 ((equal "-eval" arg) (setq eval t)) |
431 ;; ARG is line number:column option. | 393 |
432 ((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg) | 394 ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request)) |
433 (setq lineno (string-to-int (match-string 1 arg)) | 395 (setq display (match-string 1 request) |
434 columnno (string-to-int (match-string 2 arg)))) | 396 request (substring request (match-end 0)))) |
435 | 397 |
436 ;; ARG is a filename or a Lisp expression. | 398 ;; Open a new X frame. |
437 (t | 399 ((equal "-window-system" arg) |
438 | 400 (unless version-checked |
439 ;; Undo the quoting that emacsclient does | 401 (error "Protocol error; make sure to use the correct version of emacsclient")) |
440 ;; for certain special characters. | 402 (let ((frame (make-frame-on-display |
441 (setq arg (server-unquote-arg arg)) | 403 (or display |
442 ;; Now decode the file name if necessary. | 404 (frame-parameter nil 'display) |
443 (if coding-system | 405 (getenv "DISPLAY") |
444 (setq arg (decode-coding-string arg coding-system))) | 406 (error "Please specify display"))))) |
445 (if eval | 407 (push (list proc frame) server-frames) |
446 (server-with-errors-reported | 408 (select-frame frame) |
447 (let ((v (eval (car (read-from-string arg))))) | 409 ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right. |
448 (when (and (not newframe) v) | 410 (push client server-clients) |
449 (with-temp-buffer | 411 (setq registered t |
450 (let ((standard-output (current-buffer))) | 412 newframe t))) |
451 (pp v) | 413 |
452 (process-send-string proc "-print ") | 414 ;; Open a new tty frame at the client. ARG is the name of the pseudo tty. |
453 (process-send-region proc (point-min) (point-max))))))) | 415 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) |
454 | 416 (let ((tty (server-unquote-arg (match-string 1 request))) |
455 ;; ARG is a file name. | 417 (type (server-unquote-arg (match-string 2 request)))) |
456 ;; Collapse multiple slashes to single slashes. | 418 (setq request (substring request (match-end 0))) |
457 (setq arg (command-line-normalize-file-name arg)) | 419 (unless version-checked |
458 (push (list arg lineno columnno) files)) | 420 (error "Protocol error; make sure to use the correct version of emacsclient")) |
459 (setq lineno 1) | 421 (let ((frame (make-frame-on-tty tty type))) |
460 (setq columnno 0))))) | 422 (push (list (car client) (frame-tty-name frame)) server-ttys) |
461 | 423 (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) |
462 (when files | 424 (select-frame frame) |
463 (run-hooks 'pre-command-hook) | 425 ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. |
464 (server-visit-files files client nowait) | 426 (push client server-clients) |
465 (run-hooks 'post-command-hook)) | 427 (setq registered t |
466 ;; CLIENT is now a list (CLIENTNUM BUFFERS...) | 428 newframe t)))) |
467 (if (and (not newframe) (null (cdr client))) | 429 |
468 ;; This client is empty; get rid of it immediately. | 430 ;; ARG is a line number option. |
469 (progn | 431 ((string-match "\\`\\+[0-9]+\\'" arg) |
470 (delete-process proc) | 432 (setq lineno (string-to-int (substring arg 1)))) |
471 (server-log "Close empty client" proc)) | 433 |
472 ;; We visited some buffer for this client. | 434 ;; ARG is line number:column option. |
473 (or nowait registered (push client server-clients)) | 435 ((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg) |
474 (unless (or isearch-mode (minibufferp)) | 436 (setq lineno (string-to-int (match-string 1 arg)) |
475 (if (and newframe (null (cdr client))) | 437 columnno (string-to-int (match-string 2 arg)))) |
476 (message (substitute-command-keys | 438 |
477 "When done with this frame, type \\[delete-frame]")) | 439 ;; ARG is a filename or a Lisp expression. |
478 (server-switch-buffer (nth 1 client)) | 440 (t |
479 (run-hooks 'server-switch-hook) | 441 ;; Undo the quoting that emacsclient does |
480 (unless nowait | 442 ;; for certain special characters. |
481 (message (substitute-command-keys | 443 (setq arg (server-unquote-arg arg)) |
482 "When done with a buffer, type \\[server-edit]")))))))) | 444 ;; Now decode the file name if necessary. |
483 ;; Save for later any partial line that remains. | 445 (if coding-system |
484 (when (> (length string) 0) | 446 (setq arg (decode-coding-string arg coding-system))) |
485 (process-put proc 'previous-string string))) | 447 (unless version-checked |
448 (error "Protocol error; make sure to use the correct version of emacsclient")) | |
449 (if eval | |
450 ;; ARG is a Lisp expression. | |
451 (let ((v (eval (car (read-from-string arg))))) | |
452 (when (and (not newframe) v) | |
453 (with-temp-buffer | |
454 (let ((standard-output (current-buffer))) | |
455 (pp v) | |
456 (process-send-string proc "-print ") | |
457 (process-send-region proc (point-min) (point-max)))))) | |
458 ;; ARG is a file name. | |
459 ;; Collapse multiple slashes to single slashes. | |
460 (setq arg (command-line-normalize-file-name arg)) | |
461 (push (list arg lineno columnno) files)) | |
462 (setq lineno 1) | |
463 (setq columnno 0))))) | |
464 | |
465 (if (not version-checked) | |
466 (error "Protocol error; make sure to use the correct version of emacsclient") | |
467 (when files | |
468 (run-hooks 'pre-command-hook) | |
469 (server-visit-files files client nowait) | |
470 (run-hooks 'post-command-hook)) | |
471 ;; CLIENT is now a list (CLIENTNUM BUFFERS...) | |
472 (if (and (not newframe) (null (cdr client))) | |
473 ;; This client is empty; get rid of it immediately. | |
474 (progn | |
475 (delete-process proc) | |
476 (server-log "Close empty client" proc)) | |
477 ;; We visited some buffer for this client. | |
478 (or nowait registered (push client server-clients)) | |
479 (unless (or isearch-mode (minibufferp)) | |
480 (if (and newframe (null (cdr client))) | |
481 (message (substitute-command-keys | |
482 "When done with this frame, type \\[delete-frame]")) | |
483 (server-switch-buffer (nth 1 client)) | |
484 (run-hooks 'server-switch-hook) | |
485 (unless nowait | |
486 (message (substitute-command-keys | |
487 "When done with a buffer, type \\[server-edit]")))))))) | |
488 ;; Save for later any partial line that remains. | |
489 (when (> (length string) 0) | |
490 (process-put proc 'previous-string string))) | |
491 ;; condition-case | |
492 (error (ignore-errors | |
493 (process-send-string | |
494 proc (concat "-error " (error-message-string err))) | |
495 (setq string "") | |
496 (server-log (error-message-string err) proc) | |
497 (delete-process proc))))) | |
486 | 498 |
487 (defun server-goto-line-column (file-line-col) | 499 (defun server-goto-line-column (file-line-col) |
488 (goto-line (nth 1 file-line-col)) | 500 (goto-line (nth 1 file-line-col)) |
489 (let ((column-number (nth 2 file-line-col))) | 501 (let ((column-number (nth 2 file-line-col))) |
490 (if (> column-number 0) | 502 (if (> column-number 0) |