点重复映射以从正常模式插入 space 并沿移动光标

Dot-repeatable mapping to insert a space from normal mode and move the cursor along

我有一个映射 nnoremap <leader>l i<space><esc>,它在保持正常模式时插入一个 space,并且映射是点重复的。但是,光标停留在原来的位置,space“扩展”到光标右侧。

我想要一个具有相同功能但移动光标的映射,例如

nnoremap <leader>h i<space><esc>l

我喜欢在正常模式下使用 space 打破字符序列,我想随意决定光标是停留还是移动(使用 h 移动光标或 l 将文本向左移动,同时将光标留在原处。

None ia<C-o> 的技巧似乎有效,这是预期的行为。

是否有任何巧妙的技巧可以仅使用 nnoremap 来实现点重复性?如果我在行尾,它也应该有效。

我或许可以这样重新表述:我希望具有类似于 Xx 的功能,即删除光标前或光标处的单个字符,而不是删除一个字符我想在 <space> beforeat 光标处插入一个(而不是像 a 那样在光标之后)。而且它应该是点可重复的并且可以计数。最好是在 .vimrc 中不使用多于一行且不需要任何插件的映射。而且我不想更改将光标向左移动一个字符的 <esc>(或 i,无论哪个负责在离开插入模式时移动光标)的行为。

编辑 1: 点重复 nnoremap <leader>l i<space><esc> 这样做:

<leader>l...

AAAAAAAAAA[B]BBBBBBBB
AAAAAAAAAA[ ]BBBBBBBBB
AAAAAAAAAA[ ] BBBBBBBBB
AAAAAAAAAA[ ]  BBBBBBBBBB

我想要一个可重复点的 <leader>h 可以做到这一点:

<leader>h...

AAAAAAAAAA[B]BBBBBBBB
AAAAAAAAAA [B]BBBBBBBB
AAAAAAAAAA  [B]BBBBBBBB
AAAAAAAAAA   [B]BBBBBBBBB

编辑 2:

@romainl 在回复中提到的解决方法可以解决问题:

function! s:insspace(...)
    if a:0
      " perform operation
      execute 'normal' v:count1.'i '."\<esc>".'l'
    else
      " set up
      let &operatorfunc = matchstr(expand('<sfile>'), '[^. ]*$')
      return "g@\<space>"
    endif
endfunction

nnoremap <silent><expr> <leader>h <sid>insspace()

谁能解释一下它是如何工作的?我是 vim...

的初学者

给定以下字符串并假设光标位于 -:

lorem-ipsum
     ^

有多种简单且可重复的方法可以在 - 之后插入 space 并将光标留在 space 上:

a <Esc>
s<C-r>" <Esc>

lorem- ipsum
      ^

上面的两个宏…

  • 是“可重复的点”,因为不涉及运动,
  • 将光标留在 space 上,因为在插入后,Vim 将光标放在最后插入的字符上。

但这恰恰是后一种行为阻止了我们在插入之前或之后在没有运动的情况下在另一个方向上做同样的事情。

没有运动,操作是“点重复”但光标留在 -:

i <Esc>
a <Esc>
s <C-r>"<Esc>

lorem -ipsum
      ^

随着运动,光标留在 space 但操作不是“点重复”:

i <Esc><Left>
<Left>a <Esc>
s <C-r>"<Esc><Left>

lorem -ipsum
     ^

The workaround有点做作但很漂亮。

也许我对你的问题理解不够透彻,但对我来说这就是诀窍:

:nnoremap <leader>h i<space><esc>w

原理:插入space,在<ESC>后向左走一个,所以光标停留在space,使用w到下一个词界。

这是你想要的吗?我现在可以做 5\h 并且在向左插入 spaces 时它会停留在当前位置。