Bir dizi yıldız madde işareti noktasını numaralı listeyle değiştirme


16

Aşağıdaki metne sahip olduğumu düşünün:

some random stuff
* asdf
* foo
* bar
some other random stuff

Yıldız mermi sayılarla değiştirmek istiyorum, şöyle:

some random stuff
1. asdf
2. foo
3. bar
some other random stuff

Vim'de bu nasıl yapılabilir?


Neden eklentileri kullanmıyorsunuz? Github
SibiCoder'daki

O kadar şaşırtıcı ve havalı ki, herkes cevaplarını sayıları artırdı ama Markdown sizin için numaralayacağından neden hepsini yapmıyorsunuz 1.? Öyleyse :%s/^* /1. /yapardı. Bu daha az iş gibi görünüyor.
civciv

Yanıtlar:


14

Aşağıdaki komutu deneyebilirsiniz:

:let c=0 | g/^* /let c+=1 | s//\=c.'. '

Önce değişkeni c( let c=0) başlatır , daha sonra gdeseni ^*(satır başlangıcı, ardından yıldız işareti ve boşluk) arayan global komutu yürütür .

Bu kalıbı içeren bir satır bulunduğunda, global komut şu komutu yürütür:
let c+=1 | s//\=c.'. '
Değişken c( let c+=1) 'i arttırır , sonra |( s), önceki aranan kalıbı ( //) bir ifadenin ( \=) değerlendirmesiyle değiştirir ( ): birleştirilmiş
değişkenin içeriği c( .) dizesiyle'. '


Tamponunuzdaki tüm satırları değiştirmek istemiyorsanız, yalnızca belirli bir paragrafı değiştirmek istiyorsanız, global komuta bir aralık iletebilirsiniz. Örneğin, yalnızca sayısı 5 ile 10 arasında olan satırları değiştirmek için:

:let c=0 | 5,10g/^* /let c+=1 | s//\=c.'. '

Dönüştürmek istediğiniz birkaç benzer listeyi içeren bir dosyanız varsa, örneğin şöyle bir şey:

some random stuff                 some random stuff                      
* foo                             1. foo                                 
* bar                             2. bar                                 
* baz                             3. baz                                 
some other random stuff           some other random stuff                
                           ==>                                                
some random stuff                 some random stuff                      
* foo                             1. foo                                 
* bar                             2. bar                                 
* baz                             3. baz                                 
* qux                             4. qux                                 
some other random stuff           some other random stuff                

Aşağıdaki komutla yapabilirsiniz:

:let [c,d]=[0,0] | g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '

cBaşka bir listeye geçtiğinizde değişkeni sıfırlayan önceki komutun sadece bir varyantıdır . Başka bir listede olup olmadığınızı tespit etmek için, değişken d, bir değişiklik yapılan son satırın numarasını saklamak için kullanılır.
Global komut geçerli satır numarasını ( line('.')) ile karşılaştırır d+1. Bunlar aynıysa, bu carttıkça ( c+1) olduğu gibi aynı listede olduğumuz anlamına gelir, aksi takdirde farklı bir listede olduğumuz anlamına gelir, yani creset ( 1).

Bir işlevin içinde, komut let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')]şu şekilde yeniden yazılabilir:

let c = line('.') == d+1 ? c+1 : 1
let d = line('.')

Veya bunun gibi:

if line('.') == d+1
    let c = c+1
else
    let c = 1
endif
let d = line('.')

Bazı tuş vuruşlarını kaydetmek için :NumberedLists, varsayılan değeri 1,$( -range=%) olan bir aralığı kabul eden özel komutu da tanımlayabilirsiniz :

command! -range=% NumberedLists let [c,d]=[0,0] | <line1>,<line2>g/^* /let [c,d]=[line('.')==d+1 ? c+1 : 1, line('.')] | s//\=c.'. '

Ne zaman :NumberedListsyürütülür <line1>ve <line2>otomatik olarak kullandığınız aralıkla değiştirilir.

Bu nedenle, arabellekteki tüm listeleri dönüştürmek için şunu yazarsınız: :NumberedLists

Yalnızca 10. ve 20. satırlar arasındaki listeler: :10,20NumberedLists

Sadece görsel seçim: :'<,'>NumberedLists


Daha fazla bilgi için bakınız:

:help :range
:help :global
:help :substitute
:help sub-replace-expression
:help list-identity    (section list unpack)
:help expr1
:help :command

9

Bu yalnızca en son bir Vim sürümüyle çalışır (ki :h v_g_CTRL-A):

  1. (Liste mermi Blok seçmek *) ve bunların yerine 0(imleç ilk üzerindedir *): Ctrl-v j j r 0.
  2. Önceki bloğu ve artışı sayacı kullanarak yeniden seçme :gv g Ctrl-a

... ve bu kadar :)


(Her bir sayıdan sonra nokta kullanmak istiyorsanız, 1 adım değiştirin: Ctrl-v j j s 0 . Esc)


9

Çizgileri görsel olarak seçin ve bu değiştirme komutunu yürütün:

:'<,'>s/*/\=line('.') - line("'<") + 1 . '.'

Bkz :help sub-replace-expression, :help line()ve :help '<.

Satırları seçmek zorunda kalmamak için ofsetlerle geriye ve ileriye doğru aramalar, aşağıdaki gibi ikame aralığını belirtmek için kullanılabilir:

:?^[^*]?+1,/^[^*]/-1s/*/\=line('.') - search('^[^[:digit:]]', 'bn') . '.'

Görmek :help cmdline-ranges


2

Diğer yol:

:let n = 1 | g/^* /s//\=printf('%d. ', n)/g | let n = n + 1

0

Özel işleçler de tanımlayabilirsiniz

Bunları anahtar dizilere '*ve '#. İşaretler *ve #mevcut değil, bu nedenle herhangi bir varsayılan işlevi geçersiz kılmazsınız. 'Önek olarak seçim yapmanın nedeni bir tür anımsatıcı almaktır. Bazı satırların önüne bir işaret / işaret ekliyorsunuz. Ve genellikle bir işarete gitmek için öneki kullanırsınız '.

fu! s:op_list_bullet(...) abort range

    if a:0
        let [lnum1, lnum2] = [line("'["), line("']")]
    else
        let [lnum1, lnum2] = [line("'<"), line("'>")]
    endif

    if !empty(matchstr(getline(lnum1), '^\s*\d\s*\.'))
        let pattern     = '\d\s*\.\s\?'
        let replacement = '* '

    elseif count(['-', '*'], matchstr(getline(lnum1), '\S'))
        let pattern     = '\v\S\s*'
        let replacement = ''

    else
        let pattern     = '\v\ze\S'
        let replacement = '* '
    endif

    let cmd = 'keepj keepp %s,%s s/%s/%s'

    sil exe printf(cmd, lnum1, lnum2, pattern, replacement)
endfu

fu! s:op_list_digit(...) abort range
    let l:c = 0

    if a:0
        let [lnum1, lnum2] = [line("'["), line("']")]
    else
        let [lnum1, lnum2] = [a:firstline, a:lastline]
    endif

    if count(['-', '*'], matchstr(getline(lnum1), '\S'))
        let pattern     = '\S\s*'
        let replacement = '\=l:c.". "'

    elseif !empty(matchstr(getline(lnum1), '^\s*\d\s*\.'))
        let pattern     = '\d\s*\.\s\?'
        let replacement = ''

    else
        let pattern     = '\v^\s*\zs\ze\S'
        let replacement = '\=l:c.". "'
    endif

    let cmd = 'keepj keepp %s,%s g/%s/let l:c = line(".") == line("'']")+1 ?
                                                \ l:c+1 : 1 |
                                                \ keepj keepp s/%s/%s'

    sil exe printf(cmd, lnum1, lnum2, pattern, pattern, replacement)
endfu

nno <silent> '*     :<C-U>set opfunc=<SID>op_list_bullet<CR>g@
nno <silent> '**    :<C-U>set opfunc=<SID>op_list_bullet
                    \<Bar>exe 'norm! ' . v:count1 . 'g@_'<CR>
xno <silent> '*     :call <SID>op_list_bullet()<CR>

nno <silent> '#     :<C-U>set opfunc=<SID>op_list_digit<CR>g@
nno <silent> '##    :<C-U>set opfunc=<SID>op_list_digit
                    \<Bar>exe 'norm! ' . v:count1 . 'g@_'<CR>
xno <silent> '#     :call <SID>op_list_digit()<CR>

Ayrıca görsel modda da çalışır.
Ex komutları komut dosyası oluşturmak için iyidir, ancak etkileşimli kullanım için normal bir operatör muhtemelen daha iyidir, çünkü herhangi bir hareket veya metin nesnesiyle birleştirebilirsiniz.

Örneğin, geçerli paragraf içinde yıldız işaretleri veya eksi işaretleri bulunan bir listeyi vurarak değiştirebilirsiniz '*ip. Burada '*bir işleç ve ipüzerinde çalıştığı metin nesnesidir.

Ve aynı şeyi, sonraki 10 satırdaki sayıların önüne eklenmiş bir liste için vurarak yapın '#10j. Burada, '#başka bir operatör ve 10joperatörün üzerinde çalıştığı çizgileri kapsayan bir harekettir.

Özel bir işleç kullanmanın diğer bir yararı da, son sürümü dot komutuyla tekrar edebilmenizdir.

resim açıklamasını buraya girin

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.