Girdi alırken güncellenen bir operatör nasıl tanımlanır?


9

Bir metin bölgesi alır, sonra bir giriş dizesi sorar ve sonra argüman olarak giriş dizesini kullanarak bölgeyi Tabular ile hizalar bir operatör eşleme tanımladım . Güzel çalışıyor.

Yeni bir operatörün tanımlanmasına yardımcı olmak için vim-operator-user kullanarak bu şekilde uyguladım :

map \aa <Plug>(operator-align)
call operator#user#define('align', 'Align')
function! Align(motion_wiseness)
    let expr = input("align: ")
    if len(expr) != 0
        execute "'[,']Tabularize /".expr
    endif
endfunction


function! Getchar()
    let c = getchar()
    if c =~ '^\d\+$'
        let c = nr2char(c)
    endif
    return c
endfunction

Sonra hizalamak için normal ifadeye girerken anında güncelleme yapabilir miyim diye merak ettim. Geçerli yaklaşımla ilgili sorun, doğru ifadeyi kullanmıyorsanız geri almanız ve sonra yeniden yapmanız gerektiğidir.

Etkileşimli girişim için şunu yaptım:

map \== <Plug>(operator-align-interactive)
call operator#user#define('align-interactive', 'AlignInteractive')
function! AlignInteractive(motion_wiseness)
    let prompt = "Align: "
    echon prompt
    let expr = ""
    let c = Getchar()
     " CR has to be checked for separately as it acts as putting the cursor back to zero position
    while c != "\<Esc>" && c != "\<CR>"
        if c == "\<BS>"
            if len(expr) != 0
                let expr = expr[0:-2]
                echon "\<CR>".substitute(expr, ".", " ", "g")
                echon "\<CR>".prompt.expr
            endif
        else
            let expr .= c
            echon c
            let cmd = "'[,']Tabularize /".expr
            execute cmd 
        endif
        let c = Getchar()
    endwhile
endfunction

O gerektiğini çalışmak ama girmek vurmadan önce hizalama ben etkili olarak etkileşimli olmayan işleviyle aynı şekilde çalışır, yani bitmiş girme girişi var peşinde olduğu, yapılmaz. Sorunun, yalnızca bir operatör yürütmesi sırasında ekranın / içeriğin güncellenmemesi gibi bir şey olup olmadığını merak ediyorum.

Sorunun ne olabileceği hakkında herhangi bir fikir takdir edilmektedir!

Yanıtlar:


8

Sen gerekir undove redrawhemen tampon değişiklikleri görmek istiyorum.

İşte işe yarayan:

function! AlignInteractive(motion_wiseness)
  let prompt = "Align: "
  let undo = 0
  let expr = ""
  let range = line("'[").','.line("']")
  let failed = 0
  let accept = 0

  echon prompt
  let c = Getchar()

  while c != "\<Esc>" && c != "\<c-c>"
    let undo = len(expr)

    if c == "\<CR>"
      let accept = 1
      break
    elseif c == "\<BS>"
      if len(expr)
        let expr = expr[0:-2]
      endif
    else
      let expr .= c
    endif

    if undo && !failed
      silent! undo
    endif

    if len(expr)
      try
        call match('', expr)
        let failed = 0
        execute range."Tabularize /".expr
      catch //
        let failed = 1
      endtry
    endif

    redraw

    echon prompt
    if failed
      echohl ErrorMsg
    endif
    echon expr
    echohl None
    let c = Getchar()
  endwhile

  if !accept && len(expr) && !failed
    silent! undo
  endif
endfunction

açıklama

rangeDeğişken depolayan '[ve ']işaretleri. Bu, akıl sağlığı için.

Adlı değişken undo, önceki uzunluğuna göre ayarlanır expr. Bu, kullanıcıdan her girdi olduğunda, bir sonraki yinelemenin yürütülmeden önce güvenli bir şekilde geri alınabileceği anlamına gelir Tabularize.

call match('', expr)ifadeyi kalıp hataları için test eder. Başarısız olursa, undoyürütülmemelidir. Desen hataları gibi atomlar yazarken ortaya çıkabilir \zs.

redrawkomut satırını temizleyecektir. Bu nedenle tam istem her yinelemede yazdırılır.

Desen bir hata içeriyorsa, ile vurgulanır ErrorMsg.

accept<cr>basıldığında ayarlanır . Yanlışsa, değişiklikleri geri alın (varsa). Döngüyü kıran her şey iptal edilir.

Mevcut eklenti

Vim-easy-align adlı , denediğiniz şeyi yapabilen bir eklenti var . Senaryosundan ilham alabilirsin .


Açık açıklamalar için çok teşekkür ederim! Kolay hizalamanın bunu yapabileceğini bilmiyordum. Geri alma işlevi uygulamak istediğim bir sonraki şeydi, ancak güncellemede takılı kaldım.
tusj

Sorun değil 🙂 Bir hata varsa deseni vurgulamak için yanıtı güncelledim.
Tommy A

1
Mevcut uygulamada, yazılı olmayan gereksinim nedeniyle ufak bir hata var: Esc veya <CC> yazıldıysa, işlem iptal edilmelidir. Ben ilk dava ekleyerek düzeltildi: if c == "\<Esc>" && undo silent! undo endif <CC> olsa nasıl tespit emin değilim.
tusj

@tusj Cevabı güncelledim.
Tommy A
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.