Làm thế nào để gọi trình soạn thảo vim và đầu ra đường ống để bash


34

Đôi khi tôi cần phải viết văn bản và sau đó chuyển văn bản đó sang một lệnh khác. Quy trình làm việc thông thường của tôi diễn ra như thế này:

vim
# I edit and save my file as file.txt
cat file.txt | pandoc -o file.pdf # pandoc is an example 
rm file.txt

Tôi thấy điều này cồng kềnh và tìm cách học bash scripting Tôi muốn làm cho quá trình đơn giản hơn nhiều bằng cách viết một lệnh kích hoạt một trình soạn thảo và khi trình soạn thảo đóng ống đầu ra của trình soạn thảo vào thiết bị xuất chuẩn. Sau đó, tôi có thể chạy lệnh như quickedit | pandoc -o file.pdf.

Tôi không chắc nó sẽ hoạt động như thế nào. Tôi đã viết một chức năng để tự động hóa điều này bằng cách làm theo quy trình làm việc chính xác ở trên cộng với một số bổ sung. Nó tạo ra một chuỗi ngẫu nhiên để hoạt động như một tên tệp và chuyển chuỗi đó đến vim khi hàm được gọi. Khi người dùng thoát vim bằng cách lưu tệp, hàm sẽ in tệp vào bàn điều khiển và sau đó xóa tệp.

function quickedit {
    filename="$(cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32)"
    vim $filename
    cat $filename
    rm $filename
}
# The problem:
# => Vim: Warning: Output is not to a terminal

Vấn đề tôi sớm gặp phải là khi tôi làm một cái gì đó như quickedit | commandvim, bản thân nó không thể được sử dụng như một trình soạn thảo vì tất cả đầu ra bị hạn chế đối với đường ống.

Tôi tự hỏi nếu có bất kỳ giải pháp cho vấn đề này, để tôi có thể dẫn đầu ra của quickeditchức năng của mình . Sự thay thế tối ưu là kích hoạt một trình soạn thảo riêng biệt, nói văn bản cao siêu, nhưng tôi thực sự muốn ở lại trong thiết bị đầu cuối.


Từ trong vim, ra lệnh :w !pandoc -o file.pdf? (Lưu ý: khoảng cách giữa w!là thiết yếu.)
John1024

Được, nó tuyệt đấy. Tôi không biết bạn có thể dẫn đầu ra vim từ bên trong vim. Điều này phục vụ cho mục đích của tôi, nhưng đối với kiến ​​thức trong tương lai của tôi, liệu có thể giải quyết vấn đề của tôi chính xác theo cách tôi dự định giải quyết không?
theideasmith

Bạn có thể gửi chức năng của bạn? Bạn có ý nghĩa gì khi bạn nói về vấn đề bạn sớm gặp phải (đoạn cuối thứ hai)? Tôi không hiểu điều đó.
Lucas

5
Bên cạnh đó, bạn nên sử dụngmktemp thay vì phát minh lại nó trong thời trang không an toàn.
tự đại diện

Là một người dùng bash mới, các mối nguy hiểm bảo mật của việc phát minh lại mktemp là gì?
theideasmith

Câu trả lời:


42

vipe là một chương trình để chỉnh sửa các đường ống:

command1 | vipe | command2

Bạn nhận được một trình soạn thảo với đầu ra hoàn chỉnh command1và khi bạn thoát, nội dung được chuyển command2qua đường ống.

Trong trường hợp này, không có command1. Vì vậy, bạn có thể làm:

: | vipe | pandoc -o foo.pdf

Hoặc là:

vipe <&- | pandoc -o foo.pdf

vipechọn ra EDITORVISUALcác biến, vì vậy bạn có thể sử dụng chúng để mở Vim.

Nếu bạn chưa cài đặt nó, vipecó sẵn trong moreutilsgói; sudo apt-get install moreutilshoặc bất cứ điều gì tương đương với flavour của bạn.


1
Đối với người dùng Mac đã đến đây: moreutilscó sẵn trong Homebrew.
vergenzt

Đối với người dùng FreeBSD: moreutilscó sẵn để được cài đặt qua pkg (8) .
Mateusz Piotrowski

20

Bạn có thể làm điều này từ bên trong Vim:

:w !pandoc -o file.pdf

Hoặc thậm chí ghi bộ đệm vào một đường ống phức tạp:

:w !grep pattern | somecommand > file.txt

Và sau đó bạn có thể thoát Vim mà không cần lưu:

:q!

Tuy nhiên, xem xét trường hợp sử dụng cụ thể của bạn, có lẽ có một giải pháp tốt hơn bằng cách sử dụng vilàm trình soạn thảo dòng lệnh của bạn. Giả sử bạn sử dụng bash:

set -o vi

Điều này đặt keybindings của bạn để vi. Vì vậy, bạn có thể chỉnh sửa các lệnh của bạn ngay trên dòng lệnh với cơ bản vikeybindings bằng cách nhấn <Esc>và sau đó gõ vilệnh như x, cw, vv (Bạn có thể lấy lại trong chế độ chèn bằng cách nhấn i.)

Thậm chí tốt hơn và phù hợp hơn với câu hỏi này, bạn có thể mở Vim để tạo trực tiếp nội dung dòng lệnh của mình. Chỉ cần gõ <Esc>vvà bạn sẽ nhận được một bộ đệm Vim trống. Khi bạn lưu và thoát, đó lệnh trên dòng lệnh của bạn và nó được chạy ngay lập tức. Điều này linh hoạt hơn nhiều so với chỉnh sửa trực tiếp trên dòng lệnh vì bạn có thể viết toàn bộ tập lệnh nhỏ nếu muốn.


Vì vậy, ví dụ, nếu bạn muốn viết một số văn bản phức tạp và chuyển nó thành pandoc ngay lập tức, bạn có thể chỉ cần gõ:

<Esc>v

Sau đó chỉnh sửa bộ đệm Vim cho đến khi bạn có một cái gì đó như:

cat <<EOF | pandoc -o file.pdf
stuff for pandoc
more stuff for pandoc
EOF

Sau đó lưu và thoát (với :x) và toàn bộ điều sẽ được chạy dưới dạng lệnh shell.

Nó cũng sẽ có sẵn trong lịch sử lệnh của shell của bạn.


1
Nếu bạn muốn giữ các ràng buộc phím Emacs, bạn vẫn có thể sử dụng Vim để chỉnh sửa các dòng lệnh bằng cách đặt EDITORbiến môi trường thành vimvà nhấn Ctrl-Xtheo sau Ctrl-Etrong khi chỉnh sửa dòng lệnh.
Anthony G - công lý cho Monica

18

Chạy trong một đường ống

Thử:

quickedit() (  trap 'rm ~/temp$$' exit; vim ~/temp$$ >/dev/tty; cat ~/temp$$ )

Điều quan trọng là, để có thể sử dụng vimbình thường, vimcần thiết bị xuất chuẩn là thiết bị đầu cuối. Chúng tôi thực hiện điều đó ở đây với chuyển hướng >/dev/tty.

Vì mục đích bảo mật, tôi đặt tệp tạm thời vào thư mục chính của người dùng. Để biết thêm về điều này, xem Câu hỏi thường gặp của Greg 062 . Điều này giúp loại bỏ sự cần thiết phải sử dụng tên tệp tối nghĩa.

Thí dụ:

Khi vimmở, tôi gõ This function succeeded.và lưu tệp. Kết quả trên màn hình trông như sau:

$ quickedit | grep succeeded
This function succeeded.

Mặc dù đầu ra của quickeditđược chuyển hướng đến một đường ống, vimvẫn hoạt động bình thường vì chúng tôi đã cấp cho nó quyền truy cập trực tiếp /dev/tty.

Chạy một chương trình từ trong vim

Như tôi đã đề cập trong các bình luận, vim có thể dẫn một tập tin vào một lệnh. Từ trong vim, ví dụ, ban hành lệnh :w !pandoc -o file.pdf(Lưu ý: khoảng trắng giữa w và! Là điều cần thiết).


2
Câu trả lời tốt đẹp. Câu hỏi này trực tiếp giải quyết câu hỏi của người dùng và cung cấp một giải pháp nhanh chóng và thanh lịch: chuyển hướng vim sang / dev / tty! Đơn giản!
Mike S

Tôi đang sử dụng Zsh; trap '...' exitthất bại nhưng trap '...' EXITdường như để làm việc Tôi không biết nhiều về bẫy, nhưng cách tiếp cận chung của tôi đối với các tệp tạm thời là sử dụng mktmp [--suffix=...]. Ngoài ra, vim <outfile> -c '...' >/dev/ttychạy như bình thường cho đến khi tệp được tải, sau đó thực thi chuỗi lệnh đã cho, bao gồm cả :wqnếu bạn muốn bỏ qua giai đoạn chỉnh sửa. Tôi cũng đã sử dụng set | grep -a EXITvà tìm thấy signals=(EXIT ... DEBUG).
John P

5

Đảm bảo rằng nó vimđược đặt làm trình chỉnh sửa mặc định của bạn (ví dụ: export EDITOR=vimtrong .bash_profilehoặc hoặc sau .bashrcđó, tại bất kỳ dấu nhắc nào, bạn có thể nhập Ctrl- Xtheo sau Ctrl- E. Điều này sẽ mở dòng lệnh hiện tại của bạn trong trình vimchỉnh sửa được định cấu hình của bạn (ví dụ ). thoát ra và lệnh sẽ được thực thi như thể bạn đã gõ nó trên dòng lệnh, bao gồm các đường ống và tương tự.

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.