37

С Vim я могу легко сделать

$ echo 123 | vim -

Можно ли это сделать с 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

Неужели невозможно прочитать буфер из канала Unix?

Изменить: В качестве решения я написал оболочку оболочки с именем emacspipe:

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

8 ответов8

33

Вы можете использовать процесс подстановки:

$ emacs --insert <(echo 123)
13

Вы можете перенаправить в файл, а затем открыть файл. например

echo 123 > temp; emacs temp

jweede отмечает, что если вы хотите, чтобы временный файл автоматически удалялся, вы можете:

echo 123 > temp; emacs temp; rm temp

Способ Emacsy сделать это - запустить команду оболочки в Emacs.

M-! echo 123 RET

Это дает вам буфер с именем * Shell Command Output * с результатами команды.

12

Правильно, невозможно прочитать буфер из stdin.

Единственное упоминание о stdin на информационных страницах Emacs - это :

В пакетном режиме Emacs не отображает редактируемый текст, и стандартные символы прерывания терминала, такие как C-z и C-c продолжают оказывать свое обычное действие. Функции prin1 , princ и print выводят в stdout вместо области эха, а message и сообщения об ошибках выводят в stderr . Функции, которые обычно читают из минибуфера, получают данные из stdin .

И функция read может читать из стандартного stdin , но только в пакетном режиме.

Таким образом, вы даже не можете обойти это, написав собственный elisp.

9

Это возможно, см. Https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

Вот эхо в скрипте emacs (скопировано из ссылки выше):

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

или прочитать его в буфер, а затем распечатать все сразу

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

Это работает:

echo 123 | emacs --insert <(cat)

но, по некоторым причинам, только с emacs в графическом режиме (Gnome, Konsole, GNU Emacs 23.4.1). Команда:

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

генерирует ошибку 'emacs: стандартный ввод не является tty'. Та же ошибка появляется при попытке в текстовой консоли.

5

Другая возможность, не упомянутая ни в одном из предыдущих ответов, - это использовать /dev/stdin если она есть в выбранном вами варианте Unix.

Простая попытка открыть /dev/stdin напрямую не работает, потому что Emacs делает несколько проверок и затем сообщает о Symbolic link that points to nonexistent file . (И если Emacs позволил бы вам загрузить файл, то попытка сохранить его снова как /dev/stdin редко будет делать то, что ожидал пользователь.)

Однако сочетание /dev/stdin с аргументом --insert работает:

echo 123 | emacs --insert /dev/stdin

Следует отметить, что эта версия работает только при использовании X. Если вам нужно решение, которое работает в терминале, я предлагаю вам взглянуть на другой ответ.

5

Можно создать простую функцию оболочки, которая будет работать как чтение со стандартного ввода (хотя на самом деле это запись во временный файл, а затем чтение). Вот код, который я использую:

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

Вы просто используете функцию в качестве псевдонима для Emacs, например

echo "hello world" | e -

или как обычно из файлов

e hello_world.txt

Замена emacs на emacsclient в функции также работает.

2

случайно, что-то вроде:

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

или же

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

это вариант. Emacs просто не интегрируется с UNIX, как это делает vim.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .