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

回答:


15

正しい、stdinからバッファーを読み取ることは不可能です。

Emacsの情報ページでのstdinの唯一の言及はこれで、次のように書かれています:

バッチモードでは、Emacsは編集中のテキストを表示せず、標準端末はなどの文字を割り込み、通常の効果C-zC-c継続します。関数prin1princおよびエコーエリアの代わりにprint 出力stdout、while messageおよびエラーメッセージはに出力されstderrます。通常ミニバッファーから読み取る関数は、stdin代わりに入力を受け取ります。

また、read関数はから読み取ることができますstdinが、バッチモードでのみです。

そのため、カスタムelispを作成してもこの問題を回避することはできません。


11
私は誰に対しても無礼を意味しませんが、これは忌まわしいことです。これは非常に基本的なエディター機能であり、GNU EMACSは何十年も使用されています。組み込まれる必要があります。
user78783215

35

プロセス置換を使用できます:

$ emacs --insert <(echo 123)

これは間違いなくVim機能に最も近い答えです。パイプ部分をサブプロセス置換に移動するだけです。
dbmikus

私は..私は鉱山とトマシュObrębskiの間好むかを決めることができません@dbmikus
アンドリュー・ウッド

Tomaszの結果、何らかの理由で次のエラーが表示されます。 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 *という名前のバッファーにコマンドの結果が表示されます。


はい、私は手際の良い方法があることを知っていますが、それがユニキシの方法で使用されることを望みました。一時ファイルを作成することは、あまり良いオプションではありません(後で削除することを忘れないでください)。
サスタニン2009

1
など:echo 123 > temp; emacs temp; rm temp
jweede 09

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))
    ))

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機能には、同様に動作します。


これはうまく機能しますが、_emacsfunはでemacsclient -c -t $@あるか、少なくとも-nオプションを削除する必要があります。のマニュアルページemacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (そして今、あなたはhelm-swoopマングローリーに行くことができます!)
アレハンドロ

1
これが、emacsclientで作業できる唯一の答えです。基本的なアイデアからシェルスクリプトを作成したので、i3 configから呼び出すことができます。+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:CygwinのEmacs(w32)で美しく動作します。他の多くの設定はそうではありません
チャールズロベルトカナト

5

前の回答のいずれにも言及されていない別の可能性は/dev/stdin、選択したUnixバリアントに含まれている場合に使用することです。

/dev/stdinEmacsがいくつかのチェックを行ってから報告するため、単純に直接開こうとしても機能しませんSymbolic link that points to nonexistent file。(そして、もしEmacsがファイルをロードすることを許可していたなら/dev/stdin、ユーザーが期待することはめったにしないので、それをもう一度保存しようとします。)

ただし/dev/stdin--insert引数と組み合わせても機能します。

echo 123 | emacs --insert /dev/stdin

このバージョンはXを使用している場合にのみ機能することに注意してください。端末で機能するソリューションが必要な場合は、別の回答をご覧になることをお勧めします。


emacs: standard input is not a ttyLinuxとbsdでテストするメッセージが表示されました

1
@ Chinggis6私の提案はX11を使用している場合にのみ機能するようです。最初に入力unset DISPLAYすると、同じエラーメッセージが表示されます。
カスペルド

1
@ Chinggis6私は答えを更新して、Xが機能するためにXが必要であることを指摘し、Xなしで機能する答えを指摘しました
。– kasperd

2

オフハンド、次のようなもの:

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

または

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

オプションです。Emacsは、vimのようにUNIXと統合しません。


1
Emacsがその歴史を考えれば、UNIXとの統合がうまくいかず、UNIXの重要な教義の1つが「すべてがファイルである」ということです。出力を直接Emacsにパイプするのは直感的です。
SabreWolfy

5
@SabreWolfy GNU EmacsはUnixで最も一般的にホストされますが、Vimのように「Unixプログラム」ではなく、プラットフォームに依存しないテキストエディタを実装するLispマシンです。(Richard Hoskinsの回答を参照してください。これを行う「Emacsの方法」は、シェルコマンドをEmacsにパイプするのではなく、Emacs経由M-!でシェルコマンドを呼び出し、結果の出力を一時バッファーに自動的にキャプチャします。)戦争はさておき、どちらのエディターも他のエディターより「優れている」。彼らはほとんどすべてについて非常に異なる視点を持っています。
アーロンミラー

シェルにいて、次のようなことをしたい場合を除きますcurl foo.bar | vim -。ごめんなさい。私はcurl foo.bar | emacsあなたがそれを行うことができないことを除いて
-dylnmc
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.