You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vimscript中实现弹窗(Popup)内的输入(Input)功能?以Coc插件的Coc-rename功能为例

Creating a Popup Input Like Coc-Rename in Vimscript

Got it, you're looking for that smooth popup input experience similar to Coc-rename—where a compact window pops up near your cursor, lets you type and edit a value in-place, and applies the change when you confirm with Enter (or cancels with ESC). Let's break down how to build this step by step.

Core Approach

The idea is to use Vim's popup_create() to make a container window, then listen for keyboard input to update the popup's content in real-time. We'll handle basic editing (typing, backspace, cursor movement) and add confirmation/cancellation logic to mimic Coc's behavior.

Step 1: Build the Popup Input Function

First, create a reusable function that generates the popup and manages input:

function! PopupInput(prompt, default) abort
  " Initialize popup content: prompt line + default input text
  let l:initial_content = [a:prompt, a:default]
  let l:popup_id = popup_create(l:initial_content, {
        \ 'border': ['', '', '', ' ', '', '', '', ''], " Subtle border
        \ 'highlight': 'NormalFloat', " Use the default float window highlight
        \ 'line_highlight': [{'line': 0, 'hl': 'Comment'}], " Gray out the prompt line
        \ 'line': winline() + 1, " Position popup below current line
        \ 'col': wincol() + len(a:prompt) + 2, " Align input with prompt
        \ })

  let l:input_text = a:default
  let l:cursor_pos = len(a:default) " Track cursor position in input

  while 1
    let l:char = getchar()

    " Handle confirmation (Enter)
    if l:char == "\<CR>"
      popup_close(l:popup_id)
      return l:input_text
    " Handle cancellation (ESC)
    elseif l:char == "\<ESC>"
      popup_close(l:popup_id)
      return ''
    " Handle backspace
    elseif l:char == "\<BS>"
      if l:cursor_pos > 0
        let l:input_text = strpart(l:input_text, 0, l:cursor_pos - 1) . strpart(l:input_text, l:cursor_pos)
        let l:cursor_pos -= 1
      endif
    " Handle left arrow (move cursor left)
    elseif l:char == "\<Left>"
      if l:cursor_pos > 0
        let l:cursor_pos -= 1
      endif
    " Handle right arrow (move cursor right)
    elseif l:char == "\<Right>"
      if l:cursor_pos < len(l:input_text)
        let l:cursor_pos += 1
      endif
    " Handle printable characters
    elseif type(l:char) == type(0) && l:char >= 32 && l:char <= 126
      let l:input_text = strpart(l:input_text, 0, l:cursor_pos) . nr2char(l:char) . strpart(l:input_text, l:cursor_pos)
      let l:cursor_pos += 1
    endif

    " Update popup with current input + cursor marker
    let l:display_text = l:input_text
    if l:cursor_pos <= len(l:display_text)
      " Add an underscore to show cursor position
      let l:display_text = strpart(l:display_text, 0, l:cursor_pos) . '_' . strpart(l:display_text, l:cursor_pos)
    endif
    call popup_settext(l:popup_id, [a:prompt, l:display_text])
  endwhile
endfunction

Step 2: Add a Rename Feature (Like Coc-Rename)

Now let's use this function to build a rename tool that works like Coc-rename. This will grab the current word, let you edit it in the popup, then replace all occurrences:

function! RenameCurrentWord() abort
  let l:current_word = expand('<cword>')
  let l:new_name = PopupInput('Rename to:', l:current_word)

  " Exit if user cancelled or didn't change the word
  if empty(l:new_name) || l:new_name == l:current_word
    return
  endif

  " Replace all occurrences of the word (add 'c' flag to confirm each change if needed)
  execute '%s/\<' . escape(l:current_word, '/\') . '\>/' . escape(l:new_name, '/\') . '/g'
  echo "Renamed all instances of '" . l:current_word . "' to '" . l:new_name . "'"
endfunction

" Bind to a convenient shortcut (e.g., Leader + rn)
nnoremap <silent> <leader>rn :call RenameCurrentWord()<CR>

Step 3: Customize the Experience

You can tweak this to match your preferences:

  • Adjust Popup Style: Modify the border option to use fancier borders (e.g., ['╭', '─', '╮', '│', '╯', '─', '╰', '│'] for rounded corners) or change highlight to a custom group.
  • Live Preview: To mimic Coc's real-time preview, add a call to update the buffer temporarily during input (reset if the user cancels).
  • Input Validation: Add checks to restrict input to certain characters (e.g., no spaces for variable names).
  • Tab Completion: Integrate Vim's complete() function to add auto-completion for common values.

This setup gives you a native Vimscript solution that behaves almost identically to Coc-rename, without relying on external plugins.

内容的提问来源于stack exchange,提问作者kroyxlab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 08:57:30