0

Autocommands support the ++once modifier. I am trying to achieve the same effect for a map.

Instead of coming up with a general solution I have been trying to solve my particular case via a side-effect – I thought it would be easier...

In this case it's a buffer-local map. The map, in window A, closes window B. To remove the map once it has executed, I have a BufLeave autocmd in window B to remove the map from window A. However I cannot get the autocmd to find the map.

Here's how I set things up in window A:

nnoremap <buffer> <Esc> :<C-U>close_other_window()<CR>
let bufnr = bufnr()
execute "autocmd BufLeave <buffer=".bufnr_of_other_window."> nunmap <buffer=".bufnr."> <Esc>"

The problem is the nunmap cannot find the map. There's no error but the map remains in place. If I use the following instead, it still cannot find the map (perhaps because <buffer> is window B's buffer when the autocmd executes):

execute "autocmd BufLeave <buffer=".bufnr_of_other_window."> nunmap <buffer> <Esc>"

Any tips for this situation or the general case would be appeciated!

7
  • 3
    That kind of sound like a xy problem no? What are you trying to do which requires you to delete some mappings like this? Anyway what about getting rid of the autocmd and letting the mapping delete itself? Maybe you could update close_other_window() so that it closes the window and delete the mapping: This way you wouldn't have to worry if the mapping is local to another buffer since you will run the command from the same buffer the mapping is defined for.
    – statox
    Jun 2, 2021 at 12:05
  • I agree with everything statox says. If you still decide you want to use something like your current approach, though, please include close_other_window() as it may have relevance.
    – B Layer
    Jun 2, 2021 at 12:20
  • Re xy: I addressed that in my second paragraph. I'm now trying the general solution: nnoremap <buffer> <Esc> :blah<Bar>nunmap <buffer> <Esc><CR> but without success. Jun 2, 2021 at 13:08
  • 3
    I still think it would be worth it to explain why you want to delete a mapping this way that's what I meant when I talked about the xy problem. Now for the command you gave in you last comment: I believe that if your replace <Esc> with e.g. a the mapping would work. The issue is that your string <Esc> is probably interpreted as an escape character and not the literal string <Esc> (check the output of :map <esc> to be sure). To fix that you'll probably have to mess with escaping, maybe using execute with simple quotes to run the nnoremap command would help but I'm not sure.
    – statox
    Jun 2, 2021 at 15:02
  • You probably really don't want to map escape. For example, vi.stackexchange.com/q/11144/10604, and its linked/related questions on the right sidebar.
    – D. Ben Knoble
    Jun 2, 2021 at 19:29

1 Answer 1

1

Following @statox's comment I found this solution:

nnoremap <buffer> <Esc> :blah<Bar>execute "nunmap <buffer> \e"<CR>

(The \e for <Esc> is in the docs for expr-string.)

2
  • You shouldn't need :execute for the second part. Simply ...<Bar>nunmap <buffer> <Esc> should do. Or does it not work, for some reason? Ah, I think you might need an extra escape here, so ...<Bar>nunmap <lt>buffer> <lt>Esc>... Yeah, looks ugly. Better yet would be to put both the :blah and the :nunmap in a function, then you don't need to deal with escaping.
    – filbranden
    Jun 2, 2021 at 21:04
  • I already tried all that before posting the question. Did you? I agree about using a function; I'm curious to get it working inline. Jun 3, 2021 at 7:56

Your Answer

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

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