【问题标题】:How to change Vim insert mode mappings behavior?如何更改 Vim 插入模式映射行为?
【发布时间】:2011-06-17 19:47:48
【问题描述】:

我已在脚本中插入映射模式date<Tab> 以以YYYY-MM-DD 格式插入当前日期。

inoremap <script> <silent> <buffer> date<Tab> <C-R>=strftime("%Y-%m-%d")<CR>

当我在插入模式下开始输入模式时,Vim 只显示最后输入的字符,而不是显示完整的模式,然后仅在按 Tab 时将其替换为日期字符串当我不想使用它时很讨厌。例如,如果我输入“日期”,这就是 Vim 显示的内容(“|”是光标表示):

  • |d
  • |a
  • |t
  • data|

另外,我安装了 Snipmate vim 插件,它使用 Tab 键将 sn-ps 替换为代码模板,当我输入 sn-p 时,它不起作用就像我之前描述的那样。 Snipmate 所做的是仅映射 Tab 键,当按下该键时,它会获取前一个单词并检查它是否与它的一个 sn-ps 匹配。

也就是说,我会留下两个问题,其中一个问题的答案解决了我的问题:

  • 有没有办法配置 Vim 在将其更改为映射之前不显示完整模式?

  • 我可以让两个插件使用相同的映射吗?就像如果我也映射 Tab 键,只要光标前的单词是“日期”,我的插件就会起作用,而 Snipmate 在其他情况下会起作用。

【问题讨论】:

  • 我认为您最好的选择是编写一个名为 'date' 的 sn-p,它可以扩展为您想要的内容。如果我没记错的话,snipmate 在 sn-ps 中支持本机 vimscript,所以这应该很容易实现。第一个问题的答案是否定的。
  • 实现您想要的最佳方式是通过在插入模式下键入时自动扩展的缩写。您可以参考this answer I gavehow to insert the current time 上的问题,了解有关实施的详细信息。
  • @Randy Morris - 映射用于脚本,所以对我来说没问题,但我不能假设每个人都使用 Snipmate。不过谢谢!

标签: vim


【解决方案1】:

第一个答案是否定的。

第二个也没有,但可以模仿:

通用方式如下(需要frawor):

" plugin/tab.vim
execute frawor#Setup('0.0', {'@/mappings': '0.0'})
" Make sure that mappings were set up
runtime! after/plugin/snipMate.vim

" Get information about already existing mapping
" (it was defined by snipmate)
let s:snipmap=s:_r.map.maparg('<Tab>', 'i', 0)

" Create a new mapping with unique lhs
let s:snipmap.lhs='<SNR>'.s:_sid.'_OldSnipMap'
call s:_r.map.map(s:snipmap)

function s:F.insdate()
    if getline('.')[:(col('.')-1)][-4:] is# 'date'
        return repeat("\<BS>", 4).strftime("%Y-%m-%d")
    else
        " Here is the magic: I have a choice to either use remappable mapping
        " or <C-\><C-o>:call feedkeys()<CR> workaround for nore mapping
        return "\<C-\>\<C-o>:call feedkeys(\"\\<SNR>".s:_sid."_OldSnipMap\")\n"
    endif
endfunction
call s:_f.mapgroup.add('Tab', {'tab': {'lhs': '<Tab>', 'rhs': s:F.insdate, 'mode': 'i'}})

请注意,在您的示例中,您没有映射 &lt;Tab&gt;,而是映射了 date&lt;Tab&gt;,因此它不会干扰 snipmate 映射。上面的代码使用了与 IMAP 插件相同的方法:当 {lhs} 的最后一个键被按下时,检查之前的键是否在缓冲区中。如果它们被删除并插入 {rhs} 代替。因此,无论多么慢,您都可以输入date&lt;Tab&gt;,它会起作用。

注2:这是通用方式。您只需查看 &lt;Tab&gt; {rhs} 即可删除 frawor 依赖项和大部分代码:

function s:Insdate()
    if getline('.')[:(col('.')-1)][-4:] is# 'date'
        return repeat("\<BS>", 4).strftime("%Y-%m-%d")
    else
        return "\<C-g>u\<C-r>=TriggerSnippet()\n"
    endif
endfunction
inoremap <Tab> <C-r>=<SID>Insdate()<CR>

【讨论】:

    【解决方案2】:
    • 据我所知,似乎没有这样的设置可以“关闭”“搜索地图”状态,如果它是键映射匹配中某个地图的一部分,vim 会吃掉您输入的所有字符。

    • Vim 只能将一个键绑定到一个特定的动作,所以没有办法让一个键做两件事你可能希望。另一方面,您可以配置“snipmate”以使用其他键来执行“展开”动作。当您遇到关键冲突问题时,这应该是一种通常的方式。或者,您可以使用“缩写”来做某事:

      :abbreviate <expr> :date: strftime("%Y-%m-%d")  
      

      但是很抱歉,这里也有“吃相配”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-08
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-13
      相关资源
      最近更新 更多