Как заставить Emacs читать буфер из stdin при запуске?

40

С 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
sastanin
источник

Ответы:

15

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

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

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

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

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

Трей Джексон
источник
11
Я имею в виду неуважение ни к кому, но это отвратительно. Это очень простая функция редактора, и GNU EMACS существует уже несколько десятилетий. Он должен быть встроен.
user787832
35

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

$ emacs --insert <(echo 123)
Эндрю Вуд
источник
Это определенно тот ответ, который ближе всего подходит к функциональности Vim. Практически просто перемещаем переданную по конвейеру часть в замену подпроцесса.
dbmikus
@dbmikus Я не могу решить, что предпочитаю между моим и Томашем Обренбски ..
Эндрю Вуд
В результате Томаша я почему-то получаю следующую ошибку: emacs: standard input is not a tty
dbmikus
О, действительно! Я предположил, что он проверил перед публикацией.
Эндрю Вуд
1
Может быть, это зависит от месяца.
dbmikus
14

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

echo 123 > temp; emacs temp

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

echo 123 > temp; emacs temp; rm temp

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

M-! echo 123 RET

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

Ричард Хоскинс
источник
Да, я знаю, что есть изнурительный способ, но я надеялся, что его можно использовать неординарным образом. Создание временного файла не очень хорошая опция (я должен помнить, чтобы удалить его позже).
Састанин
1
такие как:echo 123 > temp; emacs temp; rm temp
Jweede
2
В общем, между Emacs и Unix существует высокий импеданс. Или, по крайней мере, между Emacs и традиционным рабочим процессом Unix.
Ричард Хоскинс
2
@jweede Если вы хотите добавить M-! часть моего ответа на ваш, тогда я мог бы удалить свой ответ. Наши ответы сильно совпадают, но я думаю, что метабанг важен для будущих читателей.
Ричард Хоскинс
1
temp может уже существовать в текущем каталоге, это небезопасно; как решение, я написал обертку: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Спасибо всем!
Састанин
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))
    ))
cwitte
источник
6

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

# 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в функции работает также.

dshepherd
источник
Это хорошо работает для меня, но _emacsfun должен быть emacsclient -c -t $@, или, по крайней мере, отказаться от опции -n. Страницы man с emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (и теперь вы можете helm-swoopперейти к Man Glory!)
Алехандро
1
Это единственный ответ, который я мог получить, работая с emacsclient. Я сделал сценарий оболочки из основной идеи, чтобы я мог вызвать его из конфигурации i3. +1
ergosys
6

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

echo 123 | emacs --insert <(cat)

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

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

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

Томаш Обренбский
источник
echo 123 | exec emacs -nw --insert <(cat) </dev/ttyдолжно сработать.
пирократизм
Это работает; почему исполнительный? Это также работает: emacs -nw --insert <(echo 123) </ dev / tty
RoyM
Go figure: прекрасно работает на Emacs (w32) на Cygwin, где многие другие мои настройки не работают
Чарльз Роберто Канато
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. Если вам нужно решение, которое работает в терминале, я предлагаю вам взглянуть на другой ответ .

kasperd
источник
я получил emacs: standard input is not a ttyсообщение, тестирующее его на Linux и
1
@ Chinggis6 Похоже, мое предложение работает только при использовании X11. Если я наберу первый раз unset DISPLAY, я получу то же сообщение об ошибке, что и вы.
Касперд
1
@ Chinggis6 Я обновил свой ответ,
указав
2

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

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

или

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

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

jweede
источник
1
Удивительно, что Emacs не лучше интегрируется с UNIX, учитывая его историю, и что одним из ключевых принципов UNIX является то, что «все является файлом». Он чувствует себя интуитивно понятным для передачи данных непосредственно в Emacs.
SabreWolfy
5
@SabreWolfy Хотя GNU Emacs чаще всего размещается в Unix, это не «программа Unix», как Vim, а скорее машина Lisp, которая реализует в значительной степени независимый от платформы текстовый редактор. (См. Ответ Ричарда Хоскинса: «Способ Emacs» заключается не в том, чтобы передать команду оболочки в Emacs, а в том, чтобы вызвать команду оболочки из Emacs через M-!, которая автоматически захватывает полученный вывод во временный буфер.) кроме войны, ни один редактор не «лучше» другого; у них просто очень разные взгляды на практически все.
Аарон Миллер
за исключением случаев, когда вы находитесь в оболочке и хотите сделать что-то вроде curl foo.bar | vim -.. извините. Я имел в виду, curl foo.bar | emacsкроме как вы не можете сделать это
dylnmc