如何使用宏/映射/函数删除Vim中的YAML部分?

时间:2018-01-18 08:03:35

标签: vim yaml

YAML部分以^---开头,没有任何结尾分隔符。示例文件:

--- a header
data:
  key: value
  key2: value
--- another header
data:
  name: 

理想的方法是使用运营商挂起的映射(请参阅a.b.),这样您就可以删除,更改或抽取一个部分。我的部分工作解决方案“围绕---”映射是:

:onoremap a- :<c-u>execute "normal! ?^--- \r:nohlsearch\rVNk"<cr>

这适用于中间部分,但在文件的最后一部分失败,因为它找不到后续的标题匹配。我可以修改搜索,这样除了标题文本(搜索/^--- \|\%$/\v^--- |%$)之外它还会找到文件的结尾,但是错过了文件的最后一行。搜索应该向上移动以不选择后续标题,但如果我们到达文件的末尾,我们就不能上去。

另一种方法是使用/search/offset功能,但我不知道是否有办法将搜索分组以查找偏移量应用于成功{{1}的pattern\|end匹配但不是pattern。由于“高于模式一行”是end,我希望以下类似的东西是可能的(这是简化的语法):

/pattern/-1

这是可能的,还是我需要编写一个函数来改变选择?我还不知道vimscript,所以在这方面的任何指针也会受到赞赏。

3 个答案:

答案 0 :(得分:1)

试试这个:

来源这个功能:

function! GimmeRange() abort
    let pat = '^--- \|\%$'
    let start = search(pat, 'b')
    let end = search(pat)
    let end = end == line('$')? end:end-1
    return ":\<c-u>exec 'normal! ".start.'GV'.( end-start )."+'\<CR>"
endfunction

创建此地图:

onoremap <expr> a-  GimmeRange()  

使用omapping a-

进行测试

答案 1 :(得分:1)

简单的映射:

:map £ mdG:set paste<CR>o---<Esc>:set nopaste<CR>'d$/---<CR>NedddnGdd
  • md:在当前行设置d标记(被认为属于要删除的部分

  • G:转到文件末尾

  • :set paste<CR>:暂时停用autoindent(使用CTRL-V CTRL-M获取<CR>

  • o---<Esc>:添加由---组成的新最后一行(使用CTRL-V ESC获取<Esc>

  • :set nopaste<CR>:恢复之前的自动设置

  • 'd$:转到d标记

  • 行尾
  • /---<CR>N:转到要删除的部分的开头

  • dddn:删除部分标题,然后删除部分正文

  • Gdd:删除最后一行(---的那一行)

答案 2 :(得分:0)

使用Kent建议的功能更清晰,更易于维护,但我能够修改原始映射并将其发布到此处以便完整。

igemnace给了我关于#vim IRC聊天的一些建议。关键是我可以通过在搜索中包含\n来搜索文件中的行结尾(不是文字换行符)。接下来,我需要更改运动字符,因为匹配开始提前一行。我们需要从上面的比赛(j)下线,而我们不需要从下面的比赛中上升(k)。最后,需要使用\zs修改搜索匹配区域,因此如果光标位于标题之前的行上,则vim不会认为光标与匹配重叠。这会导致编辑器在这种情况下删除错误的部分。逻辑是:

  • 向后搜索.*\zs\n--- \|\%$
  • 下线
  • 直观选择,直到下一场LOWER比赛

在所有逃脱之后,它变为:

:onoremap a- :<c-u>execute "normal! ?.*\\\zs\\n--- \\\|\\\%$\r:nohlsearch\rjVN"<cr>

但我不希望映射消灭我的搜索缓冲区,所以我保存并恢复了它:

:onoremap a- :<c-u>let savedSearch=@/\|execute "normal! ?.*\\\zs\\n--- \\\|\\\%$\rjVN"\|let @/=savedSearch<cr>

请注意,当文件以节头开头时,此解决方案不起作用,但YAML从不这样做。这种假设不能移植到其他数据语言,因此编写函数是一个更好的解决方案的另一个原因。