Jak zmusić Emacsa do odczytu bufora ze standardowego wejścia na start?

40

Z Vimem mogę to łatwo zrobić

$ echo 123 | vim -

Czy można zrobić z Emacsem?

$ 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

Czy naprawdę niemożliwe jest odczytanie bufora z potoku unix?

Edycja : Jako rozwiązanie napisałem opakowanie powłoki o nazwie emacspipe:

#!/bin/sh
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
sastanina
źródło

Odpowiedzi:

15

Prawidłowo, nie można odczytać bufora ze standardowego wejścia.

Jedyną wzmianką o stdin na stronach informacyjnych Emacsa jest to , co mówi:

W trybie wsadowym Emacs nie wyświetla edytowanego tekstu, a standardowe znaki terminala przerywają, takie jak C-zi C-cnadal działają normalnie. Funkcje prin1, princa print wyjście do stdoutzamiast echo, natomiast obszar messagei komunikaty o błędach do wyjścia stderr. Funkcje, które normalnie czytałyby z minibufora, stdinzamiast tego pobierają dane wejściowe .

I readfunkcja może odczytywać stdin, ale tylko w trybie wsadowym.

Więc nie możesz nawet obejść tego, pisząc własny elisp.

Trey Jackson
źródło
10
Mam na myśli brak szacunku dla nikogo, ale to jest odrażające. Jest to bardzo podstawowa funkcja edytora, a GNU EMACS istnieje już od dziesięcioleci. Powinien być wbudowany.
użytkownik787832
35

Możesz użyć podstawienia procesu :

$ emacs --insert <(echo 123)
Andrew Wood
źródło
To zdecydowanie odpowiedź, która zbliża się do funkcjonalności Vima. Prawie tylko przenoszenie części rurowej do zamiany podprocesu.
dbmikus
@dbmikus Nie mogę zdecydować, który wolę między moim a Tomem Obrębskim.
Andrew Wood,
Wyniki Tomasza spowodowały, że z jakiegoś powodu otrzymałem następujący błąd: emacs: standard input is not a tty
dbmikus
Och, rzeczywiście! Zakładałem, że przetestował przed wysłaniem.
Andrew Wood,
1
Może to zależy od miesiąca.
dbmikus
14

Możesz przekierować do pliku, a następnie go otworzyć. na przykład

echo 123 > temp; emacs temp

jweede zauważa, że ​​jeśli chcesz, aby plik tymczasowy był automatycznie usuwany, możesz:

echo 123 > temp; emacs temp; rm temp

Emacsy sposobem na to jest uruchomienie polecenia powłoki w Emacsie .

M-! echo 123 RET

To daje bufor o nazwie * Shell Command Output * z wynikami polecenia.

Richard Hoskins
źródło
Tak, wiem, że istnieje emacsy sposób, ale mam nadzieję, że może być używany w sposób uniksowy. Utworzenie pliku tymczasowego nie jest zbyt przyjemną opcją (muszę pamiętać, aby go później usunąć).
sastanin
1
takie jak:echo 123 > temp; emacs temp; rm temp
jweede
2
Ogólnie rzecz biorąc, istnieje wysoka impedancja między Emacsem a Uniksem. Lub przynajmniej między Emacsem a tradycyjnym przepływem pracy w Uniksie.
Richard Hoskins,
2
@jweede Jeśli chcesz dodać M-! część mojej odpowiedzi na twoją, wtedy mógłbym usunąć swoją odpowiedź. Nasze odpowiedzi w dużym stopniu się pokrywają, ale myślę, że meta-bang jest ważny dla przyszłych czytelników.
Richard Hoskins,
1
temp może już istnieć w bieżącym katalogu, nie jest to bezpieczne; jako rozwiązanie napisałem opakowanie: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Dzięki wszystkim!
sastanin
9

Jest to możliwe, patrz https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

Oto echo w skrypcie emacsa (skopiowanym z powyższego linku):

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

lub odczytać go do bufora, a następnie wydrukować za jednym razem

#!/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
źródło
6

Możliwe jest utworzenie prostej funkcji powłoki, która działa podczas odczytu ze standardowego wejścia (chociaż w rzeczywistości zapisuje do pliku tymczasowego, a następnie go odczytuje). Oto kod, którego używam:

# 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
}

Po prostu używasz tej funkcji jako aliasu dla emacsa, np

echo "hello world" | e -

lub jak zwykle z plików

e hello_world.txt

Zastępowanie emacsprzez emacsclientw funkcji również działa.

dshepherd
źródło
Działa to dla mnie dobrze, ale _emacsfun powinien być emacsclient -c -t $@, a przynajmniej upuścić opcję -n. strony man z emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (a teraz możesz dostać helm-swoopsię do Man Glory!)
Alejandro
1
To jedyna odpowiedź, jaką mogłem dostać do pracy z emacsclient. Zrobiłem skrypt powłoki z podstawowego pomysłu, więc mogę go wywołać z konfiguracji i3. +1
ergosys
6

To działa:

echo 123 | emacs --insert <(cat)

ale z jakiegoś powodu tylko z emacsem w trybie graficznym (Gnome, Konsole, GNU Emacs 23.4.1). Komenda:

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

generuje błąd „emacs: standardowe wejście nie jest tty”. Ten sam błąd pojawia się podczas próby w surowej konsoli tekstowej.

Tomasz Obrębski
źródło
echo 123 | exec emacs -nw --insert <(cat) </dev/ttypowinno działać.
pirokrastyka
To działa; dlaczego wykonawca? Działa to również: emacs -nw --insert <(echo 123) </ dev / tty
RoyM
Idź rysunek: pięknie działa na Emacsie (w32) na Cygwinie, gdzie nie ma wielu innych ustawień
Charles Roberto Canato
5

Inną możliwością nie wymienioną w żadnej z poprzednich odpowiedzi jest skorzystanie z niej, /dev/stdinjeśli ma ją wybrany wariant Unix.

Po prostu próba /dev/stdinbezpośredniego otwarcia nie działa, ponieważ Emacs wykonuje kilka kontroli, a następnie zgłasza Symbolic link that points to nonexistent file. (A jeśli Emacs pozwoliłby ci załadować plik, wówczas próba zapisania go ponownie, jak /dev/stdinrzadko robiłaby to, czego oczekiwał użytkownik).

Jednak połączenie /dev/stdinz --insertargumentem działa:

echo 123 | emacs --insert /dev/stdin

Należy zauważyć, że ta wersja działa tylko przy użyciu X. Jeśli potrzebujesz rozwiązania, które działa w terminalu, sugeruję, aby spojrzeć na inną odpowiedź .

kasperd
źródło
dostałem emacs: standard input is not a ttywiadomość testującą to na Linuksie i BSD
1
@ Chinggis6 Wygląda na to, że moja sugestia działa tylko przy użyciu X11. Jeśli wpierw unset DISPLAYpiszę, otrzymuję ten sam komunikat o błędzie co ty.
kasperd
1
@ Chinggis6 Zaktualizowałem moją odpowiedź, aby zaznaczyć, że potrzebuje X do działania, i wskazałem odpowiedź, która działa bez X.
kasperd
2

z ręki coś takiego:

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

lub

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

jest opcją. Emacs po prostu nie integruje się z UNIX tak, jak robi to vim.

jweede
źródło
1
Zaskakujące jest to, że Emacs nie integruje się lepiej z UNIXem, biorąc pod uwagę jego historię i że jednym z kluczowych założeń UNIX jest to, że „wszystko jest plikiem”. Intuicyjne jest przesyłanie danych wyjściowych bezpośrednio do Emacsa.
SabreWolfy,
5
@SabreWolfy Chociaż GNU Emacs jest najczęściej hostowany na Uniksie, nie jest to „program uniksowy”, taki jak Vim, ale raczej maszyna Lisp, która implementuje w dużej mierze niezależny od platformy edytor tekstowy. (Zobacz odpowiedź Richarda Hoskinsa; „Sposób Emacsa” nie polega na wprowadzeniu polecenia powłoki do Emacsa, ale wywołaniu polecenia powłoki z poziomu Emacsa przez M-!, który automatycznie przechwytuje wynikowy wynik w tymczasowym buforze.) Święty poza wojnami żaden redaktor nie jest „lepszy” od drugiego; po prostu mają bardzo różne perspektywy na prawie wszystko.
Aaron Miller
z wyjątkiem sytuacji, gdy jesteś w skorupce i chcesz zrobić coś takiego curl foo.bar | vim -... Przepraszam. curl foo.bar | emacs
Chodziło