3

这就是我所做的
:syntax match conceal Test +[A-Z0-9]\{6}+
:set conceallevel=2
:set concealcursor=nvi
所以当我用123456vim 编写时,我希望它在那里什么都没有。但是,当我移过该区域时,实际发生的情况是,我必须向要移动的方向移动 6 次,光标才能通过该区域。

有没有办法解决这个问题?我希望 vim 看到它,好像那里什么都没有,当我移过那个区域时,就好像那里什么都没有。但我仍然希望能够搜索并删除它。

4

2 回答 2

9

目前没有内置的方法可以做到这一点。您可以使用synconcealed()来确定光标下是否有隐藏字符以及隐藏字符并重新映射所有移动键以尊重它:像这样:

function! ForwardSkipConceal(count)
    let cnt=a:count
    let mvcnt=0
    let c=col('.')
    let l=line('.')
    let lc=col('$')
    let line=getline('.')
    while cnt
        if c>=lc
            let mvcnt+=cnt
            break
        endif
        if stridx(&concealcursor, 'n')==-1
            let isconcealed=0
        else
            let [isconcealed, cchar, group]=synconcealed(l, c)
        endif
        if isconcealed
            let cnt-=strchars(cchar)
            let oldc=c
            let c+=1
            while c<lc && synconcealed(l, c)[2]==group | let c+=1 | endwhile
            let mvcnt+=strchars(line[oldc-1:c-2])
        else
            let cnt-=1
            let mvcnt+=1
            let c+=len(matchstr(line[c-1:], '.'))
        endif
    endwhile
    return ":\<C-u>\e".mvcnt.'l'
endfunction
nnoremap <expr> l ForwardSkipConceal(v:count1)

. 注意:这对单个动作 ( l) 和在正常模式下执行此操作,只是为了显示它可能完成的方式。

于 2012-09-13T04:43:12.457 回答
4

ZyX 从上面的解决方案对我不起作用:显然隐藏文本区域的 ID 在遍历它时会发生变化,导致运动过早停止。

我一直在使用下面粘贴的替代版本(也缺少BackwardSkipConceal功能)。它不是很漂亮,但在替换 LaTeX 文档或 C++ 代码中的数学字符时效果很好。

function! ForwardSkipConceal(count)
    let cnt=a:count
    let mvcnt=0
    let c=col('.')
    let l=line('.')
    let lc=col('$')
    let line=getline('.')
    while cnt
        if c>=lc
            let mvcnt+=cnt
            break
        endif
        if stridx(&concealcursor, 'n')==-1
            let isconcealed=0
        else
            let [isconcealed, cchar, group] = synconcealed(l, c)
        endif
        if isconcealed
            let cnt-=strchars(cchar)
            let oldc=c
            let c+=1
            while c < lc
              let [isconcealed2, cchar2, group2] = synconcealed(l, c)
              if !isconcealed2 || cchar2 != cchar
                  break
              endif
              let c+= 1
            endwhile
            let mvcnt+=strchars(line[oldc-1:c-2])
        else
            let cnt-=1
            let mvcnt+=1
            let c+=len(matchstr(line[c-1:], '.'))
        endif
    endwhile
    return ":\<C-u>\e".mvcnt.'l'
endfunction

function! BackwardSkipConceal(count)
    let cnt=a:count
    let mvcnt=0
    let c=col('.')
    let l=line('.')
    let lc=0
    let line=getline('.')
    while cnt
        if c<=1
            let mvcnt+=cnt
            break
        endif
        if stridx(&concealcursor, 'n')==-1 || c == 0
            let isconcealed=0
        else
            let [isconcealed, cchar, group]=synconcealed(l, c-1)
        endif
        if isconcealed
            let cnt-=strchars(cchar)
            let oldc=c
            let c-=1
            while c>1
              let [isconcealed2, cchar2, group2] = synconcealed(l, c-1)
              if !isconcealed2 || cchar2 != cchar
                  break
              endif
              let c-=1
            endwhile
            let c = max([c, 1])
            let mvcnt+=strchars(line[c-1:oldc-2])
        else
            let cnt-=1
            let mvcnt+=1
            let c-=len(matchstr(line[:c-2], '.$'))
        endif
    endwhile
    return ":\<C-u>\e".mvcnt.'h'
endfunction

nnoremap <expr> l ForwardSkipConceal(v:count1)
nnoremap <expr> h BackwardSkipConceal(v:count1)
于 2014-06-14T21:43:36.830 回答