Làm thế nào để xác định một toán tử đang cập nhật trong khi nó đang nhập liệu?


9

Tôi đã xác định ánh xạ toán tử lấy một vùng văn bản, sau đó yêu cầu một chuỗi đầu vào và sau đó căn chỉnh vùng đó với Tabular bằng cách sử dụng chuỗi đầu vào làm đối số. Nó hoạt động độc đáo.

Tôi đã triển khai nó như thế này, sử dụng vim-toán tử-user để giúp xác định toán tử mới:

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

Sau đó, tôi tự hỏi nếu tôi có thể làm cho nó cập nhật nhanh chóng trong khi nhập biểu thức thông thường để căn chỉnh với. Vấn đề với cách tiếp cận hiện tại là bạn phải hoàn tác và sau đó làm lại nếu bạn không sử dụng đúng biểu thức.

Đối với nỗ lực tương tác, tôi đã thực hiện điều này:

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

sẽ hoạt động nhưng việc căn chỉnh không được thực hiện trước khi tôi nhấn enter, nghĩa là sau khi tôi nhập xong, nghĩa là nó hoạt động giống như chức năng không tương tác. Tôi tự hỏi nếu vấn đề có thể là một cái gì đó như màn hình / nội dung không được cập nhật trong khi thực hiện toán tử, chỉ sau đó.

Bất kỳ ý tưởng về những gì vấn đề có thể được đánh giá cao!

Câu trả lời:


8

Bạn cần undoredrawnếu bạn muốn thấy những thay đổi trong bộ đệm ngay lập tức.

Đây là những gì hoạt động:

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

Giải trình

Các rangebiến lưu trữ '[']dấu ngoặc. Đây là vì lợi ích của sự tỉnh táo.

Một biến được gọi undolà được đặt dựa trên độ dài trước đó của expr. Điều này có nghĩa là bất cứ khi nào có đầu vào từ người dùng, lần lặp tiếp theo có thể hoàn tác một cách an toàn trước khi thực hiện Tabularize.

call match('', expr)kiểm tra biểu thức cho các lỗi mẫu. Nếu thất bại, undokhông nên được thực thi. Lỗi mô hình có thể xảy ra khi bạn gõ các nguyên tử như \zs.

redrawsẽ xóa dòng lệnh. Đây là lý do tại sao lời nhắc đầy đủ được in trên mỗi lần lặp.

Nếu mẫu có lỗi, nó được tô sáng bằng ErrorMsg.

acceptđược đặt khi <cr>được nhấn. Nếu đó là sai, hoàn tác các thay đổi (nếu có). Bất cứ điều gì khác phá vỡ vòng lặp hủy bỏ.

Plugin hiện có

Có một plugin gọi là vim-easy-align có thể làm những gì bạn đang cố gắng. Bạn có thể lấy cảm hứng từ kịch bản của nó .


Cảm ơn bạn rất nhiều vì những lời giải thích rõ ràng! Tôi không biết rằng sự dễ dàng có thể làm điều đó. Chức năng hoàn tác là điều tiếp theo mà tôi muốn thực hiện, nhưng tôi đã bị kẹt khi cập nhật.
tusj

Không có vấn đề gì Tôi chỉ cập nhật câu trả lời để làm nổi bật mẫu nếu nó có lỗi.
Tommy A

1
Có một lỗi nhỏ trong quá trình triển khai hiện tại, do yêu cầu không được viết: nếu Esc hoặc <CC> đã được nhập, thao tác sẽ bị hủy. Tôi đã sửa trường hợp đầu tiên bằng cách thêm: if c == "\<Esc>" && undo silent! undo endif Tôi không chắc chắn cách phát hiện cho <CC>.
tusj

@tusj Mình cập nhật câu trả lời.
Tommy A
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.