2012-10-04 59 views
1

我想要一个动作跳转到代码块的末尾。我写了一个函数,我试图onoremap它,但它不起作用。这是我做的:编写自定义动作需要一些帮助

onoremap <silent> } :set opfunc=MovementToEdgeOfBlock(1)<cr>[email protected] 

如果我做的只是:

nnoremap <silent> } :call MovementToEdgeOfBlock(1)<cr> 

则函数按预期工作。但我更需要它作为其他命令的运动。那么我做错了什么?

下面是函数本身(我不认为这个问题是在功能,但无论如何):

function! MovementToEdgeOfBlock(direction) 
    let startLine=line(".") 
    function! HowManyTabs(line) 
     let i=0 
     while a:line[i]==#"\t" 
      let i+=1 
     endwhile 
     return i 
    endfunction 
    let startLineTabs = HowManyTabs(getline(".")) 
    echom startLineTabs " tabs" 
    if a:direction==1 
     let tabs=HowManyTabs(getline(line('.')+1)) 
    else 
     let tabs=HowManyTabs(getline(line('.')-1)) 
    endif 
    while tabs>startLineTabs 
     if a:direction==1 
      execute "normal! j" 
     else 
      execute "normal! k" 
     endif 
     let tabs=HowManyTabs(getline(line('.'))) 
    endwhile 
endfunction 

回答

2

你有没有仔细阅读:h 'opfunc',包括:h [email protected]其被引用在那里?它完全与你想要达到的目标无关。更多,[email protected]从来没有打算在操作等待模式下工作。更多的,'opfunc'选项需要一个函数名称,而不是像您尝试传递它的表达式,并将此函数传递给一个字符串参数。

你应该做的是首先尝试创建完全相同的映射用于运营商挂起模式,就像在普通模式下使用一样。如果这不起作用尝试使用<expr>映射:我会写你的函数如下:

" Do not redefine function each time ToEdgeOfBlock is called, 
" put the definition in global scope: There is no way to have 
" a local function in any case. 
" The following does exactly the same thing your one used to do (except 
" that I moved getline() here), but faster 
function! s:HowManyTabs(lnr) 
    return len(matchstr(getline(a:lnr), "^\t*")) 
endfunction 
function! s:ToEdgeOfBlock(direction) 
    let startlnr=line('.') 
    let startlinetabs=s:HowManyTabs(startlnr) 
    let shift=(a:direction ? 1 : -1) 
    let nextlnr=startlnr+shift 
    while s:HowManyTabs(nextlnr)>startlinetabs && 1<=nextlnr && nextlnr<=line('$') 
     let nextlnr+=shift 
    endwhile 
    return nextlnr.'gg' 
endfunction 
noremap <expr> } <SID>ToEdgeOfBlock(1) 

我的版本还允许您使用撤消的<C-o>跳。

+0

非常感谢你。 – gvlasov