Python dosya tipini kullanırken çok satırlı bir dizgiyi vim'de nasıl yeniden biçimlendirebilirim?


23

Bazı Python kodlarını vim'de düzenlemeye başladığımı varsayalım:

myobj.myfunc("Some string parameter that goes on and on and on and on and sometimes doesn't"
             "split very"
             "neatly over different lines so that"
             "it is formatted attractively")

Bunu yeniden biçimlendirmeyi tercih ederdim, bu yüzden kendi belirttiğim gibi yeniden akıtır textwidth:

myobj.myfunc("Some string parameter that goes on and on and "
             "on and on and sometimes doesn't split very "
             "neatly over different lines so that it is "
             "formatted attractively")

Bunu yapmanın kolay bir yolu var mı? Bu, geleneksel bir metin paragrafı gqipolsaydı , ya da benzerleri faydalı olurdu, ancak bu, dizgiyi sınırlandırmak için kullanılan tırnakların üstesinden gelmeyecek.

Not : Burada özellikle Python hakkında soru soruyorum, ancak ideal olarak, bu cevap dize devamına izin veren birçok programlama dili için geçerli olacaktır.



3
Ayrıca kodu yeniden yazmayı düşündünüz mü """multi-line string"""?
200_success

1
@ 200_success, bu harika bir ipucu, teşekkürler. Python'un bu özelliğini hiç bilmiyordum. Çoğunlukla çalışıyor gibi görünüyor - fonksiyona tüm parametreler yeniden akıtılsa da ideal değil. Benim sorum hala sahip olduğum dize türü için ve kesinlikle diğer şeritler için geçerli olduğunu düşünüyorum.
Andrew Ferrier

2
Çok satırlı bir dizginin, boşlukta dizede önemli olması durumunda sorun olabilen boşluk karakterleri ekleyeceğini unutmayın.
Matt Boehm

Yanıtlar:


6

Oh, zor bir tane. En iyi yaklaşım muhtemelen bir makro ama daha büyük bir eklenti olduğunu düşünüyorum. İşte çırpılmış bir örnek (daha iyi bir hobiye ihtiyacım var). Benim için çalışıyor gibiydi ama uygun şekilde girintilemek için python girintili eklentiye ihtiyaç duyacaktı. Denemek.

function ReformatMultiLines()
  let brx = '^\s*"'
  let erx = '"\s*$'
  let fullrx = brx . '\(.\+\)' . erx
  let startLine = line(".")
  let endLine   = line(".")
  while getline(startLine) =~ fullrx
    let startLine -= 1
  endwhile
  if getline(endLine) =~ erx
    let endLine += 1
  endif
  while getline(endLine) =~ fullrx
    let endLine += 1
  endwhile
  if startLine != endLine
    exec endLine . ' s/' . brx . '//'
    exec startLine . ' s/' . erx . '//'
    exec startLine . ',' . endLine . ' s/' . fullrx . '/\1/'
    exec startLine . ',' . endLine . ' join'
  endif
  exec startLine
  let orig_tw = &tw
  if &tw == 0
    let &tw = &columns
    if &tw > 79
      let &tw = 79
    endif
  endif
  let &tw -= 3 " Adjust for missing quotes and space characters
  exec "normal A%-%\<Esc>gqq"
  let &tw = orig_tw
  let endLine = search("%-%$")
  exec endLine . ' s/%-%$//'
  if startLine == endLine
    return
  endif
  exec endLine
  exec 'normal I"'
  exec startLine
  exec 'normal A "'
  if endLine - startLine == 1
    return
  endif
  let startLine += 1
  while startLine != endLine
    exec startLine
    exec 'normal I"'
    exec 'normal A "'
    let startLine += 1
  endwhile
endfunction

Sonra :call ReformatMultiLines()onu bir haritalamada kullanabilir ve / veya kullanabilirsiniz.


6

Bu normal bir durumsa, en iyisi bir eklenti aramakta veya @Sukima işlevini kullanmaktır. Ancak bunu anında yapıyor olsaydım, muhtemelen ne yapardım:

  1. Açılış pareninden sonra ve kapanış pareninden önce yeni bir satır ekleyin, böylece dizeler ayrı satırlarda olur.

    myobj.myfunc(
                 "Some string parameter that goes on and on and on and on and sometimes doesn't"
                 "split very"
                 "neatly over different lines so that"
                 "it is formatted attractively"
    )
    
  2. Dizeleri olan satırları seçin ve çevreleyen tırnak işaretlerini silin: :norm ^x$x

  3. Metin genişliğini azaltın (eksik teklifleri hesaba katmak için) :set tw-=2
  4. Yeniden seç ve biçimlendir: gvgq
  5. Metin genişliğini düzeltin: :set tw+=2
  6. Yeniden eklenti tırnak: gv:norm I"<Esc>A". Bunun yerine, <Esc>ctrl-v yazıp ardından Escape tuşunu yazarak değişmez bir kaçış eklemek istiyorsunuz. Kaçmak için jj haritası yaptığımdan, genellikle buraya jj yazarım.
  7. İsteğe bağlı olarak, ilk iki / son iki çizgiye yeniden katılmak için J kullanın. Python'da çok uzun bir dize varken, genellikle bir sonraki satırda başlamayı ve sadece bir önceki satırdan bir seviye daha fazla girintiyi tercih etmeyi tercih ederim. Bu, dize için daha fazla yatay alan sağlar ve sadece bana daha doğal geliyor. Alternatif olarak, dizgiyi yukarıdaki bir değişkene kaydedebilirsiniz. Bunun statik bir dize olduğu varsayımıyla, onu daha düşük bir girinti düzeyinde olması ve daha az satıra sığması için global bir değişkene bile kaydedebilirsiniz. Aynı satırdaki kapanış parenine tekrar katılacağınızı, muhtemelen metin genişliğini 2 yerine 3 artırmak / artırmak istediğinizi unutmayın.

1
Teşekkürler. Ben sadece bunu denedim ama :set tw-=2sonuçta E487: Argument must be positive: tw-=2. Sözdizimi yanlış mı?
Andrew Ferrier

1
Textwidth öğesinin geçerli değerini ile işaretleyin :set tw?. Tahminime göre metin genişliği 0 olarak ayarlanmış. Bu adımlar metin genişliğinin satır başına istediğiniz karakter sayısı olarak başladığını varsayar.
Matt Boehm

Örneğinizde muhtemelen s/2/3/kapanış teklifinden önce bir boşluk eklemek isteyip istemediğinize göre , uzun dizeniz sözcükler arasında uygun boşluk bırakmaz.
cdosborn

1

Kod ayrıştırma ve biçimlendirme, özellikle Python gibi dinamik diller için zordur.

Python'u Vimscript'te ayrıştırmaya çalışmak yerine, yapf gibi harici bir formatlayıcı kullanmanızı öneririz . İle burada cevap sizinle yazma otomatik bu yazabilirsiniz:

augroup write_cmd
    autocmd BufWritePre *.py call s:write_cmd('yapf')
augroup end

s:write_cmd()Fonksiyon diğer cevap ise - Ben bir hata bulursanız iki yerde güncellemek zorunda kalmazsınız yüzden buraya eklemek olmaz :-)

Ayrıca ayarlayabilirsiniz formatprgiçin yapfmanuel ile biçimlendirmek gq.


Merhaba. Yararlı cevap, ancak bu soruyu cevapladığını sanmadığım için aşağıdayım: bu soru çok özel olarak yapfyapılmadığı anlaşılan çok satırlı dizeleri yeniden biçimlendirme hakkında soruyor . Yine de yararlı bir araç gibi göründüğünü kabul ediyorum.
Andrew Ferrier

@AndrewFerrier Fuarı yeterince; Ancak geçen gün bunu test ettiğimde dizgileri yeniden biçimlendirdiğimi yemin edebilirdim, ama şimdi çalışmasını da sağlayamıyorum: - / Sanırım kafam karıştı.
Martin Tournoij

0

Aşağıdaki işlevler ve karşılık gelen eşlemeler bu sorunu benim için çözdü:

function! BreakMultlineString(quote)
let c = 100
while c == 100
    normal 100|
    let c = virtcol('.')
    if c == 100
        execute "normal ," . a:quote
    endif
endwhile
endfunction

function! JoinMultilineString()
    let c = "'"
    while c == "'" || c == '"'
        normal gj^
        let c = matchstr(getline('.'), '\%' . col('.') . 'c.')
        normal k
        if c == "'" || c == '"'
            normal ,j
        endif
    endwhile
endfunction

" break lines
nnoremap <Leader>" 100\|Bi"<CR>"<Esc>
nnoremap <Leader><Leader>" :call BreakMultlineString('"')<CR>
nnoremap <Leader>' 100\|Bi'<CR>'<Esc>
nnoremap <Leader><Leader>' :call BreakMultlineString("'")<CR>

" join lines
nmap <Leader>j Jds'ds"x
nnoremap <Leader>J :call JoinMultilineString()<CR>
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.