Satırları araya ekleyerek blokları birleştir


15

Bu satırdan geçmek gibi satırları araya ekleyerek iki metin bloğunu birleştirmenin özel bir yolu var mı:

a1
a2
a3
a4
  b1
  b2
  b3
  b4

Buna:

a1
  b1
a2
  b2
a3
  b3
a4
  b4

birkaç komutla?

EDIT : Sato Katsura'nın çözümünü gerçekten çok seviyorum , işte böyle uyguladım:

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>

Şimdi merak ediyorum - kullanım durumunuz nedir? Bir TV sezonu için altyazıları yeniden adlandırıyor musunuz?
VanLaser

@ VanLaser Haha, değilim. Çoğunlukla ben bir programdan göz ayrıştırma çıktı, ben oluşturma sırası / sonra nesnelerin okuma gecikmesi ile ilgili tutarlılığı kontrol etmek gerekir. Serpiştirme blokları, gecikmeli çıkış bloklarında karşılık gelen çizgileri eşleştirmeyi kolaylaştırır. Ayrıca bazen kod satırlarını günlük kaydı veya kıyaslama için tekrarlanan benzer talimatlarla eklemem gerekir. Makrolarla bu talimatları oluşturmak kolaydır, daha sonra bunları gerçek kodla araya
koymak

1
@ lago-lito - Cevabınız için teşekkürler! Evet, Vim oldukça çok yönlü :) "Göz ayrıştırma" ifadeniz beni scroll-bindingiki Vim penceresinde de düşündürdü .
VanLaser

Bunu kullanırken sorun yaşıyorum, iki ardışık bloğu nasıl seçiyorsunuz? Bitişik olmaları gerekiyor mu?
cbcoutinho

@cbcoutinho Evet var :) İkisini de seçebileceğinizden emin değilim. Örneğin ben gösterebiliriz, ben (söz hakkından) benim imleci koydu b1ben vurmak, sonra vipsonra, bütün bir parça seçmek için ,ithangi <map-I've-Picked>. Senin tarafında çalışmıyor mu?
iago-lito

Yanıtlar:


8

Bunu yapmanın özel bir yolu yok (bildiğim kadarıyla), ancak evet, birkaç komutla yapılabilir:

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

İle çalıştırabilirsiniz :call Interleave(5, 8, 1). İlk parametre ilk satır, ikinci satır son satır ve üçüncü satır nerede taşınacağıdır. Muhtemelen ne yaptığınızı görmek için satır numaralarını açmak istersiniz ( :set number).

Bu blokların örtüşmediğini varsayar. İşlevin nasıl çalıştığını görmek :help :moveve :help range()anlamak.

Muhtemelen iki bloğu almanın daha iyi yolları vardır. İki blok takas etmenize izin verilen bir eklenti var. Eklentinin adını hatırlayamıyorum, ancak yazar (belki de ünlü Dr. Chip?) Bir arayüz bulmaya benden daha fazla düşündürdü. :)


Tatlı! İki blok bitişik ve aynı boyuta sahip olduğundan sadece iki argümana ihtiyacım var: startve size. Bu değerleri bir seçimden alan bir homebrew işlevi ile mükemmel olur. Üzerinde çalışıyorum. :)
iago-lito


13

İşte başka bir alternatif:

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

Önce 4 satır olan satırları geçerli satırın sonrasına ( :h :t) kopyalayın, ardından ardışık b satırlarını ( :h :d) silin

Daha da iyisi bu komut:

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

Yani, her satır için 'b' ile başlayan bir sonraki satırı bulun ve mevcut satırın altına taşıyın.


1
İkinci komutta "E16: Geçersiz aralık" var. Bunun .+,$dyerine denedim ve işe yaradı (olduğu gibi .+,.+4d).
Peter Lewerin

Bunun neden olduğundan emin değilim
Christian Brabandt

1
hayır değil. Oku: h: aralık, normal ifade araması yerine her zaman doğrudan numaralandırma kullanabilirsiniz
Christian Brabandt

2
@ iago-lito İkinci numara her zaman işe yarar, ancak /^\s*bbaşka bir numaraya geçmeniz gerekir :range. örneğin: 1. bloğu seçin, yürütün'<,'>g/^/'>+1m.
dedowsdi

1
@ iago-lito Esasen Christian'ın cevabı ile aynı. 1. bloğu görsel olarak seçerseniz hiçbir şey sabit kodlanmaz '>+1, 2. bloğun başlangıcını işaretler.
dedowsdi

3

Makrolar ve işaretlerle biraz eğlenmek istiyorsanız, böyle bir şey deneyebilirsiniz:

  • Önce bir işareti (burada koymak aiçeren satırında) a1ilema

  • İçeren satıra gidin b1ve ile işaretleyinmb

  • İstediğiniz kayıtta (burada kayıt q) bir makro kaydetmeye başlayınqq

  • Aşağıdaki makroyu ekleyin: ddmb'apjma'b

  • İle makro kaydetmeyi durdur q

  • İle gerektiği gibi çok kez çal X@qnerede Xoynamak için zaman sayısıdır.

Makroyu ayrıntılandırmak için:

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

Düzenle Lago-lito'nun yorumlarda belirttiği gibi, bu yöntem işaretlerin ve arabelleklerin üzerine yazacaktır.

  • İşaretler için bunun gerçek bir sorun olduğunu düşünmüyorum: Bir arabellekteki 26 işaretin hepsini nadiren kullanıyorum ve bence çoğu zaman 2 ücretsiz işaret bulacak.

  • Arabellek için geçici bir değişkene kaydetmek mümkündür: Makroyu :let saveReg=getreg('"')kaydetmeden önce kaydı kaydetmek için kullanın ve eylem tamamlandıktan :call setreg('"', saveReg)sonra kaydı önceki durumuna geri getirmek için kullanın.

Her neyse, bu çözümün sadece hızlı bir çözüm olduğunu ve optimal olmadığını itiraf etmeliyim: Bana göre Christan'ın cevabı en iyisi ve kabul edilmeli çünkü tamponlarla ve işaretlerle uğraşmıyor, kullanıcıyı yaratmaya zorlamıyor bir fonksiyon ve global komutun gücünü gösterir.


İlginç. Ne yazık ki, bu işaretler ve kayıtların içeriğinin üzerine
yazıyor

@ lago-lito: gerçekten işaretlerin ve arabelleklerin üzerine yazar. İşaretler için arabelleklerimdeki 26 işaretin tümünü hiç kullanmam, bu yüzden bunun gerçekten bir sorun olduğunu düşünmüyorum. Tamponları için bu bir sorun daha olabilir diye sık sık kullanılmayan bir tampon bulmak ya da gerçekten, geçici değişken ve işlevleri kullanamıyorsanız düşünüyorum getreg()ve setreg()sizin tampon kaydedin. Ama bunun optimal bir çözüm olmadığını kabul ediyorum :-)
statox

1

Başka bir benzer soru gördüm ve çözüm şunlardan oluşur:

Ortaya bir artı:

Mj

Ve koş:

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

İlginç :) Bu, sadece seçilen paragrafı değil, tüm dosyanızı serpiştirdiğine dikkat edin!
iago-lito
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.