Come fare in modo che Emacs legga il buffer dallo stdin all'avvio?


40

Con Vim posso facilmente farlo

$ echo 123 | vim -

È possibile fare con Emacs?

$ 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

È davvero impossibile leggere un buffer da una pipe unix?

Modifica : come soluzione, ho scritto un involucro di shell chiamato emacspipe:

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

Risposte:


15

Corretto, è impossibile leggere un buffer da stdin.

L'unica menzione di stdin nelle pagine informative di Emacs è questa , che dice:

In modalità batch, Emacs non visualizza il testo in fase di modifica e i terminali standard interrompono come C-ze C-ccontinuano ad avere il loro effetto normale. Le funzioni prin1, prince print uscita al stdoutposto del di eco, mentre messageei messaggi di errore uscita stderr. Le funzioni che normalmente leggerebbero dal minibuffer prendono invece il loro input stdin.

E la readfunzione può leggere da stdin, ma solo in modalità batch.

Quindi, non puoi nemmeno aggirare questo problema scrivendo elisp personalizzato.


11
Non voglio mancare di rispetto a nessuno, ma questo è disgustoso. Questa è una funzione di editor molto semplice e GNU EMACS è in circolazione da decenni. Dovrebbe essere integrato.
user787832

35

È possibile utilizzare la sostituzione del processo :

$ emacs --insert <(echo 123)

Questa è sicuramente la risposta più vicina alla funzionalità di Vim. Praticamente solo spostando la parte convogliata in una sostituzione di sottoprocesso.
dbmikus,

@dbmikus Non riesco a decidere quale preferisco tra il mio e quello di Tomasz Obrębski ..
Andrew Wood,

I risultati di Tomasz in me emacs: standard input is not a tty
causano

Oh davvero! Ho pensato che avesse provato prima di pubblicare.
Andrew Wood,

1
Forse dipende dal mese.
dbmikus,

14

Puoi reindirizzare a un file, quindi aprire il file. per esempio

echo 123 > temp; emacs temp

jweede osserva che se si desidera che il file temporaneo venga rimosso automaticamente, è possibile:

echo 123 > temp; emacs temp; rm temp

Il modo Emacsy per farlo è eseguire il comando shell in Emacs .

M-! echo 123 RET

Questo ti dà un buffer chiamato * Shell Command Output * con i risultati del comando.


Sì, so che esiste un modo emacsy, ma speravo che potesse essere usato in modo univoco. La creazione di un file temporaneo non è un'opzione molto piacevole (devo ricordarmi di eliminarlo in seguito).
sastanin,

1
come ad esempio:echo 123 > temp; emacs temp; rm temp
jweede,

2
In generale, esiste un'alta impedenza tra Emacs e Unix. O almeno tra Emacs e il tradizionale flusso di lavoro Unix.
Richard Hoskins,

2
@jweede Se vuoi aggiungere M-! parte della mia risposta alla tua, quindi potrei cancellare la mia risposta. C'è una grande sovrapposizione nelle nostre risposte, ma penso che il meta-bang sia importante per i futuri lettori.
Richard Hoskins,

1
temp potrebbe già esistere nella directory corrente, non è sicuro; come una soluzione, ho scritto un wrapper: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Grazie a tutti!
sastanin,

9

È possibile, consultare https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

Ecco l'eco in uno script emacs (copiato dal link sopra):

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

o per leggerlo in un buffer e quindi stamparlo tutto in una volta

#!/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

È possibile creare una semplice funzione shell che funziona come sta leggendo da stdin (anche se in realtà sta scrivendo su un file temporaneo per poi leggerlo). Ecco il codice che sto usando:

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

Basta usare la funzione come alias per emacs, ad es

echo "hello world" | e -

o normalmente dai file

e hello_world.txt

Anche la sostituzione emacsdi emacsclientnella funzione funziona.


Questo funziona bene per me, ma _emacsfun dovrebbe essere emacsclient -c -t $@, o almeno rilasciare l'opzione -n. man page con emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (e ora puoi helm-swooparrivare a Man Glory!)
Alejandro

1
Questa è l'unica risposta con cui ho potuto lavorare con emacsclient. Ho creato uno script di shell dall'idea di base in modo da poterlo chiamare dalla configurazione i3. +1
ergosys

6

Questo funziona:

echo 123 | emacs --insert <(cat)

ma, per qualche motivo, solo con emacs in modalità grafica (Gnome, Konsole, GNU Emacs 23.4.1). Il comando:

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

genera un errore 'emacs: l'input standard non è un tty'. Lo stesso errore appare quando provato nella console di testo non elaborato.


echo 123 | exec emacs -nw --insert <(cat) </dev/ttydovrebbe funzionare.
piroplastica,

Che funzioni; perché il dirigente? Questo funziona anche: emacs -nw --insert <(echo 123) </ dev / tty
RoyM

Vai a capire: funziona magnificamente su Emacs (w32) su Cygwin, dove molte altre mie impostazioni non lo fanno
Charles Roberto Canato,

5

Un'altra possibilità non menzionata in nessuna delle risposte precedenti è quella di utilizzare /dev/stdinse la variante Unix scelta lo possiede.

Il semplice tentativo di aprire /dev/stdindirettamente non funziona, perché Emacs esegue alcuni controlli e quindi segnala Symbolic link that points to nonexistent file. (E se Emacs ti avesse permesso di caricare il file, quindi provare a salvarlo di nuovo come /dev/stdinfarebbe raramente ciò che l'utente si aspettava.)

Tuttavia, combinando /dev/stdincon l' --insertargomento funziona:

echo 123 | emacs --insert /dev/stdin

Va notato che questa versione funziona solo quando si utilizza X. Se è necessaria una soluzione che funziona in un terminale, suggerisco di cercare un'altra risposta .


ho ricevuto un emacs: standard input is not a ttymessaggio per testarlo su linux e bsd

1
@ Chinggis6 Sembra che il mio suggerimento funzioni solo quando si utilizza X11. Se digito per primo unset DISPLAY, ricevo lo stesso messaggio di errore.
Kasperd,

1
@ Chinggis6 Ho aggiornato la mia risposta per sottolineare che ha bisogno di X per funzionare e ho indicato una risposta che funziona senza X.
Kasperd,

2

di mano, qualcosa come:

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

o

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

è un'opzione. Emacs semplicemente non si integra con UNIX come fa Vim.


1
È sorprendente che Emacs non si integri meglio con UNIX, data la sua storia e che uno dei principi chiave di UNIX sia che "tutto è un file". È intuitivo reindirizzare l'output direttamente in Emacs.
SabreWolfy,

5
@SabreWolfy Mentre GNU Emacs è più comunemente ospitato su Unix, non è "un programma Unix" come è Vim, ma piuttosto una macchina Lisp che implementa un editor di testo ampiamente indipendente dalla piattaforma. (Vedi la risposta di Richard Hoskins; il "modo di Emacs" di fare questo non è di convogliare il comando shell in Emacs, ma di aver invocato il comando shell da Emacs via M-!, che cattura automaticamente l'output risultante in un buffer temporaneo.) Holy guerre a parte, nessuno dei due editor è "migliore" dell'altro; hanno solo prospettive molto diverse su praticamente tutto.
Aaron Miller,

tranne quando sei in una shell e vuoi fare qualcosa di simile curl foo.bar | vim -... mi dispiace. Volevo dire curl foo.bar | emacstranne che non puoi farlo
dylnmc
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.