0

I'm writing a script in which I am in need of closure functionalities. Take this function, for instance:

func! SetOpNorm(norm_comm, motion_key = 'y')
    let l:norm_comm = a:norm_comm
    let l:motion_key = a:motion_key
    let s:OpFun = { type, ... ->
        \ let l:NormFun = { sel ->
            \ sil exe 'normal!' l:norm_comm
            \ sil exe "normal! \<del>"
        \ }
        \ call function('s:MapOverOp', [l:NormFun, l:motion_key, a:type] + a:000)() }
    set opfunc=s:OpFun
endfunc

The script would work except for the fact that vimscript closures accept an expr1 as their bodies and not a list of commands. Is there a way to work around this limitation?

I also tried using local functions to achieve the same result:

func! SetOpNorm(norm_comm, motion_key = 'y')
    let l:norm_comm = a:norm_comm
    let l:motion_key = a:motion_key
    func! OpFun(type, ...)
        func! NormFun(sel)
            sil exe 'normal!' l:norm_comm
            sil exe "normal! \<del>"
        endfunc
        call function('s:MapOverOp', [function('NormFun'), l:motion_key, a:type] + a:000)()
    endfunc
    set opfunc=OpFun
endfunc

But after some testing I think that this doesn't work as the inner local functions do not capture their sorrounding context.

4
  • 1
    Don't you need closure following the args of the inner function, per :h func-closure ??
    – B Layer
    Commented Apr 8, 2021 at 9:08
  • If you mean closure as in a keyword I don't think so... I'm using neovim btw, mybe some things are different from regular vim
    – Dincio
    Commented Apr 8, 2021 at 9:10
  • Nevermid... I just read :h func-closure and it looks like exactly what I need. Didn't bother to look before because I had already read :h closure. The naming might be a bit ambigous XD
    – Dincio
    Commented Apr 8, 2021 at 9:12
  • I agree that it's not helpful having the information split across two sections although, to be fair, :func-closure is linked in closure (but the reverse isn't true).
    – B Layer
    Commented Apr 8, 2021 at 9:41

1 Answer 1

1

See :h func-closure to declare inner function as closure.

For an example of g@ implementation using closures you can look into my plugin source code: vim-opera.

1
  • Thanks this solved the problem (and also my bigger problem of reinventing the plugin you're mentioning).
    – Dincio
    Commented Apr 8, 2021 at 9:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.