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

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.


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)

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.


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

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.


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.


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ź .


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.