1

I want a movement to jump to the end of a block of code. I wrote a function and I'm trying to onoremap it, but it doesn't work. Here is what I do:

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

If I do simply:

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

then the function works as intended. But I need it more as a movement for other commands. So what am I doing wrong?

Here is the function itself (I don't think that the problem is in the function, but anyway):

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'optionは、渡そうとする式ではなく関数名を取り、この関数に1つの文字列引数を渡します。

最初に、通常モードで使用するのとまったく同じオペレーター保留モードのマッピングを作成する必要があります。これが機能しない場合は、<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 に答える