¿Cómo hacer que Emacs lea el búfer desde la entrada estándar al inicio?

¿Cómo hacer que Emacs lea el búfer desde la entrada estándar al inicio?

Con Vim puedo hacer fácilmente

$ echo 123 | vim -

¿Es posible hacerlo 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

¿Es realmente imposible leer un búfer desde una tubería Unix?

Editar: Como solución, escribí un contenedor de shell llamado emacspipe:

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

Respuesta1

Correcto, es imposible leer un búfer desde la entrada estándar.

La única mención de stdin en las páginas de información de Emacs eseste, que dice:

En modo por lotes, Emacs no muestra el texto que se está editando y los caracteres de interrupción de terminal estándar como C-zy C-ccontinúan teniendo su efecto normal. Las funciones prin1y envían a en lugar del área de eco, mientras que princlos mensajes de error se envían a . Las funciones que normalmente leerían desde el minibúfer toman sus entradas en su lugar.printstdoutmessagestderrstdin

Y elreadLa función puede leer desde stdin, pero solo en modo por lotes.

Por lo tanto, ni siquiera puedes solucionar este problema escribiendo elisp personalizado.

Respuesta2

Podrías usarsustitución de procesos:

$ emacs --insert <(echo 123)

Respuesta3

Puede redirigir a un archivo y luego abrir el archivo. p.ej

echo 123 > temp; emacs temp

jweede señala que si desea que el archivo temporal se elimine automáticamente, puede:

echo 123 > temp; emacs temp; rm temp

La forma en que Emacsy hace esto espara ejecutar el comando shell en Emacs.

M-! echo 123 RET

Eso le proporciona un búfer llamado *Salida del comando Shell* con los resultados del comando.

Respuesta4

Esposible crear una función de shell simpleque funciona mientras lee desde la entrada estándar (aunque en realidad escribe en un archivo temporal y luego lo lee). Aquí está el código que estoy 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
}

Simplemente usa la función como alias para emacs, por ejemplo

echo "hello world" | e -

o como de costumbre desde archivos

e hello_world.txt

Reemplazar emacspor emacsclienten la función también funciona.

información relacionada