ผสานบล็อกด้วยเส้นแทรก


15

มีวิธีเฉพาะในการรวมสองบล็อกข้อความโดย interleaving บรรทัดเช่นผ่านจากนี้

a1
a2
a3
a4
  b1
  b2
  b3
  b4

เพื่อที่:

a1
  b1
a2
  b2
a3
  b3
a4
  b4

ในคำสั่งไม่กี่?

แก้ไข : ฉันชอบโซลูชันของ Sato Katsuraนี่คือวิธีที่ฉันใช้งาน:

function! Interleave()
    " retrieve last selected area position and size
    let start = line(".")
    execute "normal! gvo\<esc>"
    let end = line(".")
    let [start, end] = sort([start, end], "n")
    let size = (end - start + 1) / 2
    " and interleave!
    for i in range(size - 1)
        execute (start + size + i). 'm' .(start + 2 * i)
    endfor
endfunction

" Select your two contiguous, same-sized blocks, and use it to Interleave ;)
vnoremap <pickYourMap> <esc>:call Interleave()<CR>

ตอนนี้ฉันอยากรู้ - กรณีการใช้งานของคุณคืออะไร? คุณปิดกั้นการเปลี่ยนชื่อคำบรรยายสำหรับฤดูกาลทีวีหรือไม่?
VanLaser

@VanLaser ฮ่าฮ่าฉันไม่ได้ ส่วนใหญ่ฉันกำลังแยกวิเคราะห์ผลลัพธ์จากโปรแกรมซึ่งฉันต้องตรวจสอบความสอดคล้องเกี่ยวกับลำดับของการสร้าง / จากนั้นการอ่านวัตถุล่าช้า Interleaving blocks ช่วยให้จับคู่บรรทัดที่สอดคล้องกันในบล็อกเอาต์พุตที่ล่าช้าได้ง่ายขึ้น บางครั้งฉันก็จำเป็นต้องสอดแทรกบรรทัดของรหัสด้วยซ้ำคำแนะนำที่คล้ายกันสำหรับการบันทึกหรือการเปรียบเทียบ การสร้างคำแนะนำเหล่านั้นนั้นทำได้ง่ายด้วยมาโครแล้วแทรกคำเหล่านั้นด้วยโค้ดจริงตอนนี้เพียงแค่กดปุ่มไม่กี่ครั้งด้วยฟังก์ชั่นนี้ซึ่งให้ความรู้สึกที่ยอดเยี่ยม :)
iago-lito

1
@ lago-lito - ขอบคุณสำหรับคำตอบ! ใช่เสียงเรียกเข้านั้นค่อนข้างเอนกประสงค์ :) การแสดงออกของคุณ "การแยกวิเคราะห์ดวงตา" ทำให้ฉันคิดเหมือนกันที่scroll-bindingหน้าต่าง Vim สองบาน
VanLaser

ฉันมีปัญหาในการใช้สิ่งนี้คุณจะเลือกบล็อกทั้งสองต่อเนื่องกันอย่างไร พวกเขาต้องการที่จะอยู่ติดกัน?
cbcoutinho

@cbcoutinho ใช่พวกเขามี :) ฉันไม่แน่ใจว่าคุณสามารถเลือกได้ทั้งสองอย่าง ในตัวอย่างที่ผมเคยแสดงผมวางเคอร์เซอร์ของฉันใน (พูด) b1แล้วผมตีvipเพื่อเลือกก้อนทั้งหมดแล้วซึ่งเป็น,it <map-I've-Picked>มันไม่ทำงานเคียงข้างคุณหรือไม่
iago-lito

คำตอบ:


8

ไม่มีวิธีเฉพาะในการทำ (เท่าที่ฉันรู้) แต่ใช่มันสามารถทำได้ด้วยคำสั่งไม่กี่:

function! Interleave(start, end, where)
    if a:start < a:where
        for i in range(0, a:end - a:start)
            execute a:start . 'm' . (a:where + i)
        endfor
    else
        for i in range(a:end - a:start, 0, -1)
            execute a:end . 'm' . (a:where + i)
        endfor
    endif
endfunction

:call Interleave(5, 8, 1)คุณสามารถเรียกใช้มันด้วย พารามิเตอร์แรกคือบรรทัดแรกที่จะย้ายบรรทัดที่สองเป็นบรรทัดสุดท้ายและบรรทัดที่สามที่จะย้าย คุณอาจต้องการเปิดหมายเลขบรรทัดเพื่อดูว่าคุณกำลังทำอะไร ( :set number)

สิ่งนี้จะถือว่าบล็อกไม่ทับซ้อนกัน ดู:help :moveและ:help range()เข้าใจการทำงานของฟังก์ชัน

อาจมีวิธีที่ดีกว่าในการรับทั้งสองช่วงตึก มีปลั๊กอินที่ลอยอยู่รอบ ๆ ที่ควรให้คุณสลับสองช่วงตึก ฉันจำชื่อปลั๊กอินไม่ได้ แต่ผู้แต่ง (อาจเป็น Dr. Chip ที่มีชื่อเสียง?) ได้คิดมากขึ้นในการค้นหาส่วนต่อประสานมากกว่าที่ฉันทำ :)


หวาน! ฉันต้องการเพียงสองข้อโต้แย้งตั้งแต่สองช่วงตึกอยู่ติดกันและมีขนาดเดียวกัน: และstart sizeด้วยฟังก์ชัน homebrew ที่ดึงค่าเหล่านั้นจากการเลือกมันจะสมบูรณ์แบบ ฉันกำลังทำงานกับมัน :)
iago-lito

crosslink ที่น่าสนใจ? ;)
iago-lito

13

นี่คือทางเลือกอื่น:

:g/^a/+4t .
:+,+5d 

ก่อนอื่นให้คัดลอกบรรทัดที่มี 4 บรรทัดด้านล่างเป็นหลังบรรทัดปัจจุบัน ( :h :t) จากนั้นลบบรรทัด b ต่อเนื่อง ( :h :d)

คำสั่งนี้ดียิ่งขึ้น:

 :g/^a//^\s*b/m .

ซึ่งหมายความว่าสำหรับแต่ละบรรทัดที่เริ่มต้นด้วยการค้นหาบรรทัดถัดไปที่เริ่มต้นด้วย 'b' และย้ายไปด้านล่างบรรทัดปัจจุบัน


1
ฉันได้รับ "E16: ช่วงที่ไม่ถูกต้อง" ในคำสั่งที่สอง ฉันลอง.+,$dแทนและมันก็.+,.+4dใช้ได้ดีเหมือนเดิม
Peter Lewerin

ไม่แน่ใจว่าทำไมสิ่งนี้จึงเกิดขึ้น
Christian Brabandt

1
ไม่มันไม่ อ่าน: h: พิสัย, คุณสามารถใช้การนับโดยตรงแทนการค้นหา regex
Christian Brabandt

2
@ เจนนิเฟอร์-lito เคล็ดลับที่สองเคยทำงาน แต่คุณต้องมีการเปลี่ยนแปลงไปยังอีก/^\s*b :rangeเช่น: เลือก 1st block, execute'<,'>g/^/'>+1m.
dedowsdi

1
@ iago-lito เป็นหลักเหมือนกับคำตอบของคริสเตียน ไม่มีการฮาร์ดโค้ดใด ๆ หากคุณเลือกบล็อกที่ 1 ให้มองเห็นซึ่ง'>+1เป็นจุดเริ่มต้นของบล็อกที่สอง
dedowsdi

3

หากคุณต้องการมีความสนุกสนานเล็กน้อยกับมาโครและทำเครื่องหมายคุณสามารถลองดังนี้:

  • ก่อนนำเครื่องหมาย (ที่นี่a) บนบรรทัดที่มีa1กับma

  • ไปที่บรรทัดที่มีb1และทำเครื่องหมายด้วยmb

  • เริ่มการบันทึกแมโครในการลงทะเบียนที่คุณต้องการ (ที่นี่การลงทะเบียนq) ด้วยqq

  • แทรก folowing ในแมโครของคุณ: ddmb'apjma'b

  • หยุดการบันทึกแมโครด้วย q

  • เล่นได้หลายครั้งตามความจำเป็นกับX@qที่Xคือจำนวนของเวลาที่จะเล่นมัน

วิธีดูรายละเอียดของแมโคร:

dd mb 'a p j ma 'b
 |  |  | | |    |
 |  |  | | |    go back to line marked `b`
 |  |  | | |
 |  |  | | move of one line and replace the mark `a`
 |  |  | insert the deleted line under the line marked `a`
 |  |  go to line marked `a`
 |  mark the future line to move with `b`
 delete the line to move

แก้ไขตามที่ lago-lito พูดถึงในความคิดเห็นวิธีนี้จะเขียนทับเครื่องหมายและบัฟเฟอร์

  • สำหรับเครื่องหมายที่ฉันไม่คิดว่าเป็นปัญหาจริง: ฉันไม่ค่อยใช้ทั้งหมด 26 คะแนนในบัฟเฟอร์และฉันคิดว่าหนึ่งครั้งส่วนใหญ่จะพบเครื่องหมาย 2 ฟรี

  • สำหรับบัฟเฟอร์มันเป็นไปได้ที่จะบันทึกในตัวแปรชั่วคราว: ก่อนที่จะบันทึกการใช้แมโคร:let saveReg=getreg('"')เพื่อบันทึกการลงทะเบียนและเมื่อการกระทำเสร็จแล้วใช้:call setreg('"', saveReg)เพื่อให้รีจิสเตอร์กลับสู่สถานะก่อนหน้า

อย่างไรก็ตามฉันต้องยอมรับว่าวิธีนี้เป็นวิธีแก้ปัญหาที่รวดเร็วและไม่เหมาะสมที่สุด: ในความเห็นของฉันคำตอบของ Christan เป็นคำตอบที่ดีที่สุดและควรได้รับการยอมรับเพราะไม่ยุ่งกับบัฟเฟอร์และเครื่องหมายไม่บังคับให้ผู้ใช้สร้าง ฟังก์ชั่นและแสดงพลังของคำสั่งทั่วโลก


น่าสนใจ น่าเสียดายที่นี่เขียนทับเนื้อหาของเครื่องหมายและการลงทะเบียนซึ่งฉันอาจใช้;)
iago-lito

@ lago-lito: แน่นอนมันเขียนทับเครื่องหมายและบัฟเฟอร์ สำหรับเครื่องหมายฉันไม่เคยใช้เครื่องหมาย 26 ทั้งหมดในบัฟเฟอร์ของฉันดังนั้นฉันไม่คิดว่ามันเป็นปัญหาจริงๆ สำหรับบัฟเฟอร์มันอาจเป็นปัญหามากกว่านี้ฉันคิดว่าคุณมักจะพบบัฟเฟอร์ที่ไม่ได้ใช้หรือถ้าคุณทำไม่ได้จริงๆให้ใช้ตัวแปรชั่วคราวและฟังก์ชั่นgetreg()และsetreg()เพื่อบันทึกบัฟเฟอร์ของคุณ แต่ฉันยอมรับว่ามันไม่ใช่ทางออกที่ดีที่สุด :-)
statox

1

ฉันเพิ่งเห็นคำถามที่คล้ายกันอื่นและการแก้ปัญหาประกอบด้วย:

ข้ามไปที่กลางบวกหนึ่ง:

Mj

และเรียกใช้:

:,$g/./exe 'm' 2*line('.')-line('$')-1

สิ่งที่น่าสนใจ :) ระวังว่าสิ่งนี้จะแทรกไฟล์ทั้งหมดของคุณและไม่เพียงแค่ย่อหน้าที่เลือก!
iago-lito
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.