我定义了两个用于在Vim中快速插入foldmarkers的宏:
nnoremap <leader>mb A {{{<Esc>0
nnoremap <leader>me o# }}}<Esc>0zc
但很快就发现它们对于不使用#
作为注释字符串的所有内容感到相当不满意。
所以我想出了这个动态,但它不起作用:
nnoremap <leader>mb A {{{<Esc>0
nnoremap <leader>me :call s:InsertFoldEnding()
…
function! s:InsertFoldEnding()
l:line=call line('.')
l:str=&commentstring + '}}}'
call append(l:line, l:str)
endfunction
错误讯息:
E81: Using <SID> not in a script context
有什么问题?是否有更好的方法来插入这些折叠?
我希望折叠最终看起来像这样:
" Caption {{{
Content
" }}}
答案 0 :(得分:4)
你有很多错误。
s:
函数。您需要将s:
替换为<SID>
,并确保在定义该函数的同一文件中定义映射。 (或者手动展开<SID>
“,但这很棘手。)l:line=…
是一个错误的赋值表达式。使用:let
分配和删除l:
前缀(在函数上下文中,它是默认值)。&commentstring+'}}}'
可能会导致0
。 +
始终是数字加法,使用.
来连接字符串。append()
函数没有缩进。因此,您需要在行前加matchstr(getline('.'), '^\s*')
或做更聪明的事情。&commentstring
看起来像/*%s*/
。您无需连接,您需要使用printf(&cms, '}}}')
或substitute()
。split(&foldmarker, ',')[0]
代替'{{{'
和split(&foldmarker, ',')[1]
代替'}}}'
。我个人使用这个(不直接你需要的东西,至少没有一些编辑):
function InsertBlock(foldlevel, ...)
let line=getline('.')
if !empty(a:000)
let text=a:000[0]
else
let text=matchstr(line, '\S.*\S\@<=')
endif
if empty(line)
normal! "_cc_"
let indent=getline('.')[:-3]
else
let indent=matchstr(line, '^\s*')
endif
let cmsl=split(&commentstring, '%s', 1)
let [startmarker, endmarker]=split(&foldmarker, ',')
let left=(indent).get(cmsl, 0, '').startmarker
if a:foldlevel>0
let left.=a:foldlevel
elseif a:foldlevel==0
let left.='1'
endif
let left.=' '.text
let right=''
if !empty(get(cmsl, 1, ''))
let right=' '.cmsl[1]
endif
call setline('.', left)
normal! $
if !empty(right)
call setline('.', left.right)
normal! l
endif
if a:foldlevel==-1
call append('.', (indent).get(cmsl, 0, '').endmarker)
endif
endfunction
function CloseBlock(foldlevel)
if a:foldlevel==0
return
endif
let [startmarker, endmarker]=split(&foldmarker, ',')
let foldstart=search('\V'.escape(startmarker, '\').a:foldlevel, 'bnW')
let cmsl=split(&commentstring, '%s', 1)
if foldstart
let indent=matchstr(getline(foldstart), '^\s*')
else
normal! "_cc_"
let indent=getline('.')[:-3]
endif
call setline('.', (indent).get(cmsl, 0, '').endmarker.a:foldlevel.
\ get(cmsl, 1, ''))
endfunction
nnoremap ,{ o<C-o>:call InsertBlock(foldlevel('.'))<CR><Esc>
nnoremap ,} o<C-o>:call InsertBlock(foldlevel('.')+1)<CR><Esc>
nnoremap ,[ o<C-o>:call InsertBlock(foldlevel('.')-1)<CR><Esc>
nnoremap ,- o<C-o>:call CloseBlock(foldlevel('.'))<CR><Esc>
inoremap ,{ <C-o>:call InsertBlock(foldlevel('.'))<CR>
inoremap ,} <C-o>:call InsertBlock(foldlevel('.')+1)<CR>
inoremap ,[ <C-o>:call InsertBlock(foldlevel('.')-1)<CR>
inoremap ,- <C-o>:call CloseBlock(foldlevel('.'))<CR>
inoremap ,+ <C-o>:call InsertBlock(foldlevel('.')+1)<CR><CR><C-o>:call CloseBlock(foldlevel('.'))<CR>
。请注意,这a)将非空行转换为标记,标题看起来像"▶3 Caption
({{{
太胖而无法使用)。结束标记的使用更为罕见,它们看起来像"▲3
。具有水平的标记自动结束具有更大或相同水平的所有折叠,因此大多数时间不需要结束标记。