इनपुट लेते समय जो ऑपरेटर अपडेट कर रहा है उसे कैसे परिभाषित करें?


9

मैंने एक ऑपरेटर मैपिंग को परिभाषित किया है जो पाठ का एक क्षेत्र लेता है, फिर एक इनपुट स्ट्रिंग के लिए पूछता है और फिर एक तर्क के रूप में इनपुट स्ट्रिंग का उपयोग करके टैब्यूलर के साथ क्षेत्र को संरेखित करता है। यह अच्छी तरह से काम करता है।

मैंने इसे एक नए ऑपरेटर को परिभाषित करने में मदद करने के लिए विम-ऑपरेटर-उपयोगकर्ता का उपयोग करके इसे इस तरह से लागू किया है :

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

फिर मुझे आश्चर्य हुआ कि क्या मैं नियमित अभिव्यक्ति में प्रवेश करने के दौरान इसे मक्खी पर अपडेट कर सकता हूं। वर्तमान दृष्टिकोण के साथ समस्या यह है कि यदि आपको सही अभिव्यक्ति का उपयोग नहीं करना है तो आपको पूर्ववत करना होगा और फिर से करना होगा।

संवादात्मक प्रयास के लिए, मैंने इसे बनाया:

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

यह काम करना चाहिए, लेकिन मेरे द्वारा दर्ज किए जाने से पहले संरेखण नहीं किया जाता है, अर्थात जब मैंने इनपुट में प्रवेश किया है, तो प्रभावी रूप से अर्थ है कि यह उसी तरह काम करता है जैसे कि गैर-संवादात्मक फ़ंक्शन। मुझे आश्चर्य है कि यदि समस्या एक ऑपरेटर के निष्पादन के दौरान स्क्रीन / सामग्री को अपडेट नहीं करने जैसी कुछ हो सकती है, उसके बाद ही।

समस्या की सराहना की जा सकती है पर कोई विचार!

जवाबों:


8

आपको जरूरत है undoऔर redrawयदि आप तुरंत बफर में बदलाव देखना चाहते हैं।

यहाँ क्या काम करता है:

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

व्याख्या

rangeचर संग्रहीत करता है '[और ']अंक। यह संन्यास के लिए है।

नामक एक चर पिछली लंबाई के undoआधार पर निर्धारित किया जाता है । इसका मतलब है कि जब भी उपयोगकर्ता से इनपुट होता है, तो अगला पुनरावृत्ति निष्पादन से पहले सुरक्षित रूप से पूर्ववत कर सकता है ।exprTabularize

call match('', expr)पैटर्न त्रुटियों के लिए अभिव्यक्ति का परीक्षण करता है। यदि यह विफल रहता है, undoतो निष्पादित नहीं किया जाना चाहिए। पैटर्न फेलियर हो सकता है जैसे आप परमाणु टाइप कर रहे हैं \zs

redrawकमांड लाइन को साफ करेगा। यही कारण है कि हर पुनरावृत्ति पर पूरा संकेत छपा है।

यदि पैटर्न में कोई त्रुटि है, तो इसके साथ हाइलाइट किया गया है ErrorMsg

accept<cr>दबाया जाता है जब सेट किया जाता है। यदि यह गलत है, तो परिवर्तनों को पूर्ववत करें (यदि कोई हो)। कुछ भी जो लूप कैंसिल को तोड़ता है।

मौजूदा प्लगइन

Vim-easy-align नामक एक प्लगइन है जो आप प्रयास कर रहे हैं। आप इसकी स्क्रिप्ट से प्रेरणा ले सकते हैं ।


स्पष्ट स्पष्टीकरण के लिए बहुत बहुत धन्यवाद! मुझे नहीं पता था कि आसान-संरेखण ऐसा कर सकता है। पूर्ववत कार्यक्षमता अगली चीज़ थी जिसे मैं लागू करना चाहता था, लेकिन मैं अपडेट करने में अटक गया।
tusj

कोई समस्या नहीं if मैंने पैटर्न को हाइलाइट करने के लिए सिर्फ उत्तर को अपडेट किया है यदि उसमें कोई त्रुटि है।
टॉमी ए

1
वर्तमान कार्यान्वयन में एक छोटी बग है, गैर-लिखित आवश्यकता के कारण: यदि Esc या <CC> टाइप किया गया है, तो ऑपरेशन को रद्द कर दिया जाना चाहिए। मैंने पहला मामला जोड़कर तय किया है: if c == "\<Esc>" && undo silent! undo endif मुझे यकीन नहीं है कि <CC> का पता कैसे लगाया जाए।
17

@tusj I ने उत्तर को अपडेट किया।
टॉमी ए
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.