ฉันจะแมป d [นับ] d ได้อย่างไร


18

NB คำสั่งนี้ไม่ได้ซ้ำกับคำสั่ง "d3fg" อย่างไร โปรดอ่านก่อนลงคะแนนเพื่อปิด!

ฉันได้มาบิตของอับจนในของฉันการแสวงหาที่จะได้รับการลบการทำงานเล็ก ๆ เช่นคนใหญ่ ปัญหาที่ฉันมีคือฉันไม่สามารถหาวิธีการแมปคำสั่งd3dใหม่ได้ ที่จริงแล้วฉันไม่สามารถเข้าใจได้ว่าพวกเขาทำงานอย่างไรตั้งแต่แรกและไม่พบการกล่าวถึงพวกเขาในความช่วยเหลือของ Vim *

d3jตรงไปตรงมา: มันใช้dกับการ3jเคลื่อนไหว

3ddตรงไปตรงมา: มันรันddคำสั่งด้วย "count" ของ 3

d3d ดูเหมือนว่ามันควรจะตรงไปตรงมามันใช้dโอเปอเรเตอร์กับ ... แต่อะไรนะ3d? มันไม่ใช่การเคลื่อนไหว หากคุณพิมพ์3dด้วยตัวเอง Vim จะถือว่าเป็นนับตามด้วยโอเปอเรเตอร์และรออย่างอดทนสำหรับการป้อนข้อมูลเพิ่มเติม

และคุณไม่สามารถใช้โอเปอเรเตอร์กับผู้ให้บริการรายอื่นได้ ddไม่ได้อธิบายไว้ในความช่วยเหลือเป็นลำดับของผู้ให้บริการสองราย มันเป็นคำสั่งสองแป้นที่แยกต่างหาก (เปรียบเทียบdcซึ่งไม่ทำอะไรเลย)

นอกจากนี้ยังไม่ปรากฏว่าในกรณีที่การวางตำแหน่งการนับมีความยืดหยุ่นสำหรับคำสั่งที่ต้องใช้การกดแป้นสองครั้ง: 2gjเลื่อนเคอร์เซอร์ลงสองบรรทัดหน้าจอ แต่ละg2jทิ้งการกดปุ่มสองครั้งแรกทั้งหมดและเลื่อนเคอร์เซอร์ลงหนึ่งบรรทัด

แล้วมันทำงานอย่างไร นี่เป็นกรณีพิเศษในรหัสภายในของ Vim ใช่ไหม มีวิธีใดบ้างที่ฉันสามารถสร้างการd[count]dแมปได้?

แก้ไข : มันเป็นวัตถุข้อความหรือไม่ :h text-objectsไม่รวมไว้ในรายการ "คำสั่งการเลือกวัตถุข้อความ" แต่จะรวม dd ในรายการการลบ "จัดกลุ่มจากวัตถุขนาดเล็กไปจนถึงวัตถุขนาดใหญ่" และd2awจะลบคำที่อยู่ใต้เคอร์เซอร์และคำต่อไปนี้ ในทางกลับกันc2dไม่ทำอะไรเลย

* ฉันแน่ใจว่าต้องมีการกล่าวถึงบางอย่าง แต่ไม่สามารถหาได้ ฉันได้อ่าน:help deleting, :help motion.txtและพยายาม:helpgrep dNdทุกค่าของ N 1-9


2
ฉันคิดว่าการdกระทำครั้งสุดท้ายเป็นการยืนยัน d3<CR>ดังนั้นจึงเป็นเช่นเดียวกับ y3yและใช้c3cงานได้เหมือนกัน ... ฉันไม่สามารถหาเอกสารใด ๆ ได้ใน Vim: help, vi (1), nvi (1), หรือ POSIX spec ... มันทำงานเหมือนกันในviและnvibtw .
Martin Tournoij

1
ในทางที่เป็นเหมือนdd นำเคอร์เซอร์ไปที่ non-blank แรกบนบรรทัดที่( -1) th ลง แต่มัน linewise ดังนั้นเมื่อจับคู่กับโอเปอเรเตอร์มันจะทำงานบนทั้งบรรทัด ด้วยเหตุนี้จึงทำให้รู้สึกว่าการนับสามารถปรากฏระหว่างสองs d__[count]d
tommcdo

คำตอบ:


28

โหมดที่รอดำเนินการ

ระหว่างดำเนินการพิมพ์ (เช่นd, cหรือgU) และการเคลื่อนไหว (เช่นw, i}หรือ/foo<CR>) เป็นกลุ่มผู้ประกอบการที่อยู่ในโหมดที่รอ คุณสามารถสร้างการแมปสำหรับการนี้โดยใช้และ:omap:onoremap

ในตัวอย่างของฉันฉันจะ map ผู้ประกอบการที่รอการd wนี่เป็นตัวเลือกแบบสุ่มเพราะฉันไม่รู้ว่าคุณต้องการใช้อะไร

สร้าง omap

มาสร้างแผนที่สำหรับdในโหมดรอดำเนินการ ฉันจะสมมติว่าเรากำลังเขียน VimScript ที่นี่ (เช่นในของคุณ.vimrc) ดังนั้นฉันจะไม่นำหน้า:s

onoremap d w

ทำให้นี้ทำหน้าที่เหมือนdd dwนอกจากนี้ยังทำให้การกระทำเช่นd[count]d d[count]wแต่ฉันคิดว่าคุณไม่ต้องการส่งผลกระทบต่อพฤติกรรมของdd(เช่นไม่มี[count]จำหน่าย)

การแมปนิพจน์

การแม็พนิพจน์ช่วยให้คุณประเมินนิพจน์ VimScript เพื่อสร้างทางด้านขวาของการแม็พ นิพจน์ควรประเมินเป็นสตริง การแม็พนิพจน์ถูกแสดงโดย<expr>คีย์เวิร์ด

Vim ยังมีตัวแปรบิวด์อินบางตัวที่สามารถบรรจุข้อมูลได้หลายครั้งและมักจะมีประโยชน์ในระหว่างการจับคู่ หนึ่งในนั้นคือv:countซึ่ง[count]จ่ายให้กับผู้ใช้งานหรือการเคลื่อนไหว

เรามารวมกันทั้งหมด ถ้าไม่มี[count]จะถูกส่งให้จะเป็นv:count 0เราสามารถบอกการทำแผนที่ของเราเพื่อใช้dในกรณีนั้น

onoremap <expr> d v:count == 0 ? 'd' : 'w'

ตอนนี้ddทำงานเหมือนเริ่มต้น (ลบบรรทัด) แต่พฤติกรรมเช่นd[count]d d[count]wเย็น!

จำกัด การใช้งานหลังจากdผู้ควบคุมเครื่อง

คุณอาจสังเกตเห็นบางสิ่งบางอย่าง ตอนนี้cdก็มีพฤติกรรมเหมือนcwกัน สิ่งนี้อาจไม่เป็นปัญหา แต่เพื่อความสมบูรณ์ขอ จำกัด ไว้เพื่อให้สามารถทำงานได้หลังจากdผู้ดำเนินการเท่านั้น

Vim มีตัวแปรอื่นv:operatorซึ่งมีโอเปอเรเตอร์ที่ใช้ล่าสุด ลองตรวจสอบด้วยก่อนทำสิ่งใดเป็นพิเศษ

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : 'w'

หมายเหตุ:เนื่องจาก:mapคำสั่งสามารถถูกล่ามโซ่ด้วย|เราจะต้องหลบหนีพวกเขาในการแสดงออกของเราที่นี่ ดังนั้นผู้ประกอบการตรรกะหรือจะกลายเป็น||\|\|

เจ๋งมากcdและc[count]dกลับมาทำอะไรเหมือนที่เคยทำ นี่เป็นสิ่งที่ดีเพื่อให้ปลั๊กอินอื่น ๆ สามารถกำหนดcdได้

ฉันไม่ต้องการเพียงแค่ลบการเคลื่อนไหวอื่น ๆ

หากคุณต้องการแมปd[count]dกับสิ่งที่แตกต่างอย่างสิ้นเชิงไม่มีอะไรเกี่ยวข้องกับการลบข้อความเราสามารถทำให้มันใช้ได้เช่นกัน

เมื่อคุณพิมพ์คำสั่งที่อยู่ในโหมดปกติและคุณเริ่มพิมพ์คำสั่งโดยไม่ได้ตั้งใจให้คุณสามารถกด<Esc>เพื่อยกเลิกคำสั่งที่ เช่นเดียวกับการแมปของคุณ

ขอให้d[count]dเปลี่ยนบรรทัดปัจจุบันกับสิ่งที่[count]เป็น

onoremap <expr> d (v:count == 0 \|\| v:operator != 'd') ? 'd' : '<Esc>cc' . v:count . '<Esc>'

ส่วนสุดท้ายของการทำแผนที่คือการแสดงออก <Esc>cc' . v:count . '<Esc>'VimScript: นั่นคือ<Esc>การยกเลิกdคำสั่งที่รอดำเนินการจากนั้นccเปลี่ยนบรรทัดปัจจุบันv:countเพื่อพิมพ์ค่าของ[count](ในโหมดแทรก) และ<Esc>เพื่อกลับสู่โหมดปกติ โปรดทราบว่าเรากำลังสร้างสตริงที่นี่ใช้ตัวดำเนินการเรียงต่อกัน .VimScript,


กรณีการใช้งานจริงของคุณอาจจะแตกต่างจากที่ฉันได้อธิบายไว้ที่นี่ แต่หวังว่านี่จะช่วยให้คุณได้ลูกบอลกลิ้ง

Happy Vimming!


คำตอบที่ดี! upvoted ฉันเชื่อมโยงกับกรณีการใช้งานของฉัน (เช่นใน vi.SE) เมื่อเริ่มต้นคำถาม แต่ฉันคิดว่าคุณต้องพลาด โดยทั่วไปฉันต้องทำ:omap d d(!) แต่น่าเสียดายที่โหมดรอดำเนินการไม่สามารถเข้าถึงได้จริงเนื่องจากการแมปของฉันสำหรับ d ที่ตั้งค่าฟังก์ชันตัวดำเนินการที่กำหนดเอง หวังว่าจะเป็นไปได้ที่จะปรับแต่งสิ่งต่าง ๆ เพื่อให้d3dทำงานตามที่ควรจะเป็น (แจ้งให้เราทราบหากคุณมีข้อคิดเห็นหรือรู้สึกอิสระที่จะโพสต์คำตอบที่สมบูรณ์ให้กับคำถามอื่นหากคุณต้องการ) หากฉันไม่สามารถหาคำตอบได้ในเร็ว ๆ นี้ฉันจะยอมรับและโพสต์คำถามอื่นที่เจาะจงกว่านี้ ขอบคุณ!
รวย

1
จริงๆแล้วในความคิดที่สองฉันยอมรับในตอนนี้ คุณอธิบายทั้งวิธีการสร้างแผนที่และวิธีการทำงานภายใต้ประทุนซึ่งเป็นสองสิ่งที่ฉันถาม
รวย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.