1

I want to be able to hit a single key to see the netrw buffer for the directory of the file I'm in. Rex will handily move your cursor to where it was previously, but only works if you opened the file from netrw, and breaks when you reopen a session.

fu! OpenExplorer()
    try
        silent! :Rex
    catch
        :Ex
    endtry
endfu

nno - :call OpenExplorer()<CR>

I thought I could do this with a try catch, but this code still opens a minibuffer saying **warning** (netrw) win#1 not a former netrw window

I could write some more elaborate solution or roll my own Rex, but why doesn't this work?

1
  • It seems like :Rexplore doesn’t throw an error of the kind catch can handle, but I may be wrong.
    – D. Ben Knoble
    Feb 24, 2019 at 17:32

3 Answers 3

2

Well, :silent! suppresses errors and neutralizes exceptions. If the netrw code is indeed throwing exceptions (see below) then removing it, or at least dropping the !, should clear things up. (Note: I'm interpreting what you said about that error message you saw as if that occurred in a later/different context than this code with :silent!. Accurate?)

If you need :silent! for some other reason you could check for failure by checking whether the variable v:errmsg is non-empty/non-null. With the code below we will see v:errmsg is bzzzt.

func! DoError()
    echoerr("bzzzt")
endfunc

func! HandleError()
    echom("got it")
endfunc

func! ErrmsgTest()
    try
        let v:errmsg = ""
        silent! :call DoError()
        echom("v:errmsg is " . v:errmsg)
    catch
        call HandleError()
    endtry
endfunc

Update: saw some netrw documentation that says "messages from netrw will use echoerr" so the evidence indicates you can solve your issue by removing :silent! or using v:errmsg.

Update 2: Well, silly me, believing the documentation is accurate. My findings after a deeper dive...

There is a flag g:netrw_use_errorwindow that when set to 0 (as OP has tried) is supposed to result in, per the docs: messages from netrw will use echoerr.

But at the point in the code where the flag comes into play a comment says netrw will show messages using echomsg, completely contradicting the docs. And indeed echomsg is used there not echoerr. On top of that I initially overlooked that the message is a warning and rarely will you find exceptions thrown as a result of a warning condition (at least not in quality code).

So basically there's nothing you can do to directly detect this state.

How about a hack? One that comes to mind is to see if the message in question shows up in the message history. You could do something like

mess clear
Rex
if match(execute("1mess"), "not a former netrw window") >= 0
    Ex  " or whatever you want to do to handle the warn state
endif

Like I said, hack, but it should work if there's nothing else going on in parallel that can add to message history.

As a side note, the key echomsg in the netrw code is preceded by unsilent which explains why you're seeing the warning despite silent. (unsilent nullifes the message suppression caused by any silent command set in the surrounding code.)

6
  • I tried it initially without silent! There's a variable called g:netrw_use_errorwindow, but even if I set it to 0 the catch block doesn't fire. Not really sure why.
    – Wumbo
    Feb 24, 2019 at 21:33
  • Looks like echoerr does not trigger a catch. You have to use the "throw" keyword, which netrw isn't doing. I don't know if there's a way to detect when Rexplore has failed and try Explore instead.
    – Wumbo
    Feb 24, 2019 at 21:39
  • In my answer I show code that is using echoerr but no throw yet will end up in catch (when silent! is removed). The rule is echoerr has to be called from within a try.
    – B Layer
    Feb 24, 2019 at 22:06
  • The documentation is lying apparently. I'm looking at g:netrw_use_errorwindow. The doc says "messages from netrw will use echoerr" but the code does not match. There a comment says "netrw will show messages using echomsg" and indeed there are no echoerr calls in the vicinity...nor anything else that you could catch/check to directly detect this state.
    – B Layer
    Feb 24, 2019 at 22:38
  • This is pretty weak code. Short of monitoring message history for this particular warning there's nothing you can do to detect this ... except maybe some other hacks. I'll update my answer with this info in a bit.
    – B Layer
    Feb 24, 2019 at 22:44
0

Since try catch doesn't work, I just used this workaround instead.

fu! OpenExplorer()
    let g:netrw_use_errorwindow = 0
    Rex
    if &ft != 'netrw'
        Ex
    endif
endfu

It's a little ugly that it changes the error window variable, but I kinda find that way of showing the user an error message lame anyway, so I don't mind ensuring it is set. If you didn't want that, you could run quit after the netrw ft check to close the error window instead.

0

This is what worked for me, make sure the read the source file of netrw.vim to understand what happens when calling Rexplore and how that error is displayed. While I couldn't answer your question, there is a way to avoid causing Rexplore to issue that warning.

function ToggleExplorer()
    if &ft == "netrw"
        if exists("w:netrw_rexlocal")
            Rexplore
        else
            if exists("w:netrw_rexfile")
                exec 'e ' . w:netrw_rexfile
            endif
        endif
    else
        Explore
    endif
endfun

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.