接受用户输入的Vim宏

uqdfh47h  于 2022-11-11  发布在  其他
关注(0)|答案(2)|浏览(184)

假设我有以下文本文件

name: John Doe
description: My name is John Doe and I'm really good at vim!
name: John Doe
description: My name is John Doe and I'm really good at vim!
name: John Doe
description: My name is John Doe and I'm really good at vim!
name: John Doe
description: My name is John Doe and I'm really good at vim!

是否有一种方法可以录制执行以下操作的宏:
从第一个John开始:

  1. cw,但允许运行宏的用户给予此处输入
  2. js<is>w在is之后偷偷输入单词
  3. .用给定的输入替换John
    1.重复播放
    理想情况下,我希望在第一行输入以下键击:
    @qJane
    且具有:
name: Jane Doe
description: My name is Jane Doe and I'm really good at vim!

@qJim

name: Jim Doe
description: My name is Jim Doe and I'm really good at vim!
ctehm74n

ctehm74n1#

接受用户输入的最简单方法是使用input()函数,该函数允许您提示输入名称并在表达式中使用它。
不幸的是,您不能真正从宏中使用它,因为宏也会记录您对提示符的回答(并且重放您构建的宏也会有类似的问题)。
您可以通过函数使用它,并将该函数绑定到键Map:

function! ChangeName()
  let newname = input('Name? ')
  return '0/\<John\>'."\<cr>cw".newname."\<esc>n."
endfunction
nnoremap <expr> <leader>cn ChangeName()

然后您可以键入\cn,系统将提示您输入新名称。键入新名称并按Enter后,系统将用新名称替换出现的前两个John
该函数返回Map的扩展,在map命令中使用<expr>以使其使用该函数的返回值。(让该函数发出带有:execute:normal!命令也是一种可能的方法。)
您提到了按@qJim@qJane,此时没有提示符,并且新名称“感觉”像是命令的一部分。通过在Map背后的函数的循环中使用getchar(),可以更接近于这样的操作。您仍然需要决定如何终止名称,你会在最后按回车键吗?你会用计时来决定命令什么时候结束吗如果使用getchar(),您可能还需要处理退格和取消命令。使用input()当然更容易,并且根据您的特定用例可能已经足够了。

5n0oy7gb

5n0oy7gb2#

虽然q经常与术语 macro 一起使用,但其目的只是记录和重复字符序列。重复是这里的关键-如果您的目的不是重复完全相同的序列,那么q可能不是理想的解决方案。
使用map应该可以很容易地实现这一点(注意,:h macro会将您指向:map)。可以使用:execute构建一个命令,用input()返回的任何内容替换当前行和下一行中第一个出现的 John。后者负责提示用户。
下面是一个Map到,n的小例子:

:nnoremap ,n :exe ',+s/John/' . input('Name: ')<CR>

如果您不知道要替换的名称,您也可以询问:

:nnoremap ,n :exe ',+s/' . input('Old name: ') . '/' . input('New name: ')<CR>

或者使用一个正则表达式来捕获“name”后面的第一个单词,忽略“:“或“is”:

:nnoremap ,n :exe ',+s/\vname(: \| is )+\zs\w+/' . input('New name: ')<CR>

相关问题