ইনপুট নেওয়ার সময় আপডেট হওয়া অপারেটরটিকে কীভাবে সংজ্ঞায়িত করবেন?


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>চাপলে সেট করা হয়। যদি এটি মিথ্যা হয় তবে পরিবর্তনগুলি পূর্বাবস্থায় ফেলা (যদি থাকে)। লুপটি ভেঙে অন্য যে কোনও কিছু বাতিল করে।

বিদ্যমান প্লাগইন

ভিএম-ইজি-অ্যালাইন নামে একটি প্লাগইন রয়েছে যা আপনি যা চেষ্টা করছেন তা করতে পারে। আপনি এর স্ক্রিপ্ট থেকে অনুপ্রেরণা পেতে পারেন


পরিষ্কার ব্যাখ্যার জন্য আপনাকে অনেক ধন্যবাদ! আমি জানতাম না যে সহজ-প্রান্তিককরণ এটি করতে পারে। পূর্বাবস্থায় ফাংশনটি হ'ল পরবর্তী জিনিস যা আমি প্রয়োগ করতে চেয়েছিলাম তবে আপডেটে আটকে গেলাম।
tusj

কোনও সমস্যা নেই 🙂 যদি কোনও ত্রুটি থাকে তবে আমি প্যাটার্নটি হাইলাইট করার জন্য উত্তরটি আপডেট করেছি।
টমি এ

1
অ-লিখিত প্রয়োজনীয়তার কারণে বর্তমান বাস্তবায়নে একটি ছোট্ট বাগ রয়েছে: যদি ইস্ক বা <সিসিস> টাইপ করা থাকে তবে ক্রিয়াকলাপ বাতিল করা উচিত। আমি যোগ করে প্রথম কেসটি স্থির করেছি: if c == "\<Esc>" && undo silent! undo endif <সি>> এর জন্য কীভাবে সনাক্ত করতে হবে তা সম্পর্কে আমি নিশ্চিত নই।
tusj

@ টসজ আমি উত্তর আপডেট করেছি।
টমি এ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.