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,所以在这方面的任何指针也会受到赞赏。
答案 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--- \|\%$
在所有逃脱之后,它变为:
: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从不这样做。这种假设不能移植到其他数据语言,因此编写函数是一个更好的解决方案的另一个原因。