การใช้เคอร์เซอร์หลายตัวไม่ใช่สิ่งที่มีความจำเป็น
ดังที่ฉันได้กล่าวไว้ในความคิดเห็นโดยใช้เคอร์เซอร์หลายตัว (แม้จะมีปลั๊กอิน) ไม่ใช่ "ตามวิธี Vim" ฉันเข้าใจโดยสิ้นเชิงว่ามันน่าสนใจสำหรับคนที่มาจาก Sublime-Text แต่คุณมักจะพบทางเลือกที่อย่างน้อย มีประสิทธิภาพด้วยคุณสมบัติในตัวของ Vim
แน่นอนว่าการหาโซลูชันทางเลือกเหล่านี้ไม่ใช่เรื่องง่ายเสมอไปและบางครั้งก็ต้องใช้เวลา แต่มันจะง่ายขึ้นเมื่อใช้ Vim และคุณจะเห็นว่าเมื่อเวลาผ่านไป
เยี่ยมมาก แต่ฉันจะหาวิธีอื่นได้อย่างไร
ไม่มีคำตอบสากลเนื่องจากขึ้นอยู่กับสิ่งที่คุณพยายามจะทำฉันจะลองให้คำแนะนำเกี่ยวกับสิ่งแรกที่จะลอง:
คำสั่ง dot .
คำสั่ง Dot น่าจะเป็นหนึ่งในเครื่องมือที่ทรงพลังที่สุดใน Vim มันช่วยให้เราสามารถทำซ้ำการเปลี่ยนแปลงครั้งล่าสุดได้ ฉันไม่สามารถอธิบายได้ดีไปกว่า Drew Neil ในกลุ่ม Vim ของเขา ฉันคิดว่า Vimmer ทุกคนควรพิจารณาอ่านหนังสือเล่มนี้
จุดแข็งของคำสั่งนี้คือการเปลี่ยนแปลงครั้งล่าสุดอาจเป็นการกระทำที่ทำงานกับตัวอักษรบรรทัดหรือไฟล์ทั้งหมด ตัวอย่างเช่นการเปลี่ยนแปลงสามารถคั่นด้วยช่วงเวลาที่คุณเข้าสู่โหมดแทรกและช่วงเวลาที่คุณกลับไปที่โหมดปกติ
โดยที่ในใจมันเป็นเรื่องง่ายที่จะทำสิ่งที่คุณต้องการจะทำกับ multicursor:
ก่อนอื่นมาตั้งสภาพแวดล้อมของเรากันเถอะเขียนตามที่คุณแนะนำ
\section[]{}
จากนั้นทำการเปลี่ยนแปลงที่ทำซ้ำได้
เคอร์เซอร์เปิดอยู่}
กดF[
เพื่อกลับไปที่[
อักขระ จากนั้นเข้าสู่โหมดแทรกด้วยi
และพิมพ์My first section in this book
แล้วกลับสู่โหมดปกติด้วยESC
:
\section[My first section in this book]{}
และนี่คือส่วนเวทย์มนตร์: ลองพิมพ์f{
เพื่อวางเคอร์เซอร์บน{
ตัวละครและกด.
เพื่อทำการเปลี่ยนแปลงล่าสุดซ้ำ:
\section[My first section in this book]{My first section in this book}
ความท้าทายทั้งหมดของคำสั่ง dot คือการเรียนรู้วิธีการเปลี่ยนแปลงที่ทำซ้ำได้: มันจะมาพร้อมกับ Vim grokking แต่พื้นฐานคือการเข้าใจวิธีการเปลี่ยนแปลงของคุณในทางที่ทำซ้ำได้
ยกตัวอย่างเช่นการแทรกลำไส้ใหญ่กึ่งที่ท้ายบรรทัดที่คุณจะชอบใช้
แทนA;
$a;
ทำไม?
เนื่องจากA;
สร้างการกระทำแบบอะตอมมิกดังนั้นเมื่อคุณใช้.
ในบรรทัดอื่นไม่ว่าคุณจะอยู่ที่ไหนในบรรทัดคุณจะแทรกเครื่องหมายโคลอนกึ่งท้ายที่ท้าย โดยที่เมื่อ$a;
คุณใช้คุณแบ่งการเปลี่ยนแปลงออกเป็นสองส่วน$a
และการแทรก;
ดังนั้นหากคุณใช้การเปลี่ยนแปลง.
จะเป็นการแทรกเครื่องหมายโคลอนกึ่งบนตำแหน่งปัจจุบันของเคอร์เซอร์
หมายเหตุn.
สูตรวิเศษในกลุ่มคือ เวิร์กโฟลว์ที่ยอดเยี่ยมจริงๆคือ:
- ค้นหาสถานที่ที่คุณต้องการแก้ไข
/pattern
- ทำการแก้ไขที่ทำซ้ำได้ของคุณ
- ใช้
n
เพื่อไปยังสถานที่ถัดไปเพื่อแก้ไข
- ใช้
.
เพื่อแก้ไขซ้ำ
- ทำซ้ำสองขั้นตอนสุดท้าย: คุณคือราชาแห่งโลก (หรืออย่างน้อยก็มีการแก้ไข)
แมโคร
มาโครเป็นอีกหนึ่งเครื่องมือที่มีความสำคัญอย่างยิ่งใน Vim เนื่องจากช่วยให้คุณสามารถบันทึกลำดับการกดแป้นและทำซ้ำราวกับว่าคุณพิมพ์อีกครั้ง
ฉันจะใช้กรณีการใช้งานครั้งที่สองของคุณ:
variable1 = 2
my_variable2 = 12
var3 = 14
สิ่งสำคัญคือการเรียนรู้วิธีทำให้มาโครของคุณมีประสิทธิภาพ (ฉันจะยกตัวอย่างการนับหลังจาก):
variable1.someStuff = 2
my_variable2 = 12
var3 = 14
- ตอนนี้คุณสามารถใช้แมโครเพื่อทำซ้ำการแก้ไขของคุณ
@q
ในขณะที่คุณอยู่ในสายที่เหมาะสมในการแก้ไขคุณก็สามารถดำเนินการแมโครด้วย ตามที่เราต้องการเรียกใช้งานสองครั้งคุณสามารถใช้2@q
และคุณจะได้รับผลลัพธ์ต่อไปนี้:
variable1.someStuff = 2
my_variable2.someStuff = 12
var3.someStuff = 14
หมายเหตุ 1อย่างที่คุณอาจสังเกตเห็นการใช้0ea
ที่จุดเริ่มต้นของแมโครนั้นสำคัญมาก แน่นอนถ้าคุณวางเคอร์เซอร์ที่ท้ายคำแรกก่อนที่จะบันทึกแมโครและดำเนินการอีกครั้งผลลัพธ์ของคุณจะเป็นดังนี้:
variable1.someStuff = 2
my_variable2 = 12.someStuff
var3 = 14.someStuff
เมื่อเคอร์เซอร์ของคุณข้อความจะถูกแทรกที่ตำแหน่งเคอร์เซอร์หลังจากเปลี่ยนบรรทัด (เช่นจุดสิ้นสุดของบรรทัดในกรณีนี้)
หมายเหตุ 2มาโครนั้นทรงพลังอย่างยิ่งและคุณสามารถสร้างมาโครแบบเรียกซ้ำเมื่อคุณพอใจกับมัน มาโครที่นี่อาจเป็น:
`0ea.someStuff<Esc>j@q`
สุดท้าย@q
จะได้เรียกมาโครด้วยตัวเองแทนการใช้2@q
; คุณเพิ่งได้ใช้@q
และงานทั้งหมดจะเสร็จสิ้น
บล็อกภาพ
นี่คือเคล็ดลับอื่นที่ไม่ได้นำไปใช้โดยตรงกับกรณีการใช้งานของคุณ แต่อาจมีประโยชน์มากในการแก้ไขบรรทัดจำนวนมากในเวลาเดียวกัน มารับสารสกัดของรหัส CSS นี้:
li.one a{ background-image: url('/images/sprite.png'); }
li.two a{ background-image: url('/images/sprite.png'); }
li.three a{ background-image: url('/images/sprite.png'); }
เกิดอะไรขึ้นถ้าคุณย้ายไปรต์จากimages
ไปcomponents
?
ดีที่คุณสามารถวางเคอร์เซอร์บนi
ของและกดimages
<C-v>
นี่จะเป็นการเริ่มโหมดบล็อกภาพซึ่งอนุญาตให้เลือกบล็อกได้ ตอนนี้คุณสามารถพิมพ์t/
เพื่อเลือกคำที่คุณต้องการเปลี่ยนและ2j
เพื่อเลือกคำที่เกิดขึ้นทั้งหมด
หลังจากนั้นคุณก็ต้องพิมพ์ที่จะเปลี่ยนคำแล้วc
components
เมื่อคุณออกจากโหมดแทรกคุณจะเห็น:
li.one a{ background-image: url('/components/sprite.png'); }
li.two a{ background-image: url('/components/sprite.png'); }
li.three a{ background-image: url('/components/sprite.png'); }
คำสั่งระดับโลก
คำสั่งโกลบอลเป็นเครื่องมือที่อนุญาตให้ใช้คำสั่ง ex mode บนบรรทัดที่จับคู่รูปแบบอีกครั้งซึ่งเป็นวิธีที่ดีในการใช้การเปลี่ยนแปลงแบบเดียวกันในสถานที่ที่แตกต่างกันโดยไม่ต้องใช้เคอร์เซอร์หลายตัว
ไวยากรณ์มีดังต่อไปนี้:
:[range] g / pattern / command
สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับพารามิเตอร์โปรดดู[range]
:h :range
ฉันจะไม่บอกรายละเอียดที่นี่ฉันจะเตือนว่ามัน%
หมายถึงไฟล์ทั้งหมด'<,'>
แสดงถึงสิ่งที่เลือกล่าสุดและ1,5
แสดงบรรทัดที่ 1 ถึง 5 ของไฟล์
พารามิเตอร์นี้กำหนดบรรทัดที่จะถูกใช้โดยคำสั่งโกลบอล หากไม่ได้ระบุช่วงไว้คำสั่งโกลบอลจะใช้%
ตามค่าเริ่มต้น
อาร์กิวเมนต์ [pattern] เป็นรูปแบบการค้นหาตามที่คุณคุ้นเคยกับเครื่องมือค้นหา เนื่องจากมันรวมประวัติการค้นหาคุณสามารถปล่อยให้ฟิลด์นี้ว่างและคำสั่งโกลบอลจะใช้รูปแบบการค้นหาล่าสุดในประวัติการค้นหา
ในที่สุดพารามิเตอร์ [command] คือคำสั่ง ex ตามที่คุณอาจคุ้นเคย
ตอนนี้พฤติกรรมของคำสั่งทั่วโลกนั้นค่อนข้างง่าย:
- ทำซ้ำผ่านบรรทัดทั้งหมดที่กำหนดไว้ในพารามิเตอร์ [range]
- หากบรรทัดปัจจุบันตรงกับรูปแบบที่กำหนดให้ใช้คำสั่ง
เนื่องจากพารามิเตอร์ [command] เป็นคำสั่ง ex คุณสามารถทำสิ่งต่างๆมากมาย ลองใช้โค้ดหลอกต่อไปนี้ซึ่งไม่ค่อยน่าสนใจและมีข้อความดีบั๊กมากมาย:
var myList = null
var i = 0
myList = new List()
echo "List instantiated"
for (i=0; i<10; i++)
myList.Add(i)
echo i . " added to the list"
echo "end of for loop"
ตอนนี้สมมติว่าคุณแน่ใจว่ารหัสนี้ใช้งานได้และคุณต้องการลบecho
ข้อความที่ไร้ประโยชน์เหล่านี้:
คุณสามารถใช้คำสั่งโกลบอลของคุณกับไฟล์ทั้งหมดดังนั้นคุณจะต้องเสริมคำสั่งด้วย%
(หรือไม่มีสิ่งใดนับ%
เป็นช่วงเริ่มต้น)
คุณรู้ว่าบรรทัดที่คุณต้องการลบทั้งหมดตรงกับรูปแบบ echo
คุณต้องการลบบรรทัดเหล่านี้ดังนั้นคุณจะต้องใช้คำสั่ง:delete
ที่สามารถย่อเป็นd
ดังนั้นคุณจะต้องใช้ฟังก์ชั่นต่อไปนี้:
:%global/echo/delete
ซึ่งยังสามารถย่อได้ดังนี้
:g/echo/d
โปรดทราบว่า%
หายไปglobal
จะถูกย่อเป็นg
และเป็นdelete
d
ตามที่คุณอาจจินตนาการถึงผลลัพธ์คือ:
var myList = null
var i = 0
myList = new List()
for (i=0; i<10; i++)
myList.Add(i)
หมายเหตุ 1จุดสำคัญที่ต้องใช้เวลาพอสมควรในการตระหนักคือ
normal
คำสั่งนั้นเป็นคำสั่ง ex ซึ่งหมายความว่าคุณสามารถใช้มันกับคำสั่งทั่วโลก ที่จะมีประสิทธิภาพจริงๆ: n.
ขอบอกว่าผมต้องการที่จะทำซ้ำทุกสายที่มีก้องฉันไม่จำเป็นต้องแมโครหรือแม้กระทั่งสูตรมายากล ฉันสามารถใช้
:g/echo/normal YP
และ voila:
var myList = null
var i = 0
myList = new List()
echo "List instantiated"
echo "List instantiated"
for (i=0; i<10; i++)
myList.Add(i)
echo i . " added to the list"
echo i . " added to the list"
echo "end of for loop"
echo "end of for loop"
หมายเหตุ 2 "เฮ้ถ้าฉันต้องการใช้คำสั่งของฉันในบรรทัดที่ไม่ตรงกับรูปแบบเฉพาะ"
global
มีคำสั่งตรงข้ามvglobal
ยากv
ที่ทำงานเหมือนกันglobal
ยกเว้นว่าคำสั่งจะถูกนำมาใช้ในสายที่ไม่ตรงกับ [รูปแบบ] พารามิเตอร์ วิธีนี้ถ้าเราสมัคร
:v/echo/d
ในตัวอย่างก่อนหน้าของเราเราได้รับ:
echo "List instantiated"
echo i . " added to the list"
echo "end of for loop"
คำสั่งได้ถูกนำมาใช้บนเส้นซึ่งไม่ได้มีdelete
echo
ที่นี่ฉันหวังว่าคำแนะนำเล็กน้อยเหล่านั้นจะทำให้คุณมีความคิดเกี่ยวกับวิธีการกำจัดปลั๊กอินเคอร์เซอร์หลายของคุณและใช้เป็นกลุ่มในวิธี Vim ;-)
ดังที่คุณสามารถจินตนาการได้ว่าตัวอย่างเหล่านี้ค่อนข้างเรียบง่ายและถูกสร้างขึ้นมาเพื่อแสดงให้เห็นว่าเมื่อคุณทำตามวิธีการที่เป็นกลุ่มคุณไม่ค่อยต้องการเคอร์เซอร์หลายตัว คำแนะนำของฉันจะเป็นเมื่อคุณพบสถานการณ์ที่คุณคิดว่ามันจะมีประโยชน์เขียนลงและใช้เวลาในภายหลังเพื่อหาทางออกที่ดีกว่า 99% ของเวลาที่คุณจะได้พบกับวิธีที่เร็ว / มีประสิทธิภาพมากขึ้นในที่สุด
นอกจากนี้ฉันจะทำซ้ำตัวเองอีกครั้ง แต่ฉันสนับสนุนให้คุณอ่าน
Practical Vimโดย Drew Neil เพราะหนังสือเล่มนี้ไม่เกี่ยวกับ "วิธีการทำสิ่งนั้นหรือสิ่งนี้ใน Vim" เป็นเรื่องเกี่ยวกับ "วิธีการเรียนรู้ที่จะคิดด้วยวิธี Vim" ซึ่งจะช่วยให้คุณสร้างโซลูชันของคุณเองเพื่อแก้ไขปัญหาในอนาคตของคุณในทางที่ดี
ป.ล.ขอบคุณเป็นพิเศษสำหรับ @Alex Stragies สำหรับงานแก้ไขและการแก้ไขที่เขาทำกับโพสต์อันยาวนานนี้