วิธีกำหนดโอเปอเรเตอร์ที่อัพเดตในขณะที่กำลังรับอินพุตอยู่


9

ฉันได้กำหนดการแมปโอเปอเรเตอร์ซึ่งใช้พื้นที่ของข้อความจากนั้นขอสตริงการป้อนข้อมูลจากนั้นจัดพื้นที่กับTabularโดยใช้สตริงอินพุตเป็นอาร์กิวเมนต์ มันทำงานได้เป็นอย่างดี

ฉันได้ดำเนินการเช่นนี้โดยใช้vim-operator-userเพื่อช่วยกำหนดผู้ประกอบการใหม่:

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เป็นชุดขึ้นอยู่กับก่อนหน้านี้exprความยาวของ Tabularizeซึ่งหมายความว่าเมื่อมีการป้อนข้อมูลจากผู้ใช้ซ้ำไปได้อย่างปลอดภัยสามารถยกเลิกก่อนที่จะดำเนิน

call match('', expr)ทดสอบการแสดงออกของข้อผิดพลาดของรูปแบบ หากล้มเหลวundoไม่ควรจะดำเนินการ \zsความล้มเหลวในรูปแบบที่สามารถเกิดขึ้นในขณะที่คุณกำลังพิมพ์อะตอมเช่น

redrawจะล้างบรรทัดคำสั่ง นี่คือสาเหตุที่พรอมต์เต็มรูปแบบจะถูกพิมพ์ในทุกรอบ

ErrorMsgหากรูปแบบมีข้อผิดพลาดก็จะให้ความสำคัญกับ

acceptถูกตั้งค่าเมื่อ<cr>กด หากเป็นเท็จให้ยกเลิกการเปลี่ยนแปลง (ถ้ามี) สิ่งอื่นใดที่ทำให้ลูปยกเลิก

ปลั๊กอินที่มีอยู่

มีปลั๊กอินที่เรียกว่าเป็นกลุ่มง่ายชิดที่สามารถทำสิ่งที่คุณกำลังพยายาม คุณสามารถวาดแรงบันดาลใจจากสคริปต์ของมัน


ขอบคุณมากสำหรับคำอธิบายที่ชัดเจน! ฉันไม่ทราบว่าการจัดตำแหน่งอย่างง่ายสามารถทำได้ ฟังก์ชั่นการเลิกทำเป็นสิ่งต่อไปที่ฉันต้องการนำไปใช้ แต่ฉันติดอยู่กับการอัปเดต
tusj

ไม่มีปัญหา🙂ฉันเพิ่งอัปเดตคำตอบเพื่อเน้นรูปแบบหากมีข้อผิดพลาด
ทอมมี่

1
มีข้อผิดพลาดเล็ก ๆ ในการใช้งานในปัจจุบันเนื่องจากความต้องการที่ไม่ได้เขียน: หาก Esc หรือ <CC> ได้รับการพิมพ์การดำเนินงานควรจะถูกยกเลิก ฉันได้แก้ไขกรณีแรกโดยการเพิ่ม: if c == "\<Esc>" && undo silent! undo endif ฉันไม่แน่ใจว่าจะตรวจหา <CC> ได้อย่างไร
tusj

@tusj ฉันอัปเดตคำตอบ
ทอมมี่ A
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.