neovim / pynvim

Python client and plugin host for Nvim
http://pynvim.readthedocs.io/en/latest/
Apache License 2.0
1.47k stars 118 forks source link

`<abuf>` is wrong for `BufUnload` with hidden buffer #549

Open laomaiweng opened 8 months ago

laomaiweng commented 8 months ago
    @pynvim.command('Scratch')
    def cmd_scratch(self):
        buffer = self.nvim.api.create_buf(False, True)
        win = self.nvim.api.open_win(buffer, True, {'width':60,'height':5,'style':'minimal','relative':'editor','row':0,'col':0})
        self.nvim.out_write(f'Scratch {buffer=} {win=}\n')

    @pynvim.autocmd('BufUnload', eval='+expand("<abuf>")', sync=True)
    def on_bufunload(self, buffer):
        self.nvim.out_write(f'BufUnload {buffer=} {self.nvim.current.buffer.number=}\n')

When I :bdelete the scratch buffer, the BufUnload event fires and the callback receives the number of the newly focused buffer (i.e. the same as nvim.current.buffer, not the scratch buffer) in its buffer argument, from the <abuf> expansion. IIUC, the BufUnload docs says <abuf> should hold the unloading buffer number (here, the scratch buffer). Am I doing something wrong or is that a bug?

(This looks a lot like neovim/node-client#58.)

wookayin commented 8 months ago

Looks like a bug. So in the first invocation a wrong buf number is passed, but in the consequent invocations it works correctly.

So the autocmd defined by the rplugin is:

BufUnload * call remote#define#request(4, "/path/to/rplugin/python3/myplugin:autocmd:BufUnload:*", eval("+expand(\
"<abuf>\")"))

Here a rpcrequest call should block until a response is received, and note that the evaluation of expand("<abuf>") is done on the neovim client side (in the vimscript that calls the autocmd).

But in the first invocation when it is yet to be bootstrapped:

BufUnload *         call remote#define#AutocmdBootstrap("python3", "/path/to/rplugin/python3/myplugin:autocmd:BufUnload:*"
, v:true, "BufUnload", {'group': 'RPC_DEFINE_AUTOCMD_GROUP_2', 'pattern': '*', 'eval': '+expand("<abuf>")'}, "\"doau RPC_DEFINE_AUTOCMD_GROUP_2 BufUnload \".fnameesc
ape(expand(\"<amatch>\"))")

It looks like by the time the actual RPC request is made, the buffer is already gone and hence wrong buffer number is passed. I think this is a bug of neovim core (rplugin provider) rather than pynvim --- probably why node-client also suffers the same error.

wookayin commented 8 months ago

https://github.com/neovim/neovim/blob/master/runtime/autoload/remote/define.vim#L114

eval(a:forward)

this executes doau RPC_DEFINE_AUTOCMD_GROUP_2 BufUnload (i.e. no <amatch>, <abuf>) -- <amatch>, <abuf> cannot be expanded correctly due to a different (autocmd) execution context (i.e. during doautocmd BufUnload).