【问题标题】:Insert ending foldmarker in vim with variable commentstring使用变量注释字符串在 vim 中插入结束折叠标记
【发布时间】:2013-03-20 17:09:20
【问题描述】:

我定义了两个宏用于在 Vim 中快速插入折叠标记:

nnoremap <leader>mb A {{{<Esc>0
nnoremap <leader>me o# }}}<Esc>0zc

但很快发现它们对于不使用 # 作为 cmetstring 的所有内容都相当不满意。

所以我想出了这个动态地做,但它不起作用:

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
" }}}

【问题讨论】:

  • 为什么不使用zf 创建折叠?
  • 因为所做的只是将"{{{"}}} 附加到第一行和最后一行的末尾。这不是我想要的。

标签: vim folding


【解决方案1】:

你有一大堆错误。

  1. “在脚本上下文中使用 ”用于调用 s: 函数。您需要将s: 替换为&lt;SID&gt;,并确保在定义函数的同一文件中定义映射。 (或“手动”扩展&lt;SID&gt;,但这相当棘手。)
  2. l:line=… 是错误的赋值表达式。使用:let 分配和删除l: 前缀(在函数上下文中它是默认前缀)。
  3. &amp;commentstring+'}}}' 可能会导致 0+ 始终是数字加法,使用 . 连接字符串。
  4. append() 函数没有缩进。因此,您需要将 matchstr(getline('.'), '^\s*') 添加到您的线路或做一些更聪明的事情。
  5. &amp;commentstring 看起来像 /*%s*/。您不需要连接,您需要使用printf(&amp;cms, '}}}')substitute()
  6. 标记是可配置的。使用split(&amp;foldmarker, ',')[0] 代替'{{{'split(&amp;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。具有级别的标记会自动以更大或相等的级别结束所有折叠,因此大部分时间不需要结束标记。

【讨论】:

  • 我想我会用你的sn-p然后......我没有希望得到vimscript(也没有欲望;))。
  • 什么是 ?某种内置的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2012-08-11
相关资源
最近更新 更多