Làm thế nào để làm cho Emacs đọc bộ đệm từ stdin khi bắt đầu?


40

Với Vim tôi có thể dễ dàng làm

$ echo 123 | vim -

Có thể làm với 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

Có thực sự không thể đọc một bộ đệm từ một ống unix?

Chỉnh sửa : Như một giải pháp, tôi đã viết một trình bao bọc có tên emacspipe:

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

Câu trả lời:


15

Chính xác, không thể đọc một bộ đệm từ stdin.

Sự đề cập duy nhất của stdin trong các trang thông tin của Emacs là cái này , nó nói:

Trong chế độ hàng loạt, Emacs không hiển thị văn bản đang được chỉnh sửa và các ký tự ngắt đầu cuối tiêu chuẩn như C-zC-ctiếp tục có hiệu ứng bình thường. Các chức năng prin1, princprint đầu ra để stdoutthay cho vùng phản hồi, trong khi messagevà thông báo lỗi đầu ra stderr. Các chức năng thường đọc từ bộ thu nhỏ stdinthay vào đó lấy đầu vào của chúng .

readchức năng có thể đọc từ stdin, nhưng chỉ trong chế độ hàng loạt.

Vì vậy, bạn thậm chí không thể giải quyết vấn đề này bằng cách viết elisp tùy chỉnh.


10
Tôi có nghĩa là không tôn trọng bất cứ ai, nhưng điều này là gớm ghiếc. Đây là một tính năng soạn thảo rất cơ bản và GNU EMACS đã xuất hiện trong nhiều thập kỷ. Nó nên được xây dựng trong.
user787832 6/2/2015

35

Bạn có thể sử dụng thay thế quá trình :

$ emacs --insert <(echo 123)

Đây chắc chắn là câu trả lời gần nhất với chức năng Vim. Khá nhiều chỉ cần di chuyển phần đường ống thành một sự thay thế quy trình con.
dbmikus

@dbmikus Tôi không thể quyết định tôi thích cái nào hơn giữa tôi và Tomasz Obrębski ..
Andrew Wood

Kết quả của Tomasz khiến tôi gặp phải lỗi sau vì một số lý do: emacs: standard input is not a tty
dbmikus

Ôi thật đấy! Tôi cho rằng anh ấy đã thử nghiệm trước khi đăng.
Andrew Wood

1
Có lẽ nó phụ thuộc vào tháng.
dbmikus

14

Bạn có thể chuyển hướng đến một tệp, sau đó mở tệp. ví dụ

echo 123 > temp; emacs temp

jweede lưu ý rằng nếu bạn muốn tệp tạm thời tự động bị xóa, bạn có thể:

echo 123 > temp; emacs temp; rm temp

Cách Emacsy để làm điều này là chạy lệnh shell trong Emacs .

M-! echo 123 RET

Điều đó cung cấp cho bạn một bộ đệm có tên * Shell Command Output * với kết quả của lệnh.


Vâng, tôi biết có cách emacsy, nhưng tôi hy vọng nó có thể được sử dụng cách unixy. Tạo một tập tin tạm thời không phải là một lựa chọn tốt đẹp (tôi phải nhớ để xóa nó sau).
sastanin

1
chẳng hạn như:echo 123 > temp; emacs temp; rm temp
jweede

2
Nhìn chung, có một trở kháng cao giữa Emacs và Unix. Hoặc ít nhất là giữa Emacs và luồng công việc Unix truyền thống.
Richard Hoskins

2
@jweede Nếu bạn muốn thêm M-! một phần câu trả lời của tôi cho bạn, sau đó tôi có thể xóa câu trả lời của mình. Có một sự trùng lặp lớn trong câu trả lời của chúng tôi, nhưng tôi nghĩ meta-bang rất quan trọng đối với độc giả tương lai.
Richard Hoskins

1
temp có thể đã tồn tại trong thư mục hiện tại, nó không an toàn; như một giải pháp, tôi đã viết một trình bao bọc : TMP=$(mktemp) && cat > $TMP && emacs23 $TMP ; rm $TMP. Cảm ơn tất cả mọi người!
sastanin

9

Có thể, hãy xem https://stackoverflow.com/questions/2879746/idomatic-batch- Processing-of-text-in-emacs

Đây là tiếng vang trong tập lệnh emacs (được sao chép từ liên kết trên):

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

hoặc đọc nó vào một bộ đệm và sau đó in ra tất cả trong một lần

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

thể tạo một hàm shell đơn giản hoạt động như đang đọc từ stdin (mặc dù trên thực tế, nó đang ghi vào một tệp tạm thời sau đó đọc nó). Đây là mã tôi đang sử dụng:

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

Bạn chỉ cần sử dụng chức năng như một bí danh cho emacs, vd

echo "hello world" | e -

hoặc như bình thường từ các tập tin

e hello_world.txt

Thay thế emacsbởi emacsclienttrong chức năng hoạt động là tốt.


Điều này hoạt động tốt với tôi, nhưng _emacsfun nên emacsclient -c -t $@, hoặc ít nhất là bỏ tùy chọn -n. trang dành cho người đàn ông với emacsclient -t --eval "(man \"$1\")" --eval "(delete-window)" (và bây giờ bạn có thể helm-swooptheo cách của mình đến Man Glory!)
Alejandro

1
Đây là câu trả lời duy nhất mà tôi có thể làm việc với emacsclient. Tôi đã tạo một kịch bản shell từ ý tưởng cơ bản để tôi có thể gọi nó từ cấu hình i3. +1
ergosys

6

Những công việc này:

echo 123 | emacs --insert <(cat)

nhưng, vì một số lý do, chỉ với các emacs chế độ đồ họa (Gnome, Konsole, GNU Emacs 23.4.1). Lệnh:

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

tạo ra lỗi 'emacs: đầu vào tiêu chuẩn không phải là một tty'. Lỗi tương tự xuất hiện khi thử trong bảng điều khiển văn bản thô.


echo 123 | exec emacs -nw --insert <(cat) </dev/ttynên làm việc.
pyrocrasty

Điều đó làm việc; Tại sao lại thi hành án? Điều này cũng hoạt động: emacs -nw --insert <(echo 123) </ dev / tty
RoyM

Hình: hoạt động tuyệt vời trên Emacs (w32) trên Cygwin, nơi có nhiều cài đặt khác của tôi không
Charles Roberto Canato

5

Một khả năng khác không được đề cập trong bất kỳ câu trả lời nào trước đó là sử dụng /dev/stdinnếu biến thể Unix đã chọn của bạn có nó.

Đơn giản chỉ cần cố gắng mở /dev/stdintrực tiếp không hoạt động, bởi vì Emacs thực hiện một vài kiểm tra và sau đó báo cáo Symbolic link that points to nonexistent file. (Và nếu Emacs sẽ cho phép bạn tải tệp, sau đó cố gắng lưu lại vì /dev/stdinhiếm khi làm những gì người dùng mong đợi.)

Tuy nhiên, kết hợp /dev/stdinvới --insertđối số không hoạt động:

echo 123 | emacs --insert /dev/stdin

Cần lưu ý rằng phiên bản này chỉ hoạt động khi sử dụng X. Nếu bạn cần một giải pháp hoạt động trong một thiết bị đầu cuối, tôi khuyên bạn nên xem một câu trả lời khác .


tôi đã nhận được emacs: standard input is not a ttytin nhắn thử nghiệm nó trên linux và bsd

1
@ Chinggis6 Có vẻ như đề xuất của tôi chỉ hoạt động khi sử dụng X11. Nếu tôi gõ đầu tiên unset DISPLAY, tôi nhận được thông báo lỗi giống như bạn.
kasperd

1
@ Chinggis6 Tôi đã cập nhật câu trả lời của mình để chỉ ra rằng nó cần X hoạt động và chỉ ra một câu trả lời hoạt động mà không có X.
kasperd

2

offhand, một cái gì đó như:

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

hoặc là

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

là một lựa chọn. Emacs không tích hợp với UNIX theo cách vim làm.


1
Điều đáng ngạc nhiên là Emacs không tích hợp với UNIX tốt hơn, dựa trên lịch sử của nó và một trong những nguyên lý chính của UNIX là "mọi thứ đều là một tệp". Nó cảm thấy trực quan để đầu ra đường ống trực tiếp vào Emacs.
SabreWolfy

5
@SabreWolfy Mặc dù GNU Emacs được lưu trữ phổ biến nhất trên Unix, nhưng nó không phải là "chương trình Unix" theo cách của Vim, mà là một máy Lisp thực hiện trình soạn thảo văn bản độc lập với nền tảng. (Xem câu trả lời của Richard Hoskins; "Cách Emacs" khi thực hiện việc này không phải là chuyển lệnh shell shell sang Emacs, mà là gọi lệnh shell từ bên trong Emacs M-!, tự động thu được kết quả đầu ra vào bộ đệm tạm thời.) Holy chiến tranh sang một bên, không biên tập viên là "tốt hơn" khác; họ chỉ có quan điểm rất khác nhau về mọi thứ.
Aaron Miller

ngoại trừ khi bạn ở trong vỏ và muốn làm một cái gì đó như curl foo.bar | vim -.. tôi xin lỗi. Ý tôi là curl foo.bar | emacsngoại trừ bạn không thể làm điều đó
dylnmc
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.