Làm cách nào để sử dụng lệnh bên ngoài trong Vim để sửa đổi các từ và dòng đã chọn?


22

Một cái gì đó tôi thấy hữu ích trong các trình soạn thảo khác là khả năng:

  • lấy văn bản đã chọn
  • chạy một lệnh bên ngoài và chuyển lựa chọn đến nó stdin
  • nhận các lệnh bên ngoài stdoutvà thay thế lựa chọn hiện tại với nó.

Bằng cách này, bạn có thể viết các công cụ văn bản hữu ích hoạt động trên vùng chọn bằng bất kỳ ngôn ngữ nào có thể thực hiện io cơ bản.

Làm thế nào điều này có thể được thực hiện với vim bằng cách sử dụng lựa chọn? ... một ký tự, từ, đoạn ... vv

(Trực tiếp trong dòng lệnh, hoặc thông qua một ràng buộc chính?)


chú thích

Các lệnh như !sortlàm việc ở cấp độ dòng, lý do tôi hỏi câu hỏi này là vì tôi muốn thao tác trên vùng chọn. (nghĩa là văn bản sẽ bị xóa nếu xđược nhấn).

Câu trả lời:


17

Tôi thấy rằng thường thì cách dễ nhất là sử dụng chế độ trực quan với v(hoặc viết hoa Vđể chọn toàn bộ dòng) và chọn văn bản bạn muốn đặt.

Sau đó gõ:

:!cat

Điều này không làm bất cứ điều gì hữu ích, như vậy. Một lệnh hữu ích tôi thường sử dụng là:

:!python -m json.tool

để định dạng JSON.

Bạn cũng có thể chỉ cần gõ (không có chế độ trực quan):

:<range>!command

Ví dụ: đối với toàn bộ tệp:

:%!python -m json.tool

Hoặc cho dòng hiện tại:

:.!python -m json.tool

Một công cụ thực sự hữu ích khác để sử dụng với điều này là sortlệnh.
Thăm dò ý kiến ​​Cody

4
@CodyPoll Có gì sai với Vim :sort?
Martin Tournoij 4/2/2015

5
@Carpetsmoker Lệnh sắp xếp bên ngoài có nhiều tùy chọn hơn và (tùy thuộc vào miền địa phương, v.v.) tạo ra một thứ tự khác nhau.
derobert

1
Điều này không hoạt động để chọn một từ duy nhất trong một dòng. (xem câu hỏi đề cập đến lựa chọn cấp độ từ)
ideaman42

@ ideaman42 Phải ... Tôi nghĩ ban đầu tôi đọc câu hỏi này là "dòng hoặc từ" thay vì "dòng từ" ... Trong mọi trường hợp, làm điều này với các từ là không rõ ràng, các chương trình UNIX hoạt động trên các dòng và Vim cũng không ngoại lệ. Tôi đã thực hiện một số thử nghiệm và sắp xếp một giải pháp, nhưng nó không hoạt động tốt ... Có lẽ cách tiếp cận của tôi là sai, vì vậy tôi sẽ để nó trong vài ngày và quay lại với nó sau.
Martin Tournoij

7

Tôi đã viết một plugin có tên express.vim có thể giúp với điều này. Plugin xác định toán tử g=cho phép bạn đánh giá biểu thức VimScript qua chuyển động (hoặc lựa chọn Visual). Nó nhắc một biểu thức, trong đó bạn có thể sử dụng v:valnhư một trình giữ chỗ cho văn bản được bao phủ bởi chuyển động (hoặc, một lần nữa, lựa chọn trực quan).

Trong trường hợp này, một biểu thức hữu ích sẽ sử dụng system()hàm chạy lệnh bên ngoài.

system('tr a-z A-Z', v:val)

(Ở đây tôi đã sử dụng trnhư một lệnh bên ngoài ví dụ đơn giản.)

Cách sử dụng express.vim cho vấn đề này sẽ là chọn văn bản với chế độ Visual, sau đó nhập g=theo biểu thức đó, sau đó nhấn Enter:

g=system('tr a-z A-Z', v:val)<CR>

Tôi sẽ thừa nhận, nó không dễ sử dụng. (Trên thực tế, tôi hiếm khi sử dụng plugin này cho mình!) Tôi đang xem xét việc thêm một phím tắt để gọi một lệnh bên ngoài, chẳng hạn như bắt đầu biểu thức với !. Tôi sẽ đăng một bản cập nhật ở đây nếu tôi kết thúc việc đó.

CHỈNH SỬA

Tôi đã sửa đổi express.vim để xử lý các biểu thức bắt đầu bằng !các lệnh bên ngoài. Vì vậy, gắn bó với trví dụ, những điều trên trở nên đơn giản hơn rất nhiều. Sau khi chọn Visual, gõ như sau:

g=!tr a-z A-Z<CR>

Giải trình:

  1. Gọi toán tử tốc hành với g=
  2. Nhập !tr a-z A-Zdưới dạng biểu thức
  3. nhấn Enter

4

Bạn đang tìm kiếm các lệnh lọc trong Vim. Xem :help filter. Đây là tài liệu liên quan:

!{motion}{filter}   Filter {motion} text lines through the external
                    program {filter}.
!!{filter}          Filter [count] lines through the external program
                    {filter}.
{Visual}!{filter}   Filter the highlighted lines through the external
                    program {filter} (for {Visual} see |Visual-mode|).
                    {not in Vi}

:{range}![!]{filter} [!][arg]               *:range!*
                    Filter {range} lines through the external program
                   {filter}.  ...[See documentation for details]

Vì vậy, gõ 5!!sortsẽ sắp xếp 5 dòng tiếp theo bắt đầu từ con trỏ.


Có thể lọc một từ duy nhất? (không phải cấp độ dòng)
ideaman42

Vâng. Tùy chọn thứ ba (chế độ trực quan) hoạt động cho bất cứ điều gì được tô sáng (từ, dòng một phần, nhiều dòng, khối hình chữ nhật, v.v.).
Sameer

1
Tùy chọn thứ ba cũng lọc toàn bộ dòng. Nếu bạn chọn một từ duy nhất và lọc nó, ví dụ, thông qua tr [:lower:] [:upper], vim sẽ nâng cao không chỉ từ này mà cả toàn bộ dòng.
maria s

0

Lưu ý rằng nó có thể được thực hiện với:

  1. trực quan chọn bất cứ điều gì bạn muốn
  2. s^R=system('tr a-z A-Z', @")[:-2]^M(với ^RCTRL + R và ^ M là ENTER)

Nó cũng có thể làm việc với bất cứ thứ gì có lựa chọn + thay thế như thế nào ci"^R=....


Khi chạy nó trên một lựa chọn văn bản nhiều dòng (sau khi nhấn vvà di chuyển con trỏ) tôi gặp lỗi E16: Invalid range\nE16: Invalid range\nE476: Invalid command(trên Linux trvà các lệnh cơ bản khác tồn tại).
ideaman42

Bạn đã nhấn smà đi vào chế độ chèn hoặc :slệnh?
Luc Hermitte

Nghi ngờ không, nhưng cũng không chắc ý của bạn là gì, có lẽ ví dụ này có thể cho thấy cách liên kết này với khóa?
ideaman42

Bạn đánh trực tiếp stừ chế độ trực quan, hay bạn đánh :trước? Không có :liên quan đến chuỗi các phím tôi đã viết. Một ánh xạ sẽ là : vnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>.
Luc Hermitte
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.