จะใช้คำสั่งภายนอกใน Vim เพื่อแก้ไขคำและบรรทัดที่เลือกได้อย่างไร


22

สิ่งที่ฉันพบว่ามีประโยชน์ในบรรณาธิการอื่น ๆ คือความสามารถในการ:

  • นำข้อความที่เลือก
  • เรียกใช้คำสั่งภายนอกและส่งผ่านส่วนที่เลือกไปยัง stdin
  • ใช้คำสั่งภายนอกstdoutและแทนที่ส่วนที่เลือกปัจจุบันด้วย

วิธีนี้คุณสามารถเขียนเครื่องมือข้อความที่มีประโยชน์ซึ่งทำงานกับการเลือกโดยใช้ภาษาใดก็ได้ที่สามารถทำ io พื้นฐานได้

สิ่งนี้สามารถทำได้ด้วยเสียงเรียกเข้าโดยใช้การเลือก? ... อักขระเดี่ยวคำย่อหน้า ... ฯลฯ

(โดยตรงในบรรทัดคำสั่งหรือผ่านการเชื่อมโยงคีย์?)


บันทึก

คำสั่งเช่น!sortทำงานในระดับบรรทัดเหตุผลที่ฉันถามคำถามนี้เพราะฉันต้องการที่จะดำเนินการในการเลือก (เช่นข้อความที่จะถูกลบหากxกด)

คำตอบ:


17

ฉันพบว่าบ่อยครั้งวิธีที่ง่ายที่สุดคือการใช้โหมดภาพด้วยv(หรือพิมพ์ใหญ่Vเพื่อเลือกทั้งบรรทัด) และเลือกข้อความที่คุณต้องการไพพ์

จากนั้นพิมพ์:

:!cat

สิ่งนี้ไม่ได้ทำอะไรที่มีประโยชน์เช่นนี้ คำสั่งที่มีประโยชน์ที่ฉันใช้บ่อยคือ:

:!python -m json.tool

เพื่อจัดรูปแบบ JSON

คุณยังสามารถพิมพ์ (โดยไม่ใช้โหมดภาพ):

:<range>!command

ตัวอย่างเช่นสำหรับไฟล์ทั้งหมด:

:%!python -m json.tool

หรือสำหรับบรรทัดปัจจุบัน:

:.!python -m json.tool

เครื่องมือที่มีประโยชน์อีกอย่างที่ใช้กับสิ่งนี้คือsortคำสั่ง
Cody Poll

4
ผิด @CodyPoll อะไรกับกลุ่มของ:sort?
Martin Tournoij

5
@Carpetsmoker คำสั่งการเรียงลำดับภายนอกมีตัวเลือกเพิ่มเติมมากมายและ (ขึ้นอยู่กับตำแหน่งที่ตั้ง ฯลฯ ) สร้างใบสั่งต่างกัน
Derobert

1
วิธีนี้ใช้ไม่ได้กับการเลือกคำเดียวในบรรทัด (ดูคำถามที่กล่าวถึงการเลือกระดับคำ)
ideasman42

@ ideasman42 ถูกต้อง ... ฉันคิดว่าฉันอ่านคำถามนี้เป็น "บรรทัดหรือคำว่า" แทนที่จะเป็น "เส้นและคำ" ... ในกรณีใด ๆ การทำสิ่งนี้ด้วยคำพูดนั้นไม่ชัดเจนโปรแกรม UNIX ทำงานบนบรรทัดและเป็นกลุ่ม ก็ไม่มีข้อยกเว้น ฉันทำการทดลองและเรียงลำดับบางอย่างมีวิธีแก้ปัญหา แต่มันใช้งานไม่ได้ดี ... บางทีวิธีการของฉันอาจผิดไปดังนั้นฉันจะทิ้งมันไว้สองสามวันแล้วกลับไปหามันในภายหลัง
Martin Tournoij

7

ฉันเขียนปลั๊กอินชื่อexpress.vimที่สามารถช่วยได้ ปลั๊กอินกำหนดโอเปอเรเตอร์g=ที่ให้คุณประเมินนิพจน์ VimScript เหนือการเคลื่อนไหว (หรือการเลือกภาพ) มันแจ้งให้แสดงออกซึ่งคุณสามารถใช้v:valเป็นตัวยึดสำหรับข้อความที่ครอบคลุมโดยการเคลื่อนไหว (หรืออีกครั้งการเลือกภาพ)

ในกรณีนี้การแสดงออกที่มีประโยชน์จะใช้system()ฟังก์ชั่นซึ่งเรียกใช้คำสั่งภายนอก

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

(ที่นี่ฉันใช้trเป็นคำสั่งภายนอกตัวอย่างง่ายๆ)

วิธีใช้ express.vim สำหรับปัญหานี้คือการเลือกข้อความด้วยโหมด Visual จากนั้นพิมพ์g=ตามด้วยนิพจน์นั้นจากนั้นกดEnter:

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

ฉันจะยอมรับมันไม่ใช่เรื่องง่ายที่จะใช้ (ในความเป็นจริงผมไม่ค่อยใช้นี้ปลั๊กอินตัวเอง!) !ฉันกำลังพิจารณาการเพิ่มทางลัดในการเรียกคำสั่งภายนอกเช่นการเริ่มต้นการแสดงออกด้วย ฉันจะโพสต์การอัปเดตที่นี่ถ้าฉันทำอย่างนั้น

แก้ไข

ฉันแก้ไข express.vim เพื่อรักษานิพจน์ที่เริ่มต้นด้วย!คำสั่งภายนอก ดังนั้นการเกาะติดกับtrตัวอย่างด้านบนจึงง่ายกว่ามาก หลังจากการเลือกภาพให้พิมพ์ดังต่อไปนี้:

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

คำอธิบาย:

  1. เรียกใช้ตัวดำเนินการด่วนด้วย g=
  2. ป้อน!tr a-z A-Zเป็นนิพจน์
  3. กด Enter

4

คุณกำลังมองหาคำสั่งตัวกรองเป็นกลุ่ม :help filterดู นี่คือเอกสารที่เกี่ยวข้อง:

!{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]

ดังนั้นการพิมพ์5!!sortจะเรียงลำดับ 5 บรรทัดถัดไปที่เริ่มต้นจากเคอร์เซอร์


เป็นไปได้ไหมที่จะกรองคำเดียว? (ไม่ใช่ระดับบรรทัด)
ideasman42

ใช่. ตัวเลือกที่สาม (โหมดภาพ) ทำงานสำหรับทุกสิ่งที่ถูกเน้น (คำ, เส้นบางส่วน, หลายบรรทัด, บล็อกสี่เหลี่ยม ฯลฯ )
Sameer

1
ตัวเลือกที่สามยังกรองบรรทัดทั้งหมด หากคุณเลือกคำเดียวและกรองเช่นผ่านถึงtr [:lower:] [:upper]กว่ากลุ่มจะ upcase ไม่เพียง แต่คำนี้ แต่ทั้งบรรทัด
มาเรีย

0

โปรดทราบว่าสามารถทำได้ด้วย:

  1. มองเห็นสิ่งที่คุณต้องการ
  2. s^R=system('tr a-z A-Z', @")[:-2]^M(ด้วย^Rการเป็น CTRL + R และ ^ M กำลังเข้าสู่)

นอกจากนี้ยังสามารถทำงานกับสิ่งที่ไม่เลือก + ci"^R=...แทนที่เช่น


เมื่อรันสิ่งนี้กับการเลือกข้อความหลายบรรทัด (หลังจากกดvและย้ายเคอร์เซอร์) ฉันได้รับข้อผิดพลาดE16: Invalid range\nE16: Invalid range\nE476: Invalid command(บน Linux ดังนั้นtrและคำสั่งพื้นฐานอื่น ๆ ที่มีอยู่)
ideasman42

คุณกดsที่จะเข้าสู่โหมดแทรกหรือ:sคำสั่ง?
Luc Hermitte

อย่าสงสัย แต่ยังไม่แน่ใจว่าคุณหมายถึงอะไรตัวอย่างอาจแสดงวิธีการเชื่อมโยงกับคีย์
ideasman42

คุณกดโดยตรงsจากโหมดภาพหรือคุณกด:ครั้งแรก? ไม่มี:ส่วนเกี่ยวข้องกับลำดับของคีย์ที่ฉันเขียน การแมปจะเป็น: vnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>.
Luc Hermitte
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.