简体   繁体   English

vim:map命令,确认键

[英]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: 从内到外,随时将它构建成一块:

  1. There's a shell command you sometimes want to run. 你有时想运行一个shell命令。
  2. That shell command needs to be inside an :if to do the 'sometimes' bit, and so have an :endif following it. 那个shell命令需要在一个内部:if要执行'有时'位,所以有一个:endif跟随它。
  3. After a literal ! 字面意思之后! everything following is passed to the shell, including | 以下所有内容都传递给shell,包括| characters which normally signify the start of another Vim command. 通常表示另一个Vim命令开始的字符。 That's reasonable, because | 这是合理的,因为| is a perfectly good character to use in shell commands. 是一个在shell命令中使用的完美字符。 So we need some way of containing the shell command. 所以我们需要一些包含shell命令的方法。 :exe can do this; :exe可以做到这一点; it executes the supplied string as a command — and its argument, being a string, has a defined end. 它将提供的字符串作为命令执行 - 其参数(作为字符串)具有已定义的结尾。 So the general form is :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
  4. Your shell command has an expression in it. 你的shell命令中有一个表达式。 Using :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") - 在文件上自行尝试,并在继续之前检查它是否符合要求。
  5. Putting that inside the condition gives you :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 - 在定义映射之前再次尝试。
  6. Once you have that working, define the mapping. 完成后,定义映射。 A literal | 文字| does end a mapping and signify the start of the next Vim command. 确实结束映射并表示下一个Vim命令的开始。 In your original the mapping definition only went to the end of the condition (check it with :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. 这为您提供了上面的映射。 Try it by typing it at the command line first, then do :map <F8> again to check it's what you think it is. 首先在命令行输入它,然后执行:map <F8>再次:map <F8>以检查它是否符合您的想法。 And only then try pressing F8 . 然后尝试按F8
  7. If that works, put the mapping in your .vimrc . 如果可行,请将映射放在.vimrc中

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM