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

如何修复Neovim颜色选择器插件替换选中文本时的追加问题?

问题根源

你的代码核心问题是逻辑执行顺序错误:不管是否处于可视化模式,都会先执行普通光标位置的插入逻辑,之后才执行选中内容的替换逻辑。这导致颜色值先被插入到光标位置,再替换选中内容,最终表现为“追加”效果。

修复方案

调整逻辑顺序,优先处理可视化模式的替换需求,处理完成后直接跳过后续插入逻辑;同时简化冗余代码,确保逻辑清晰。

修改后的完整代码

function! s:open_color_picker()
    " 先获取颜色值(避免重复执行系统命令)
    let color_picker_path = system('find ~/.local/share/nvim -type f -name color_picker.py')
    let color_picker_path = substitute(color_picker_path, '\n\+$', '', '')
    let color_picker_path = substitute(color_picker_path, '^\\n\+', '', '')

    let color = system('python3 ' . shellescape(color_picker_path))
    let color = substitute(color, '\n\+$', '', '')
    let color = substitute(color, '^\\n\+', '', '')

    " 优先处理可视化模式的替换逻辑
    let is_visual_mode = (mode() ==# 'v' || mode() ==# 'V' || mode() ==# "\<C-v>")
    " 可选优化:利用命令的range参数更准确判断选中状态
    " let is_visual_mode = a:firstline != a:lastline || (a:firstline == a:lastline && a:firstcol != a:lastcol)
    if is_visual_mode
        let old_reg = getreg('"')
        let old_regtype = getregtype('"')

        let start_pos = getpos("'<")
        let end_pos = getpos("'>")

        let start_line = start_pos[1]
        let start_col = start_pos[2]
        let end_line = end_pos[1]
        let end_col = end_pos[2]

        if start_line == end_line
            let current_line = getline(start_line)
            let new_line = current_line[:start_col-2] . color . current_line[end_col-1:]
            call setline(start_line, new_line)
        else
            let first_line = getline(start_line)
            let last_line = getline(end_line)
            let new_first_line = first_line[:start_col-2] . color
            let new_last_line = last_line[end_col-1:]
            call setline(start_line, new_first_line)
            call setline(end_line, new_last_line)
            if end_line - start_line > 1
                call deletebufline('%', start_line + 1, end_line - 1)
            endif
        endif

        call setreg('"', old_reg, old_regtype)
        " 处理完可视化模式后直接返回,跳过普通插入逻辑
        return
    endif

    " 非可视化模式下执行光标位置插入逻辑
    let lnum = line('.')
    let col = col('.')
    let current_line = getline(lnum)

    let insert_after = get(g:, 'NVIMColorPicker#InsertAfter#TheCursor', 0)
    let insert_before = get(g:, 'NVIMColorPicker#InsertBefore#TheCursor', 0)

    if insert_after
        let hex_color = substitute(current_line, '\%' . (col + 1) . 'c', "\\0" . color, '')
        call setline(lnum, hex_color)
    elseif insert_before
        let hex_color = strpart(current_line, 0, col - 1) . color . strpart(current_line, col - 1) 
        call setline(lnum, hex_color)
    else
        let hex_color = substitute(current_line, '\%' . (col + 1) . 'c', "\\0" . color, '')
        call setline(lnum, hex_color)
    endif
endfunction

command! -range ColorPicker call s:open_color_picker()

关键修改点

  1. 调整逻辑优先级:先执行可视化模式的替换逻辑,处理完成后用return跳过后续插入代码,避免重复写入缓冲区。
  2. 简化冗余操作:去掉了normal! gvy获取选中内容的步骤(我们不需要原选中内容,直接替换即可)。
  3. 可选优化:可以利用命令的-range参数(a:firstline/a:lastline)更准确判断是否存在选中范围,适配手动指定范围的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:09:54