Como tornar o buffer de leitura do Emacs a partir do stdin on start?

35

Com o Vim, posso fazer facilmente

$ echo 123 | vim -

É possível fazer com o 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

É realmente impossível ler um buffer de um pipe unix?

Editar : Como solução, eu escrevi um wrapper chamado emacspipe :

#!/bin/sh
TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP
    
por sastanin 28.08.2009 / 17:10

8 respostas

11

Correto, é impossível ler um buffer de stdin.

A única menção de stdin nas páginas de informações do Emacs é este , que diz:

In batch mode, Emacs does not display the text being edited, and the standard terminal interrupt characters such as C-z and C-c continue to have their normal effect. The functions prin1, princ and print output to stdout instead of the echo area, while message and error messages output to stderr. Functions that would normally read from the minibuffer take their input from stdin instead.

E a função read pode leia de stdin , mas apenas no modo batch.

Então, você não pode nem mesmo resolver isso escrevendo um elisp personalizado.

    
por 28.08.2009 / 19:25
30

Você pode usar a substituição de processos :

$ emacs --insert <(echo 123)
    
por 06.10.2014 / 19:54
12

Você pode redirecionar para um arquivo e abrir o arquivo. por exemplo,

echo 123 > temp; emacs temp

O jweede observa que se você quiser que o arquivo temporário seja removido automaticamente, você pode:

echo 123 > temp; emacs temp; rm temp

A maneira do Emacsy de fazer isso é executar o comando shell no Emacs .

M-! echo 123 RET

Isso lhe dá um buffer chamado * Shell Command Output * com os resultados do comando.

    
por 28.08.2009 / 17:44
9

É possível ver link

Aqui está echo em um script do emacs (copiado do link acima):

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

ou para lê-lo em um buffer e depois imprimi-lo de uma só vez

#!/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))
    ))
    
por 13.10.2012 / 19:20
6

Isso funciona:

echo 123 | emacs --insert <(cat)

mas, por alguma razão, apenas com emacs de modo gráfico (Gnome, Konsole, GNU Emacs 23.4.1). O comando:

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

gera um erro 'emacs: entrada padrão não é um tty'. O mesmo erro aparece quando tentado no console de texto bruto.

    
por 24.10.2014 / 20:29
5

é possível criar uma função de shell simples que funciona como leitura de stdin (embora, na verdade, está gravando em um arquivo temporário e depois lendo isso). Aqui está o código que estou 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
}

Você acabou de usar a função como um alias para o emacs, por exemplo,

echo "hello world" | e -

ou como normal em arquivos

e hello_world.txt

Substituir emacs por emacsclient na função também funciona.

    
por 22.11.2014 / 21:50
5

Outra possibilidade não mencionada em nenhuma das respostas anteriores é usar /dev/stdin se a sua variante Unix escolhida a tiver.

Simplesmente tentar abrir /dev/stdin diretamente não funciona, porque o Emacs faz algumas verificações e depois reporta Symbolic link that points to nonexistent file . (E se o Emacs permitisse que você carregasse o arquivo, tente salvá-lo novamente, pois /dev/stdin raramente faria o que o usuário esperava.)

No entanto, combinar /dev/stdin com o argumento --insert funciona:

echo 123 | emacs --insert /dev/stdin

Note-se que esta versão só funciona quando se usa X. Se você precisar de uma solução que funcione em um terminal, sugiro que você olhe outra resposta .

    
por 16.12.2015 / 19:09
2

de improviso, algo como:

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

ou

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

é uma opção. O Emacs simplesmente não se integra ao UNIX da mesma forma que o vim.

    
por 28.08.2009 / 17:28

Tags