Entspricht --no-wait für Emacs

8

Das emacsclientProgramm erlaubt ein Flag --no-wait(abgekürzt als -n), das den Emacs-Server veranlasst, die angegebene Datei zu besuchen und sofort zurückzukehren.

emacsclient -n ~/.bashrc

Wenn ich einen alternativen Editor zur Verfügung stelle, funktioniert dies immer noch in Fällen, in denen kein Emacs-Server ausgeführt wird

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

Dies führt jedoch zu einem inkonsistenten Verhalten, da in Fällen, in denen der Server ausgeführt wird, dieser Aufruf sofort zurückgegeben wird. In Fällen, in denen kein Server ausgeführt wird und der alternative Editor verwendet wird, wird der Anruf zu einem blockierenden Anruf und wird erst zurückgegeben, wenn ich Emacs beende.

Gibt es eine Möglichkeit zu sagen emacs(im Gegensatz zu emacsclient), einen neuen Frame zu erstellen und dann zurückzukehren?

Nispio
quelle
1
Es sieht so aus, als würden Sie Emacs als alternativen Editor bereitstellen. Gibt es einen Grund, warum Sie die -a ''Option "Emacs-Daemon starten und Emacsclient erneut versuchen" nicht verwenden möchten?
lila_Pfeile
@purple_arrows Nach meiner Erfahrung wird mit using -a ''ein Daemon anstelle eines Servers gestartet. Dann wird versucht, ein Terminal- Emacs zu öffnen , aber da ich die -nOption bereitgestellt habe , bleibt es nicht geöffnet. Es springt einfach zurück in die Schale.
Nispio

Antworten:

6

Beschreibung

Das Standardverhalten beim Aufrufen von emacsclient ist etwas konservativ. Schauen Sie sich diesen Kommentar von emacsclient.c an :

  /* 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.  */

Aus Ihrer Beschreibung und Ihren Kommentaren geht hervor, dass Sie versuchen, den Emacs-Server bei Bedarf zu starten, während Sie gleichzeitig das -nFlag verwenden. Der Kommentar "zum Beispiel" hier lautet, warum emacsclient -n -a '' FILEnicht das erfüllt wird, wonach Sie suchen, wenn kein Server ausgeführt wird.

  1. Die -a ''Logik startet einen Daemon.
  2. Dann emacsclientsagt ihn einen neuen Terminal Rahmen zu schaffen, denn das ist die Standardeinstellung ist , wenn Sie elisp sind zu bewerten.
  3. Die -nLogik beendet sofort diesen neuen Terminalrahmen.

Wenn Sie Schritt 2 ändern könnten, um standardmäßig einen neuen grafischen Rahmen zu erstellen, emacsclient -n -a '' FILEwürden Sie tun, was Sie wollen.

Elisp-Lösung

Sie können Emacs veranlassen, standardmäßig einen neuen grafischen Rahmen zu erstellen, wenn Sie die Funktion server-process-filterwie folgt empfehlen :

(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"))))

Fügen Sie das dann, wie gesagt, in Ihre Init-Datei ein, emacsclient -n -a '' FILEund Bob ist Ihr Onkel.

Vergleiche mit Shell Solution

Einerseits kann ich auf einige Vorteile der Verwendung dieses Defadvice-Ansatzes im Vergleich zur Verwendung des von Archenoth vorgeschlagenen Skripts hinweisen

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

als alternativer Editor. Mit dem defadvice:

  1. save-buffers-kill-terminal( C-x C-cstandardmäßig) verhält sich über alle Frames hinweg konsistent. Der Emacs-Prozess wird nie abgebrochen, da jeder Frame immer ein Client-Frame ist.
  2. Der Terminalrahmen des Dämons hängt herum. Befehle wie find-grepdiese, die an externe Prozesse gesendet werden, verhalten sich besser, wenn das dumme Terminal vorhanden ist. Zumindest habe ich weniger Kopfschmerzen, die mit dem Entweichen der Muschel zusammenhängen.

Auf der anderen Seite ... ja.

  1. Das Shell-Skript ist sehr einfach.
  2. Das Kommunikationsprotokoll von Emacs wird nicht empfohlen.

Fazit

Vielleicht gibt es einen Kompromiss? Dies ist das Beste, was ich mir vorstellen kann. Sie legen es als Ihren $ EDITOR fest.

#!/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
lila_Pfeile
quelle
Wie kann ich eine Funktion empfehlen, wenn emacs nicht ausgeführt wird?
Nispio
Sie sollten es einfach in der Init-Datei ablegen können. Der Daemon liest diese Datei beim Start und beendet das Lesen, bevor emacsclient Befehle sendet. Zumindest mache ich das so.
lila_Pfeile
4

Ich bin mir nicht sicher, wie ich das innerhalb von Emacs machen soll, aber zum Glück gibt es andere Möglichkeiten, um das zu bekommen, was Sie beschreiben.

Wenn Sie nichts .emacszum Starten eines Servers haben, können Sie jederzeit ein kleines Skript erstellen, das Emacs mit der Datei startet, die Sie bearbeiten möchten, und den Server gegabelt starten.

Etwas wie:

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

Und dann gib das weiter -a.


Allerdings ...
Wenn Sie den Server in Ihrem gestartet haben .emacs, müssen Sie kein Skript erstellen. Sie haben eine etwas knappere Option:

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

Das kaufmännische Und unterstützt den Prozess und gibt Ihnen sofort Ihre Shell zurück, selbst wenn Emacs zum ersten Mal gestartet wird.

Möglicherweise müssen Sie disownden Vorgang ausführen, wenn Bash Jobs beim Beenden beendet. Wenn dies der Fall ist, fügen Sie disownam Ende einfach ein hinzu :

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

Unter Windows wäre das nächste Äquivalent der startBefehl " " ...

Wie im obigen Skriptvorschlag müssten Sie wahrscheinlich eine Batchdatei erstellen, die Folgendes enthält:

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

Und dann das -aArgument darauf richten.
Das sollte die Batch-Datei ausführen und sofort nach dem Start von Emacs mit der entsprechenden Datei zurückkehren.

Archenoth
quelle
Ich bin unter Linux (RHEL 6.5) und &war das erste, was ich versuchte. Leider wird der folgende Text an gesendet stderr: und dann die Klemmenblöcke, die auf das Ende des Prozesses warten: emacsclient: can't find socket; have you started the server? To start the server in Emacs, type "M-x server-start". Ich vermute, dass die emacsclientGabeln in den Hintergrund treten, aber dann wird aufgerufen, emacswas im Vordergrund geöffnet wird.
Nispio
In diesem Fall ist vielleicht ein kleines Skript die beste Route. So etwas wie emacs --eval '(server-start)' $* &vielleicht? Auf diese Weise wird der Server gestartet, Sie erhalten Ihr Terminal und emacsclientverfügen über einen Server , mit dem eine Verbindung hergestellt werden kann.
Archenoth
Ich habe es getestet und zu meiner Antwort hinzugefügt ... Entschuldigung! Ich hatte gedacht, Sie hätten einen Mechanismus zum Starten des Servers, als Sie emacsden normalen Weg liefen . Mir wird klar, dass die meisten Leute diese Konfiguration wahrscheinlich nicht haben würden, also ist das jetzt der erste Teil der Antwort. Ich hoffe es hilft..!
Archenoth
@nispio Setzt Ihren alternativen Editor-Parameter so, dass am Ende ein & steht.
Malabarba
2
@Malabarba Sie können keine Befehlszeilenargumente oder Shell-Anweisungen an den alternativen Editor übergeben, weshalb ich ein kleines Skript vorgeschlagen habe.
Archenoth