3

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

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> :
  • 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). – Josh Aug 27 '15 at 17:24
  • What did you put in that file? – romainl Aug 27 '15 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). – Josh Aug 27 '15 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 '15 at 20:16
  • What exactly are you trying to do with execute "nnoremap <buffer> o " . maparg("<CR>", "n")? – romainl Aug 27 '15 at 20:25
2

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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