在 vim 中反复粘贴/放下垂直块

在 vim 中反复粘贴/放下垂直块

在 vim 中,当我选择了一个垂直块(例如单列文本)时,我希望能够重复放置(粘贴)当前寄存器中的任何内容。例如,如果我有类似以下内容:

用户名0 密码0 个人信息0
用户名1 密码1 个人信息1
...
用户名9 密码9 个人信息9

并且我选择了用户名和密码之间的文本列(即两者之间的空格列),我希望能够将内容放在那里(粘贴)。从某种意义上说,这很好:我可以放一些东西,但如果选择的长度超过寄存器,则选择的其余部分将被替换为空。相反,我希望它做一些事情,比如重复选择寄存器。除了使用正则表达式之外,还有什么方法可以做到这一点?

答案1

如果新列在每一行上都有相同的值(即,您最初复制的内容在一行上),那么可能更容易在视觉上阻止选择用户名和密码列之间的空格,然后键入A(或I)以开始追加(插入)。当您返回正常模式(Esc)时,Vim 也会将文本附加到原始选择的其余部分。

如果您确实需要做重复模式,那么您可以使用这样的函数和映射:

:function! PutRegFilledToRange() range
:  let l:fill = ''
:  let l:lines = getreg()
:  let l:lineStart = 0
:  let l:linesLen = strlen(l:lines)
:  let l:lineIndex = 0
:  let l:linesNeeded = a:lastline - a:firstline + 1
:  while l:lineIndex < l:linesNeeded 
:    let l:lineEnd = matchend(l:lines, "\n\\|$", l:lineStart)
:    let l:line = strpart(l:lines, l:lineStart, l:lineEnd - l:lineStart)
:    if l:lines[l:lineEnd - 1] != "\n" 
:      let l:line = l:line . "\n"
:    endif
:    let l:fill = l:fill . l:line
:    let l:lineStart = l:lineEnd < l:linesLen ? l:lineEnd : 0
:    let l:lineIndex = l:lineIndex + 1
:  endwhile
:
:  normal gv
:  " This probably does not make much sense in any mode
:  " other than block modes, but we will try to cope.
:  if mode() == "\<C-V>" || mode() == "\<C-S>"
:    let l:newMode = "\<C-V>"
:  elseif mode() == 'v' || mode() == 's'
:    let l:newMode = 'v'
:  else
:    let l:newMode = 'V'
:  endif
:  let l:origReg = getreg('')
:  let l:origRegType = getregtype('')
:  try
:    call setreg('', l:fill, l:newMode)
:    execute 'normal ' . v:count1 . 'p'
:  finally
:    call setreg('', l:origReg, l:origRegType)
:  endtry
:endfunction
:vmap _f :call PutRegFilledToRange()<CR>

放入你的 .vimrc 或其他文件(并运行 :source /path/to/file)。或者直接将其粘贴到 Vim 会话中。

使用方法:

  • C-V{motion}y:以可视方式块选择并拖拽要重复使用的文本
  • {motion}C-V{motion}:选择要替换的块
  • _f:用当前寄存器的重复行填充选定的块(用"a_f寄存器 a 中的行填充块)

相关内容