2012-09-12 15 views
2

这是我做的
:syntax match conceal Test +[A-Z0-9]\{6}+
:set conceallevel=2
:set concealcursor=nvi
所以,当我在写的vim我123456希望它是什么也没有。但是当我移动到那个区域时实际发生的事情是,我必须沿着我想移动光标的方向移动6次以通过该区域。Vim的隐藏功能,还是让我搬过来的所有字符

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

+0

很遗憾,我认为这个功能不存在 – sehe

+0

如果它没有注册为光标位置,如何用'd {motion}'删除它?尽管隐藏功能,Vim仍然是一个文本编辑器。 –

回答

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)和正常模式,只是为了显示它可能完成的方式。

+0

函数的工作方式将光标放在行尾,每次你经过一个隐藏的物品。我猜这是因为'let lc = col('$')',你永远不会改变它。我测试了这个函数,它在我放入'let lc = col('6')'时起作用,所以我接受它,而我想我仍然可以使它工作:)编辑:编写vim仍然很新功能。 – plitter

+0

@plitter在vim帮助文件上测试时,它没有这样做。它也不应该这样做:'lc'是“最后一列”的缩写:当您可以将光标移动过去时,它用于处理'virtualedit'情况,以及隐藏项目是行中最后一个的情况。在这两种情况下,完全不需要改变它。我不知道你的改变为什么起作用,但它绝对不是正确的做法,它不能解决任何问题,只是通过创建另一个问题来掩盖一个问题。 – ZyX

+0

@plitter增加:它打算做第一个。我忘了用'lc'代替'col('$')',现在做了这个。 – ZyX

2

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) 
+0

差不多!对我来说,隐藏的id会改变每个调用,所以我只能依赖synconcealed()中的第一个var。看到它在这里工作[改善对隐藏文本的移动](https://github.com/albfan/ag.vim/commit/bdccf94877401035377aafdcf45cd44b46a50fb5) – albfan