6

Let's say I'm a terrible person and I'm thinking about remapping <CR> to do what : normally does (start command-line mode).

Vim's built-in netrw plugin also remaps <CR> to open the selected directory or file. Specifically, it appears to map it to

:call netrw#LocalBrowseCheck(<SID>NetrwBrowseChgDir(1, <SID>NetrwGetWord()))`)<CR>

The use of <SID> makes it impractical for me to simply reproduce this map in my .vimrc, which I would like to do, because I would like to

autocmd FileType netrw nnoremap <buffer> <CR> :

in order to access command-line mode consistently. What might be an effective way to move netrw's default <CR> functionality to another keystroke so I can still open files with it?

My experiments thus far have led to my trying to use maparg to do something like

function! s:ConfigureNetrw()
  execute "nnoremap <buffer> o " . maparg("<CR>", "n")
  nnoremap <buffer> <CR> :
endfunction

augroup configure_netrw
  autocmd!
  autocmd FileType netrw call s:ConfigureNetrw()
augroup end

However this seems to result in both <CR> and o doing the same thing when I check the output of nmap (they both get mapped to :). I could understand how this might happen if I used nmap, since the maparg result has a <CR> in it. But it confuses me how it doesn't seem to matter if I use nmap or nnoremap; the same thing happens.

EDIT: After a lot of frustrated poking around I have narrowed my apparent problem to this:

let g:prior = maparg("<CR>", "n")
nmap <buffer> <CR> -

I put this in ~/.vim/after/ftplugin/netrw.vim. I would expect that getting into a Netrw buffer and doing :echo g:prior would print the LocalBrowseCheck text that netrw maps <CR> to. Instead it prints -.

This happens if I put the same two lines in a function called from an autocmd, as I was originally doing. It happens if use nnoremap instead of nmap. It does not happen if I change the filename or autocmd so it associates with a different filetype (say, text); in that it prints what <CR> is originally bound to (:). I am now completely confused.

3 Answers 3

6

Netrw's documentation recommends putting your custom mappings in:

~/.vim/after/ftplugin/netrw.vim                    on unix-like systems
%userprofile%\vimfiles\after\ftplugin\netrw.vim    on Windows

You will need to use nmap because you are remapping existing mappings (that's what is blocking you), and <buffer> to restrict your mappings to netrw buffers:

nmap <buffer> <CR> :
8
  • Moving the remappings into "after" and using nmap instead of nnoremap doesn't seem to change the apparent behavior I'm seeing, which is that <CR> and : end up mapped to exactly the same thing (verbose nmap says they were both last set in the after/ftplugin/netrw.vim file).
    – user72
    Aug 27, 2015 at 17:24
  • What did you put in that file?
    – romainl
    Aug 27, 2015 at 19:43
  • Exactly the contents of s:ConfigureNetrw I edited into my question (and eventually exactly those two lines in my latest edit, and described permutations).
    – user72
    Aug 27, 2015 at 20:00
  • I have done exactly what I describe in my answer. The result is that pressing <CR> in netrw starts command-line mode and :verbose map <CR> shows that mapping in that file. I have no idea what else you expect.
    – romainl
    Aug 27, 2015 at 20:16
  • What exactly are you trying to do with execute "nnoremap <buffer> o " . maparg("<CR>", "n")?
    – romainl
    Aug 27, 2015 at 20:25
3

This is what I ended up doing:

function! s:ConfigureNetrw()
  let prior = maparg("<CR>", "n")
  if prior != ":"
    execute "nnoremap <buffer> o " . prior
    nnoremap <buffer> <CR> :
  endif
endfunction

augroup netrw_configuration
  autocmd!
  autocmd FileType netrw call s:ConfigureNetrw()
augroup end

It turns out that for one reason or another (I'm not quite sure yet, as netrw's code is a bit tricky to delve through), the filetype for a netrw buffer is set or reset multiple times, or something, because the code for the filetype autocommand or in an after/ftplugin script executes more than once. You can observe this with a snippet like:

if !exists("g:counter")
  g:counter = 1
else
  g:counter = g:counter + 1
endif

and :echo g:counter after invoking netrw. g:counter will be 3 or 5 (or at least was for me) depending on where that code was.

So the unusual behavior I was seeing where both commands ended up mapped to the same thing was because after the first invocation of the code, maparg() would return the mapping I'd set for <CR> in the prior invocations, stomping over my original mapping.

Netrw will also re-apply buffer local mappings as you navigate the tree, it seems (or perhaps simply reset the filetype, but in any case the mappings are reset), which necessitates the check to see if the mapping for <CR> is what I expect it to be.

0

I had to remap netrw's default <CR> such that I can call a certain function when entering a buffer from netrw. Tweaking and echoing parts of above answers helped me reach a solution eventually.

Note: I might be wrong in my implementation i.e it might have some unseen errors/side-effects, please correct me if you see/face any of them.

This is what I put in ~/.vim/after/ftplugin/netrw.vim

let g:prior = maparg("<CR>", "n")
nmap <buffer> <CR> <Plug>NetrwLocalBrowseCheck:call MyHideousFunc()<CR>

You can replace :call MyHideousFunc()<CR> with any regular vim commands that can be executed in normal mode!

g:prior is the global variable that shows what's mapped for <CR> when netrw buffer is open. In my case, the default value for g:prior was <Plug>NetrwLocalBrowseCheck.

4
  • 1
    Welcome to Vi and Vim! If you use g:prior, it might be worth showing how
    – D. Ben Knoble
    Jun 8, 2021 at 14:24
  • :echo g:prior shows the current <CR> mapping when netrw buffer is open. Default value (atleast in my case was <Plug>NetrwLocalBrowseCheck, so I tweaked it as I show in the answer, and it worked like a charm :)
    – maniac_en
    Jun 8, 2021 at 14:42
  • 1
    One way to future proof that would instead be :execute 'nmap <buffer> <CR>' maparg('<CR>', 'n').':call MyHideousFunc()<CR>'
    – D. Ben Knoble
    Jun 8, 2021 at 14:52
  • pretty neat solution, reducing the lines of code as a vimicist should :)
    – maniac_en
    Jun 8, 2021 at 15:19

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.