Emacs başlangıçta stdin'den tampon okumaya nasıl yapılır?


40

Vim ile kolayca yapabilirim

$ echo 123 | vim -

Emacs ile yapmak mümkün mü?

$ 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

Bir unix borusundan tampon okumak gerçekten imkansız mıdır?

Düzenleme : Bir çözüm olarak, adlı bir kabuk sarmalayıcı yazdım emacspipe:

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

Yanıtlar:


15

Doğru, stdin'den bir tampon okumak mümkün değil.

Emacs bilgi sayfalarındaki stdin'den tek söz bu :

Toplu modunda, Emacs metin düzenlenirken göstermez ve bu nedenle standart terminal kesme karakterler C-zve C-conların normal bir etkiye sahip olmaya devam. Fonksiyonlar prin1, princve print çıkış için stdoutyerine yankı alanı iken messageve hata mesajları çıktı için stderr. Normalde mini tampondan okuyacak olan işlevler stdinbunun yerine girdilerini alır .

Ve readfonksiyon stdinsadece toplu modda okuyabilir , ancak.

Yani, özel elisp yazarak bu konuda çalışamazsınız bile.


10
Kimseye saygısızlık etmek istemem ama bu çok iğrenç. Bu çok temel bir editör özelliğidir ve GNU EMACS yıllardır etrafta olmuştur. İçinde yapılmalıdır.
user787832

35

İşlem değiştirmeyi kullanabilirsiniz :

$ emacs --insert <(echo 123)

Bu kesinlikle Vim işlevselliğine en yakın olan cevap. Neredeyse sadece boru parçasını bir alt işlem ikamesine taşımak.
dbmikus

@dbmikus Benimki ile Tomasz Obrębski'nin arasında hangisini tercih ettiğime karar veremiyorum ..
Andrew Wood

Tomasz bana bazı nedenlerden dolayı aşağıdaki hatayı alıyorum: emacs: standard input is not a tty
dbmikus

Oh gerçekten! Göndermeden önce test ettiğini varsaydım.
Andrew Wood

1
Belki de aya bağlı.
dbmikus

14

Bir dosyaya yönlendirebilir, sonra dosyayı açabilirsiniz. Örneğin

echo 123 > temp; emacs temp

jweede, geçici dosyanın otomatik olarak kaldırılmasını istiyorsanız, şunları yapabilirsiniz:

echo 123 > temp; emacs temp; rm temp

Bunu yapmanın Emacsy yolu, Emacs'da shell komutunu çalıştırmaktır .

M-! echo 123 RET

Bu size komutun sonuçlarıyla * Shell Command Output * adlı bir tampon verir.


Evet, çok acayip bir yol olduğunu biliyorum, ama bunun unixy bir şekilde kullanılmasını umuyordum. Geçici bir dosya oluşturmak çok hoş bir seçenek değil (daha sonra silmeyi hatırlamam gerekiyor).
sastanin,

1
gibi:echo 123 > temp; emacs temp; rm temp
jweede

2
Genel olarak, Emacs ve Unix arasında yüksek bir empedans vardır. Veya en azından Emacs ve geleneksel Unix iş akışı arasında.
Richard Hoskins,

2
@jweede M-! senin cevabımın bir kısmını, sonra cevabımı silebilirim. Cevaplarımızda büyük bir örtüşme var, ancak meta-bang'ın gelecekteki okuyucular için önemli olduğunu düşünüyorum.
Richard Hoskins

1
temp, mevcut dizinde zaten mevcut olabilir, güvenli değildir; Bir çözüm olarak, bir sarmalayıcı yazdım: TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Herkese teşekkürler!
sastanin

9

Mümkün, https://stackoverflow.com/questions/2879746/idomatic-batch-processing-of-text-in-emacs adresini ziyaret edin.

İşte bir emacs betiğinde yankı (yukarıdaki bağlantıdan kopyalanmıştır):

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

veya bir tampon belleğe okumak ve sonra tek seferde hepsini yazdırmak için

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

Bu var basit bir kabuk işlevi oluşturmak mümkün (aslında o okuma geçici bir dosyaya yazıyor olsa da) o girdiden okuma gibi çalışır. İşte kullanıyorum kodu:

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

Bu işlevi sadece emacs için takma ad olarak kullanırsınız, örneğin

echo "hello world" | e -

veya dosyalardan normal

e hello_world.txt

Yerine emacsgöre emacsclientfonksiyonunda olduğu gibi iyi çalışır.


Bu benim için iyi çalışıyor, ama _emacsfun emacsclient -c -t $@, ya da en azından -n seçeneğini bırakmalı. man sayfaları ile emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (ve şimdi helm-swoopMan Glory için yolunuzu yapabilirsiniz !)
Alejandro

1
Emacsclient ile çalışabildiğim tek cevap bu. Temel fikirden bir kabuk betiği hazırladım, böylece onu i3 config'den çağırabilirim. +1
ergosys

6

Bu çalışıyor:

echo 123 | emacs --insert <(cat)

ancak, bazı nedenlerden dolayı, sadece grafik modlu emaclar ile (Gnome, Konsole, GNU Emacs 23.4.1). Komuta:

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

'emacs: standart giriş tty değil' hatası veriyor. Ham metin konsolunda denendiğinde aynı hata belirir.


echo 123 | exec emacs -nw --insert <(cat) </dev/ttyçalışmalı.
pirotik

Bu çalışır; neden exec Bu aynı zamanda çalışır: emacs -nw --insert <(eko 123) </ dev / tty
RoyM

Go rakamı:
Cygwin'deki Emacs'ta

5

Önceki cevapların hiçbirinde bahsedilmeyen bir başka olasılık /dev/stdin, seçtiğiniz Unix değişkenine sahipse kullanmaktır.

Basitçe /dev/stdindoğrudan açmaya çalışmak işe yaramaz, çünkü Emacs birkaç kontrol yapar ve sonra raporlar Symbolic link that points to nonexistent file. (Ve eğer Emacs dosyayı yüklemenize izin verirse /dev/stdin, kullanıcının beklediğini nadiren yaptığınız gibi tekrar kaydetmeye çalışıyorsunuz .)

Ancak argüman /dev/stdinile birleştirerek --insertçalışır:

echo 123 | emacs --insert /dev/stdin

Bu sürümün yalnızca X kullanırken çalıştığı unutulmamalıdır. Bir terminalde çalışan bir çözüme ihtiyacınız varsa, başka bir cevaba bakmanızı öneririm .


emacs: standard input is not a ttylinux ve bsd üzerinde test mesajı aldım

1
@ Chinggis6 Benim önerim sadece X11 kullanırken işe yarıyor gibi görünüyor. İlk yazarsak unset DISPLAY, seninle aynı hata mesajını alıyorum.
kasperd

1
Chinggis6 Ben işe X ihtiyacı olduğunu işaret etmek benim cevap güncellenerek X. olmadan çalışır bir cevap işaret @
kasperd

2

hazırlıksız, gibi bir şey:

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

veya

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

bir seçenek. Emacs, UNIX ile vim'in yaptığı gibi bütünleşmiyor.


1
Emacs'in tarihine bakılmaksızın UNIX ile daha iyi bütünleşmemesi ve UNIX'in kilit ilkelerinden birinin "her şey bir dosya" olması şaşırtıcı. Boru çıkışını doğrudan Emacs'a sezgisel olarak verir.
SabreWolfy

5
@SabreWolfy GNU Emacs en çok Unix'te barındırılıyor olsa da, Vim'in olduğu gibi bir "Unix programı" değil, daha çok platformdan bağımsız bir metin editörü uygulayan bir Lisp makinesi değil. (Bkz. Richard Hoskins'in cevabı; bunu yapmanın "Emacs yolu", kabuk komutunu Emacs'a aktarmak değil M-!, sonuçta elde edilen çıktıyı geçici bir tampona otomatik olarak yakalayan Emacs içinden kabuk komutunu çağırmaktır .) Kutsal Bir kenara savaş, ne editör diğerinden "daha iyi" değildir; sadece hemen hemen her şey için çok farklı bakış açılarına sahipler.
Aaron Miller

Bir kabuğun içindeyken ve gibi bir şey yapmak istemeniz hariç curl foo.bar | vim -.. Üzgünüm. Bunu curl foo.bar | emacsyapamayacağın dışında demek
istedim
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.