Bagaimana cara membuat buffer baca Emacs dari stdin saat start?

40

Dengan Vim saya bisa dengan mudah melakukannya

$ echo 123 | vim -

Apakah mungkin dilakukan dengan 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

Apakah benar-benar mustahil untuk membaca buffer dari pipa unix?

Sunting : Sebagai solusi, saya menulis pembungkus shell bernama emacspipe:

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

Jawaban:

15

Benar, tidak mungkin membaca buffer dari stdin.

Satu-satunya penyebutan stdin di halaman info Emacs adalah ini , yang mengatakan:

Dalam mode batch, Emacs tidak menampilkan teks yang sedang diedit, dan karakter standar terminal menyela seperti C-zdan C-cterus memiliki efek normal. Fungsi prin1, princdan print output ke stdoutbukan area gema, sementara messagedan pesan kesalahan output ke stderr. Fungsi-fungsi yang biasanya dibaca dari minibuffer mengambil inputnya stdinsebagai gantinya.

Dan readfungsinya dapat membaca stdin, tetapi hanya dalam mode batch.

Jadi, Anda bahkan tidak bisa mengatasi ini dengan menulis custom elisp.

Trey Jackson
sumber
11
Maksud saya tidak menghormati orang lain, tapi ini menjijikkan. Ini adalah fitur editor yang sangat mendasar dan GNU EMACS telah ada selama beberapa dekade. Harus dibangun.
user787832
35

Anda dapat menggunakan substitusi proses :

$ emacs --insert <(echo 123)
Andrew Wood
sumber
Ini jelas merupakan jawaban yang paling dekat dengan fungsionalitas Vim. Cukup banyak hanya memindahkan bagian pipa ke substitusi proses.
dbmikus
@dbmikus Saya tidak bisa memutuskan mana yang saya sukai antara milik saya dan milik Tomasz Obrębski ..
Andrew Wood
Hasil Tomasz pada saya mendapatkan kesalahan berikut karena beberapa alasan: emacs: standard input is not a tty
dbmikus
Oh memang! Saya berasumsi dia telah diuji sebelum memposting.
Andrew Wood
1
Mungkin itu tergantung pada bulannya.
dbmikus
14

Anda dapat mengalihkan ke file, lalu buka file. misalnya

echo 123 > temp; emacs temp

jweede mencatat bahwa jika Anda ingin file temp dihapus secara otomatis, Anda dapat:

echo 123 > temp; emacs temp; rm temp

Cara Emacsy untuk melakukan ini adalah dengan menjalankan perintah shell di Emacs .

M-! echo 123 RET

Itu memberi Anda buffer bernama * Shell Command Output * dengan hasil dari perintah.

Richard Hoskins
sumber
Ya, saya tahu ada cara emacsy, tapi saya berharap ini bisa digunakan dengan cara unixy. Membuat file sementara bukan opsi yang sangat bagus (saya harus ingat untuk menghapusnya nanti).
sastanin
1
seperti:echo 123 > temp; emacs temp; rm temp
jweede
2
Secara umum, ada impedansi tinggi antara Emacs dan Unix. Atau setidaknya antara Emacs dan alur kerja Unix tradisional.
Richard Hoskins
2
@ jweede Jika Anda ingin menambahkan M-! bagian dari jawaban saya untuk Anda, maka saya bisa menghapus jawaban saya. Ada banyak tumpang tindih dalam jawaban kami, tetapi saya pikir meta-bang penting bagi pembaca di masa depan.
Richard Hoskins
1
temp mungkin sudah ada di direktori saat ini, itu tidak aman; sebagai solusi, saya menulis pembungkus: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Terimakasih semuanya!
sastanin
9

Mungkin saja, lihat https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs

Berikut ini gema dalam skrip emacs (disalin dari tautan di atas):

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

atau membacanya ke dalam buffer dan kemudian mencetak semuanya sekaligus

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

Ini mungkin untuk membuat fungsi shell sederhana yang bekerja seperti yang membaca dari stdin (meskipun sebenarnya itu adalah menulis ke file sementara kemudian membaca itu). Berikut kode yang saya gunakan:

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

Anda cukup menggunakan fungsi sebagai alias untuk emacs, mis

echo "hello world" | e -

atau seperti biasa dari file

e hello_world.txt

Mengganti emacsoleh emacsclientdalam fungsi juga berfungsi.

dshepherd
sumber
Ini berfungsi baik untuk saya, tetapi _emacsfun seharusnya emacsclient -c -t $@, atau paling tidak jatuhkan opsi -n. halaman manual dengan emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (dan sekarang Anda dapat helm-swoopmenuju Man Glory!)
Alejandro
1
Ini adalah satu-satunya jawaban yang bisa saya gunakan untuk emacsclient. Saya membuat skrip shell dari ide dasar sehingga saya dapat memanggilnya dari konfigurasi i3. +1
ergosys
6

Ini bekerja:

echo 123 | emacs --insert <(cat)

tetapi, untuk beberapa alasan, hanya dengan emacs mode grafis (Gnome, Konsole, GNU Emacs 23.4.1). Perintah:

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

menghasilkan kesalahan 'emacs: input standar bukan tty'. Kesalahan yang sama muncul ketika dicoba di konsol teks mentah.

Tomasz Obrębski
sumber
echo 123 | exec emacs -nw --insert <(cat) </dev/ttyharus bekerja.
pyrocrasty
Itu bekerja; mengapa eksekutif? Ini juga berfungsi: emacs -nw --insert <(echo 123) </ dev / tty
RoyM
Go figure: bekerja dengan indah di Emacs (w32) di Cygwin, di mana banyak pengaturan saya yang lain tidak
Charles Roberto Canato
5

Kemungkinan lain yang tidak disebutkan dalam jawaban sebelumnya adalah menggunakan /dev/stdinjika varian Unix yang Anda pilih memilikinya.

Hanya mencoba membuka /dev/stdinsecara langsung tidak berhasil, karena Emacs melakukan beberapa pemeriksaan dan kemudian melaporkan Symbolic link that points to nonexistent file. (Dan jika Emacs akan memungkinkan Anda untuk memuat file, maka cobalah untuk menyimpannya lagi karena /dev/stdinjarang melakukan apa yang diharapkan pengguna.)

Namun menggabungkan /dev/stdindengan --insertargumen itu berhasil:

echo 123 | emacs --insert /dev/stdin

Perlu dicatat bahwa versi ini hanya berfungsi ketika menggunakan X. Jika Anda memerlukan solusi yang bekerja di terminal saya sarankan Anda melihat jawaban lain .

kasperd
sumber
saya mendapat emacs: standard input is not a ttypesan mengujinya di linux dan bsd
1
@ Chinggis6 Sepertinya saran saya hanya berfungsi ketika menggunakan X11. Jika saya pertama kali mengetik unset DISPLAY, saya mendapatkan pesan kesalahan yang sama seperti Anda.
kasperd
1
@ Chinggis6 Saya memperbarui jawaban saya untuk menunjukkan bahwa diperlukan X untuk bekerja dan menunjuk ke jawaban yang berfungsi tanpa X.
kasperd
2

begitu saja, sesuatu seperti:

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

atau

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

adalah sebuah pilihan. Emacs tidak berintegrasi dengan UNIX seperti yang dilakukan vim.

jweede
sumber
1
Mengejutkan bahwa Emacs tidak berintegrasi dengan UNIX dengan lebih baik, mengingat sejarahnya dan bahwa salah satu prinsip utama UNIX adalah bahwa "semuanya adalah file". Rasanya intuitif untuk menyalurkan output langsung ke Emacs.
SabreWolfy
5
@ SabreWolfy Sementara GNU Emacs paling umum di-host di Unix, itu bukan "program Unix" seperti Vim, melainkan mesin Lisp yang mengimplementasikan editor teks yang sebagian besar platform-independen. (Lihat jawaban Richard Hoskins; "Cara Emacs" untuk melakukan ini bukan untuk mengirimkan perintah shell ke Emacs, tetapi untuk memanggil perintah shell dari dalam Emacs via M-!, yang secara otomatis menangkap output yang dihasilkan ke dalam buffer sementara.) Holy selain perang, tidak ada editor yang "lebih baik" dari yang lain; mereka hanya memiliki perspektif yang sangat berbeda dalam banyak hal.
Aaron Miller
kecuali ketika Anda berada di shell dan ingin melakukan sesuatu seperti curl foo.bar | vim -.. Saya minta maaf. Maksud saya curl foo.bar | emacskecuali Anda tidak bisa melakukan itu
dylnmc