如何修复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()
关键修改点
- 调整逻辑优先级:先执行可视化模式的替换逻辑,处理完成后用
return跳过后续插入代码,避免重复写入缓冲区。 - 简化冗余操作:去掉了
normal! gvy获取选中内容的步骤(我们不需要原选中内容,直接替换即可)。 - 可选优化:可以利用命令的
-range参数(a:firstline/a:lastline)更准确判断是否存在选中范围,适配手动指定范围的场景。
内容的提问来源于stack exchange,提问作者tribhuwan
相关产品推荐
相关产品推荐

