1

我想要一个动作跳到代码块的末尾。我写了一个函数,我正在尝试对其进行映射,但它不起作用。这是我所做的:

onoremap <silent> } :set opfunc=MovementToEdgeOfBlock(1)<cr>g@

如果我只是这样做:

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
4

1 回答 1

2

您是否:h 'opfunc'仔细阅读,包括:h g@那里引用的内容?它与您想要实现的目标完全无关。更多,g@从未打算在操作员挂起模式下工作。更重要的是,'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>.

于 2012-10-04T21:08:23.457 回答