[英]vim: map command with confirmation to key
I've written a few macros in my .vimrc for the version control system I'm using (Perforce) (please don't suggest the perforce plugin for vim, I tried it and I don't like it). 我在我的.vimrc中为我正在使用的版本控制系统编写了一些宏(Perforce)(请不要为vim建议perforce插件,我试过它,我不喜欢它)。 They all work fine except the revert macro, which breaks due to a confirmation prompt (which I need so I don't accidentally fat-finger my changes away).
它们都可以正常工作,除了恢复宏,它由于确认提示而中断(我需要这样做,所以我不会意外地指责我的变化)。 It currently looks like this:
它目前看起来像这样:
map <F8> :if confirm('Revert to original?', "&Yes\n&No", 1)==1 | !p4 revert <C-R>=expand("%:p")<CR><CR><CR>:edit<CR> | endif
This causes bash to complain when vim tries to load the file: 当vim尝试加载文件时,这会导致bash抱怨:
bin/bash: -c: line 0: syntax error near unexpected token `('
Looking at the buffer bash sees, it looks like the error is that vim sends it everything after the first pipe, not just the part meant for bash. 看看缓冲区bash看到的,看起来错误是vim在第一个管道之后发送了所有内容,而不仅仅是用于bash的部分。 I tried a few alternatives but I can't seem to make it work.
我尝试了一些替代方案,但我似乎无法使其工作。 I've got it to show confirm dialog correctly when I removed the pipes and endif (using shorthand if), but then vim complains after the user gives a response.
当我删除管道和endif(使用速记if)时,我已经让它正确显示确认对话框,但是在用户给出响应之后vim会抱怨。
I think you want something along these lines: 我想你想要这样的东西:
:map <F8> :if confirm('Revert to original?', "&Yes\n&No", 1)==1 <Bar> exe "!p4 revert" . expand("%:p") <Bar> edit <Bar> endif<CR><CR>
Remember that :map
is a dumb sequence of keystrokes: what you're mapping F8
to has to be a sequence of keystrokes that would work if typed. 请记住
:map
是一个愚蠢的击键序列:你将F8
映射到必须是一系列击键,如果键入的话。 A <CR>
in the middle of the :if
statement doesn't mean 'and press Enter
when executing the command at this point if the condition is true'; 在
:if
语句中间的<CR>
并不意味着'并且如果条件为真,则在此时执行命令时按Enter
'; it means 'press Enter
here when in the middle of typing in the :if
command', which obviously isn't what you want. 这意味着'在输入
:if
命令'的过程中按Enter
,这显然不是你想要的。
Building it up a piece at time, from the inside out: 从内到外,随时将它构建成一块:
:if
to do the 'sometimes' bit, and so have an :endif
following it. :if
要执行'有时'位,所以有一个:endif
跟随它。 !
!
everything following is passed to the shell, including |
|
characters which normally signify the start of another Vim command. |
|
is a perfectly good character to use in shell commands. :exe
can do this; :exe
可以做到这一点; it executes the supplied string as a command — and its argument, being a string, has a defined end. :if condition | exe "!shell command" | endif
:if condition | exe "!shell command" | endif
:if condition | exe "!shell command" | endif
:if condition | exe "!shell command" | endif
. :if condition | exe "!shell command" | endif
。 :exe
makes this easy, since you can simply concatenate the string constant parts of the command with the result of the expression. :exe
使这很容易,因为您可以简单地将命令的字符串常量部分与表达式的结果连接起来。 So the command becomes :exe "!p4 revert" . expand("%:p")
:exe "!p4 revert" . expand("%:p")
:exe "!p4 revert" . expand("%:p")
— try that out on its own on a file, and check it does what you want before going any further. :exe "!p4 revert" . expand("%:p")
- 在文件上自行尝试,并在继续之前检查它是否符合要求。 :if confirm('Revert to original?', "&Yes\\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif
:if confirm('Revert to original?', "&Yes\\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif
:if confirm('Revert to original?', "&Yes\\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif
:if confirm('Revert to original?', "&Yes\\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif
— again try that out before defining the mapping. :if confirm('Revert to original?', "&Yes\\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif
- 在定义映射之前再次尝试。 |
|
does end a mapping and signify the start of the next Vim command. :map <F8>
after loading a file) and the !p4
part was being run immediately, on the Vim file that defines the mapping! :map <F8>
检查)并且在定义映射的Vim文件上立即运行!p4
部分! You need to change each |
|
in your command into <Bar>
, similarly to how each press of Enter
in your command needs writing as <CR>
. <Bar>
命令中,类似于在命令中按Enter
的方式需要写为<CR>
。 That gives you the mapping above. :map <F8>
again to check it's what you think it is. :map <F8>
再次:map <F8>
以检查它是否符合您的想法。 And only then try pressing F8
. F8
。 Use of the pipe to string multiple vim commands together is not particularly well-defined, and there are numerous eccentricities. 使用管道将多个vim命令串在一起并不是特别明确,并且存在许多偏心。 Critically, (see
:help :bar
) it can't be used after a command like the shell command :!
关键的是,(参见
:help :bar
)它不能在像shell命令之类的命令之后使用:!
which sees a |
看到一个
|
character as its argument. 字符作为其参数。
You might find it easier to use the system()
function. 您可能会发现使用
system()
函数更容易。
EG 例如
:echo system("p4 revert " . shellescape(expand("%:p")))
The shellescape()
wrapper is useful in case you have characters like spaces or quotes in the filename (or have cleverly named it ; rm -rf ~
(Don't try this at home!)). shellescape()
包装器非常有用,以防你在文件名中有空格或引号等字符(或者巧妙地命名它; rm -rf ~
(不要在家里试试!))。
In the interest of creating more readable/maintainable code, you may want to move your code into a function: 为了创建更易读/可维护的代码,您可能希望将代码移动到一个函数中:
function Revert()
if confirm('Revert to original?', "&Yes\n&No", 1)==1
return system("p4 revert " . shellescape(expand("%:p")))
endif
endfunction
which you would access by using the :call
or :echo
command in your macro. 您可以在宏中使用
:call
或:echo
命令访问它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.