如何在 vim 中进行类似标记的映射

How to do mark-like mapping in vim

m 普通命令在它后面接受一个字母以设置“字母”标记。

我想创建一个跨选项卡的类似命令...但我的问题是绑定:是否有一种简单的方法来绑定例如 M<letter> 到一个函数或命令或者应该我手动重复所有的可能性?

正如romainl已经说过的,不。

为了更好地解决这个问题(以防其他人后来出现),您实际上只能映射大写字母。如文档中所述,小写标记仅在单个文件中有效。大写字母,Vim 文档称为“文件标记”,在任何地方都有效。除非你有一些黑魔法功能来解决不明确的文件标记,否则你可能只需要一个 for 循环映射大写字母,如果你要使用暴力选项。

也就是说,这里也有几个替代方案。

据我所知,命令的唯一“动态”位是计数(或范围,但除非您想将字符映射到数字(并处理范围和其他有趣的事情 stuff:tm :),我不推荐这种方法:

" The <C-U> is required for all uses. If you want a function,
" you'd need :<C-U>call YourFunction()<cr>
nnoremap M :<C-U>echom v:count<cr>

另见 :h v:count,其中指出:

Note: the <C-U> is required to remove the line range that you get when typing ':' after a count.

然后您可以 运行 26M,将 v:count 解码为 Z,然后从那里进行任何奇特的查找。


第二种选择,也是 romainl 提出的一种,也是迄今为止在这种情况下最常用的一种(来源:经验和大量代码浏览),是使用 for 循环来暴力映射字母:

for i in range(char2nr('A'), char2nr('Z'))
    exec 'nnoremap M' . nr2char(i) ':echo "This is where the appropriate function call goes"<cr>'
endfor

生成所有 26 个映射。


最后的方法是滥用getchar()。这意味着单个映射,但以进行额外处理为代价:

func! Func()
    let c = getchar()
    echo c
    " Character processing (the `echo` isn't required) here
endfunc
nnoremap M :call Func()<cr>

您可以决定哪个适合您,但我强烈建议您选择选项 2,因为这会为您提供地图超时和清晰的定义,以及更明显的冲突检测。