Wie erstelle ich Emacs Lesepuffer von stdin beim Start?

40

Mit Vim kann ich das leicht machen

$ echo 123 | vim -

Kann man das mit Emacs machen?

$ echo 123 | emacs23
... Emacs starts with a Welcome message

$ echo 123 | emacs23 -
... Emacs starts with an empty *scratch* buffer and “Unknown option”

$ echo 123 | emacs23 --insert -
... “No such file or directory”, empty *scratch* buffer

Ist es wirklich unmöglich, einen Puffer aus einer Unix-Pipe zu lesen?

Bearbeiten : Als Lösung schrieb ich einen Shell-Wrapper mit dem Namen emacspipe:

#!/bin/sh
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
Sastanin
quelle

Antworten:

15

Richtig, es ist unmöglich, einen Puffer von stdin zu lesen.

Die einzige Erwähnung in den Emacs Informationsseite stdin ist dies , das sagt:

Im Batch-Modus zeigt Emacs den zu bearbeitenden Text nicht an und die Standard-Terminal-Interrupt-Zeichen wie C-zund haben C-cweiterhin ihre normale Wirkung. Die Funktionen prin1, princund print Ausgang stdoutstatt des Echobereich, während messageund Fehlermeldungen ausgegeben zu stderr. Funktionen, die normalerweise aus dem Minipuffer gelesen werden, erhalten stattdessen ihre Eingabe von stdin.

Und die readFunktion kann lesen stdin, aber nur im Batch-Modus.

Sie können dies also nicht einmal umgehen, indem Sie benutzerdefiniertes elisp schreiben.

Trey Jackson
quelle
10
Ich meine keine Respektlosigkeit gegenüber irgendjemandem, aber das ist abscheulich. Dies ist eine sehr grundlegende Editorfunktion, und GNU EMACS gibt es schon seit Jahrzehnten. Es sollte eingebaut sein.
user787832
35

Sie können die Prozessersetzung verwenden :

$ emacs --insert <(echo 123)
Andrew Wood
quelle
Dies ist definitiv die Antwort, die der Vim-Funktionalität am nächsten kommt. Ziemlich einfach das Pipe-Teil in eine Teilprozessersetzung verschieben.
Dbmikus
@ Dbmikus Ich kann mich nicht entscheiden, was ich zwischen mir und Tomasz Obrębski bevorzugen ..
Andrew Wood
emacs: standard input is not a tty
Tomaszs
Oh ja! Ich nahm an, dass er vor dem Posten getestet hatte.
Andrew Wood
1
Vielleicht kommt es auf den Monat an.
Dbmikus
14

Sie können zu einer Datei umleiten und diese dann öffnen. z.B

echo 123 > temp; emacs temp

jweede stellt fest, dass Sie, wenn die temporäre Datei automatisch entfernt werden soll, Folgendes tun können:

echo 123 > temp; emacs temp; rm temp

Die Emacsy-Methode hierfür besteht darin, den Shell-Befehl in Emacs auszuführen .

M-! echo 123 RET

Das gibt Ihnen einen Puffer mit dem Namen * Shell Command Output * mit den Ergebnissen des Befehls.

Richard Hoskins
quelle
Ja, ich weiß, dass es einen emaksen Weg gibt, aber ich hoffte, dass er auf unixige Weise verwendet werden kann. Das Erstellen einer temporären Datei ist keine sehr gute Option (ich muss daran denken, sie später zu löschen).
Sastanin
1
wie zum Beispiel:echo 123 > temp; emacs temp; rm temp
jweede
2
Im Allgemeinen besteht zwischen Emacs und Unix eine hohe Impedanz. Oder zumindest zwischen Emacs und dem traditionellen Unix-Arbeitsablauf.
Richard Hoskins
2
@jweede Wenn Sie M- hinzufügen möchten! Teil meiner Antwort auf Ihre, dann könnte ich meine Antwort löschen. Es gibt eine große Überschneidung in unseren Antworten, aber ich denke, Meta-Bang ist wichtig für zukünftige Leser.
Richard Hoskins
1
temp ist möglicherweise bereits im aktuellen Verzeichnis vorhanden. Es ist nicht sicher. als Lösung, schrieb ich einen Wrapper: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Danke an alle!
Sastanin
9

Es ist möglich, siehe https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

Hier ist Echo in einem Emacs-Skript (kopiert vom obigen Link):

#!/usr/bin/emacs --script
(condition-case nil
    (let (line)
      (while (setq line (read-from-minibuffer ""))
        (princ line)
        (princ "\n")))
  (error nil))

oder um es in einen Puffer einzulesen und dann alles auf einmal auszudrucken

#!/usr/bin/emacs --script
(with-temp-buffer
  (progn
    (condition-case nil
    (let (line)
      (while (setq line (read-from-minibuffer ""))
        (insert line)
        (insert "\n")))
      (error nil))
    (princ (buffer-string))
    ))
cwitte
quelle
6

Es ist möglich, eine einfache Shell-Funktion zu erstellen, die so funktioniert, wie sie von stdin liest (obwohl sie tatsächlich in eine temporäre Datei schreibt und diese dann liest). Hier ist der Code, den ich benutze:

# The emacs or emacsclient command to use
function _emacsfun
{
    # Replace with `emacs` to not run as server/client
    emacsclient -c -n $@
}

# An emacs 'alias' with the ability to read from stdin
function e
{
    # If the argument is - then write stdin to a tempfile and open the
    # tempfile.
    if [[ $# -ge 1 ]] && [[ "$1" == - ]]; then
        tempfile="$(mktemp emacs-stdin-$USER.XXXXXXX --tmpdir)"
        cat - > "$tempfile"
        _emacsfun --eval "(find-file \"$tempfile\")" \
            --eval '(set-visited-file-name nil)' \
            --eval '(rename-buffer "*stdin*" t))'
    else
        _emacsfun "$@"
    fi
}

Sie verwenden die Funktion nur als Alias ​​für Emacs, z

echo "hello world" | e -

oder wie gewohnt aus Dateien

e hello_world.txt

Das Ersetzen emacsdurch emacsclientin der Funktion funktioniert ebenfalls.

dshepherd
quelle
Das funktioniert gut für mich, aber _emacsfun sollte es sein emacsclient -c -t $@oder zumindest die Option -n streichen . Manpages mit emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (und jetzt können Sie helm-swoopIhren Weg zu Man Glory!)
Alejandro
1
Dies ist die einzige Antwort, die ich bekommen konnte, um mit Emacsclient zu arbeiten. Ich habe aus der Grundidee ein Shell-Skript gemacht, damit ich es von i3 config aufrufen kann. +1
ergosys
6

Das funktioniert:

echo 123 | emacs --insert <(cat)

aber aus irgendeinem Grund nur mit Grafikmodus-Emacs (Gnome, Konsole, GNU Emacs 23.4.1). Der Befehl:

echo 123 | emacs -nw --insert <(cat)

erzeugt einen Fehler 'emacs: Standardeingabe ist kein tty'. Der gleiche Fehler tritt auf, wenn in der Rohtextkonsole versucht wird.

Tomasz Obrębski
quelle
echo 123 | exec emacs -nw --insert <(cat) </dev/ttysollte arbeiten.
Pyrocrasty
Das funktioniert; warum der exec? Dies funktioniert auch: emacs -nw --insert <(echo 123) </ dev / tty
RoyM
Go figure: Funktioniert wunderbar auf Emacs (w32) auf Cygwin, wo viele andere Einstellungen von mir nicht funktionieren
Charles Roberto Canato
5

Eine weitere Möglichkeit nicht in einem der vorhergehenden Antworten erwähnt ist zu verwenden , /dev/stdinwenn Ihre gewählte Unix - Variante hat.

Der einfache Versuch, /dev/stdindirekt zu öffnen, funktioniert nicht, da Emacs einige Überprüfungen vornimmt und dann Berichte erstellt Symbolic link that points to nonexistent file. (Und wenn Emacs Ihnen erlaubt hätte, die Datei zu laden, dann würden Sie versuchen, sie erneut zu speichern, wie /dev/stdines der Benutzer selten erwartet hätte.)

Das Kombinieren /dev/stdinmit dem --insertArgument funktioniert jedoch:

echo 123 | emacs --insert /dev/stdin

Es sollte beachtet werden, dass diese Version nur unter Verwendung von X funktioniert. Wenn Sie eine Lösung benötigen, die in einem Terminal funktioniert, empfehle ich Ihnen, eine andere Antwort zu suchen .

Kasperd
quelle
Ich habe emacs: standard input is not a ttyNachricht testen es unter Linux und BSD
1
@ Chinggis6 Sieht so aus, als ob mein Vorschlag nur bei Verwendung von X11 funktioniert. Wenn ich zum ersten Mal tippe unset DISPLAY, erhalte ich dieselbe Fehlermeldung wie Sie.
Kasperd
1
@ Chinggis6 Ich habe meine Antwort aktualisiert, um darauf hinzuweisen, dass X zum Arbeiten benötigt wird, und auf eine Antwort verwiesen, die ohne X funktioniert.
kasperd
2

so etwas wie:

$ echo 123 > tmp.txt; emacs tmp.txt

oder

$ echo 123 > tmp.txt; emacs tmp.txt; rm tmp.txt

ist eine Option. Emacs lässt sich nicht wie Vim in UNIX integrieren.

Jweede
quelle
1
Es ist überraschend, dass sich Emacs angesichts seiner Geschichte nicht besser in UNIX integrieren lässt und dass einer der wichtigsten Grundsätze von UNIX ist, dass "alles eine Datei ist". Es fühlt sich intuitiv an, die Ausgabe direkt in Emacs zu leiten.
SabreWolfy
5
@SabreWolfy Während GNU Emacs am häufigsten unter Unix gehostet wird, handelt es sich nicht wie Vim um ein "Unix-Programm", sondern um eine Lisp-Maschine, die einen weitgehend plattformunabhängigen Texteditor implementiert. (Siehe die Antwort von Richard Hoskins. Die "Emacs-Methode" besteht nicht darin, Shell-Befehle an Emacs weiterzuleiten, sondern den Shell-Befehl von Emacs aus aufzurufen M-!, der die resultierende Ausgabe automatisch in einem temporären Puffer festhält.) Holy Abgesehen von Kriegen ist keiner der Herausgeber "besser" als der andere. Sie haben einfach sehr unterschiedliche Perspektiven auf so ziemlich alles.
Aaron Miller
es sei denn, Sie sind in einer Shell und möchten etwas tun curl foo.bar | vim -.. Es tut mir leid. Ich meinte, curl foo.bar | emacsaußer du kannst das nicht
dylnmc