Tương đương với - không chờ đợi emacs


8

Các emacsclientchương trình cho phép một lá cờ --no-wait(viết tắt là -n) mà sẽ làm cho máy chủ emacs đến thăm một file nào đó, và trở về ngay lập tức.

emacsclient -n ~/.bashrc

Nếu tôi cung cấp một trình soạn thảo thay thế, thì nó vẫn sẽ hoạt động trong trường hợp không có máy chủ Emacs đang chạy

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc

Tuy nhiên, điều này mang lại cho tôi hành vi không nhất quán vì trong trường hợp máy chủ đang chạy, cuộc gọi này sẽ quay lại ngay. Trong trường hợp không có máy chủ đang chạy và trình soạn thảo thay thế được sử dụng, cuộc gọi sẽ trở thành một cuộc gọi chặn và sẽ không quay lại cho đến khi tôi thoát Emacs.

Có cách nào để nói emacs(trái ngược với emacsclient) để tạo một khung mới và sau đó quay lại không?


1
Có vẻ như bạn cảm thấy thoải mái khi cung cấp Emacs làm biên tập viên thay thế. Có lý do nào bạn chọn không sử dụng -a ''tùy chọn "khởi động trình nền Emacs và thử lại emacsclient" không?
màu tím_

@purple_arrows Theo kinh nghiệm của tôi, việc sử dụng -a ''sẽ bắt đầu một trình nền thay vì máy chủ. Sau đó, nó cố gắng mở một thiết bị đầu cuối Emacs, nhưng vì tôi đã cung cấp -ntùy chọn, nó không mở. Nó chỉ bị trả lại ngay ra vỏ.
nispio

Câu trả lời:


6

Sự miêu tả

Hành vi mặc định khi gọi emacsclient là một chút bảo thủ. Kiểm tra nhận xét này từ emacsclient.c :

  /* Unless we are certain we don't want to occupy the tty, send our
     tty information to Emacs.  For example, in daemon mode Emacs may
     need to occupy this tty if no other frame is available.  */

Từ mô tả và nhận xét của bạn, có vẻ như bạn đang cố gắng khởi động máy chủ Emacs theo yêu cầu đồng thời sử dụng -ncờ. Nhận xét "ví dụ" ở đây là lý do tại sao emacsclient -n -a '' FILEkhông thỏa mãn những gì bạn đang tìm kiếm khi không có máy chủ nào đang chạy.

  1. Các -a ''lý khởi động một daemon.
  2. Sau đó emacsclientbảo nó tạo khung đầu cuối mới, vì đó là mặc định trừ khi bạn đánh giá elisp.
  3. Các -nluận ngay lập tức giết chết mà khung nhà ga mới.

Nếu bạn có thể thay đổi Bước 2 để tạo khung đồ họa mới theo mặc định, thì emacsclient -n -a '' FILEsẽ làm những gì bạn muốn.

Giải pháp Elisp

Bạn có thể khiến Emacs tạo khung đồ họa mới theo mặc định nếu bạn tư vấn cho chức năng server-process-filternhư vậy:

(defadvice server-process-filter (before prefer-graphical activate)
  ;; STRING is a sequence of commands sent from emacsclient to the server.
  (when (and
         ;; Check that we're editing a file, as opposed to evaluating elisp.
         (string-match "-file" string)
         ;; Check that there are no frames beyond the Emacs daemon's terminal.
         (daemonp)
         (null (cdr (frame-list)))
         (eq (selected-frame) terminal-frame)
         ;; Check that we have a graphical display.
         ;; `display-graphic-p' doesn't work here.
         (getenv "DISPLAY"))
    (setq string (concat
                  ;; STRING must be all one line, but comes to us
                  ;; newline-terminated.  Strip off the trailing newline.
                  (replace-regexp-in-string "\n$" "" string)
                  ;; Add the commands to create a graphical frame.
                  "-window-system "
                  "-display " (getenv "DISPLAY")
                  ;; Add back the newline.
                  "\n"))))

Đặt nó trong tập tin init của bạn, sau đó, như đã nói, emacsclient -n -a '' FILEvà Bob là chú của bạn.

So sánh với giải pháp Shell

Một mặt, tôi có thể chỉ ra một vài lợi thế khi sử dụng phương pháp tiếp cận khiếm khuyết này so với việc sử dụng tập lệnh được đề xuất bởi Archenoth

#!/bin/bash
emacs --eval '(server-start)' $* &

làm biên tập viên thay thế. Với sự thất bại:

  1. save-buffers-kill-terminal( C-x C-ctheo mặc định) hoạt động nhất quán trên tất cả các khung. Nó không bao giờ giết chết quá trình Emacs, bởi vì mọi khung hình luôn là một khung máy khách.
  2. Khung thiết bị đầu cuối của daemon treo xung quanh. Các lệnh như find-grepvậy bao ra các quy trình bên ngoài hoạt động tốt hơn khi thiết bị đầu cuối câm ở đó. Ít nhất, tôi trải nghiệm ít đau đầu liên quan đến thoát vỏ.

Mặt khác ... vâng.

  1. Kịch bản shell đó là đơn giản đẹp.
  2. Tư vấn giao thức truyền thông của Emacs thì không.

Phần kết luận

Có lẽ có một sự thỏa hiệp? Đây là điều tốt nhất tôi có thể nghĩ ra. Bạn đặt nó là $ EDITOR của bạn.

#!/bin/sh

emacsclient -e "(frames-on-display-list \"${DISPLAY}\")" 1>/dev/null 2>/dev/null
if [ "$?" = "1" ]; then
    emacsclient -c -n -a "" "$@"
else
    emacsclient -n "$@"
fi

Vậy làm thế nào để tôi khuyên một chức năng khi emacs không chạy?
nispio

Bạn có thể chỉ cần thả nó trong tệp init. Trình nền đọc tệp đó khi nó khởi động và kết thúc việc đọc trước khi emacsclient bắt đầu gửi lệnh. Đó là cách tôi đang làm nó, ít nhất.
màu tím_

4

Tôi không chắc chắn làm thế nào để làm điều đó một cách nghiêm ngặt trong Emacs, nhưng may mắn thay, có những cách khác để có được những gì bạn mô tả.

Nếu bạn không có thứ gì đó .emacsđể khởi động máy chủ, bạn luôn có thể tạo một tập lệnh nhỏ khởi động Emacs với tệp bạn muốn chỉnh sửa và khởi động máy chủ rẽ nhánh.

Cái gì đó như:

#!/bin/bash
emacs --eval '(server-start)' $* &

Và sau đó vượt qua nó để -a.


Tuy nhiên ...
Nếu bạn có máy chủ khởi động .emacs, bạn không thực sự cần phải tạo tập lệnh; bạn có một tùy chọn ngắn gọn hơn một chút:

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc &

Dấu và sẽ tạo nền cho quá trình và ngay lập tức trả lại cho bạn vỏ của bạn, ngay cả khi Emacs bắt đầu lần đầu tiên.

Bạn có thể phải disownxử lý nếu bash giết công việc khi thoát. Nếu đó là trường hợp, bạn chỉ cần thêm một disownvào cuối:

emacsclient -n -a "/usr/local/bin/emacs" ~/.bashrc & disown

Trên Windows, tương đương gần nhất sẽ là startlệnh "" ...

Vì vậy, giống như đề xuất tập lệnh ở trên, bạn có thể phải tạo một tệp bó có nội dung như sau:

start /b C:\path\to\emacs %*

Và sau đó chỉ ra -alập luận về nó.
Điều đó sẽ chạy tệp bó và quay lại ngay sau khi khởi động Emacs với tệp thích hợp.


Tôi đang dùng Linux (RHEL 6.5) và &là điều đầu tiên tôi thử. Thật không may, văn bản sau đây được gửi tới stderr: và sau đó các khối thiết bị đầu cuối đang chờ quá trình kết thúc: emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". Tôi đoán rằng các emacsclientnhánh rẽ vào nền, nhưng sau đó nó sẽ emacsmở ra ở phía trước.
nispio

Trong trường hợp đó, có lẽ một kịch bản nhỏ có thể là con đường tốt nhất ..? Một cái gì đó như emacs --eval '(server-start)' $* &có thể? Bằng cách đó, máy chủ bắt đầu, bạn có được thiết bị đầu cuối của mình và emacsclientcó một máy chủ mà nó có thể kết nối.
Archenoth

Tôi đã thử nó và thêm nó vào câu trả lời của tôi ... Xin lỗi về điều đó! Tôi đã hình dung bạn có một cơ chế để khởi động máy chủ khi bạn chạy emacstheo cách thông thường. Tôi nhận ra rằng hầu hết mọi người sẽ không có cấu hình đó, vì vậy đây là phần đầu tiên của câu trả lời. Hy vọng nó giúp..!
Archenoth

@nispio đặt tham số trình chỉnh sửa thay thế của bạn để có & ở cuối.
Malabarba

2
@Malabarba Bạn không thể chuyển các đối số dòng lệnh hoặc chỉ thị shell cho trình soạn thảo thay thế, đó là lý do tại sao tôi đề xuất một tập lệnh nhỏ.
Archenoth
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.