Windows – Firefox — How to open a link (to any text-based file) in Vim


Rather often, I see web pages with links to files that I want to open directly in gVim (when browsing with Firefox on Windows). Chrome-specific answer — also good to have.

Attempting to get this working, I was messing around with Firefox's Tools > Options > Applications settings (where it chooses what to do based on MIME type). To no avail. For most of these files (e.g. Python source files), clicking on them brings up the "Opening" dialog with the options "Open with", "Save file", and other options. Against "Open With" I can select from a dropdown "Other…" and I get the "Choose Helper Application" dialog. Now, "Vi Improved – A Text Editor" does appear in that list for me, but the problem is that choosing it opens up vim.exe in a shell window, while I want to see gVim.exe. In the "Choose Helper Application", I can select "Browse…" and navigate to Vim's directory, choose "gvim.exe", and then it works. But for the next file, it doesn't remember this setting, and I have to do it all again.

How can I make it stick there, or use another way to easily open files in gVim?

From reading Firefox bug reports, I figured that the "Choose Helper Application" dialog is populated based on the given file's MIME type, and, unless the user changed some settings, this is taken from the Windows Registry. But I want to be able to open any file with gVim, so it's not a good solution for me to set the default in Windows for every extension I possibly want to open.

Best Answer

First of all, Firefox bases the settings in "Choose Helper Application" on system settings, so there's no simple way to configure that.

An even better solution, usability-wise, is to use the Firefox extension called "Open With"

It says it's for web browsers, but it turns out it could be any program — it just calls he program with the URL as the first argument.

Next, I wrote a Python script:

import sys, os, re, tempfile, urllib, urlparse, time

handler, url = sys.argv[1:3]
match = re.match(r".*(\.[A-Za-z_]+)$", urlparse.urlparse(url).path)
tmpfile, tmpfile_path = tempfile.mkstemp( if match else '')
print "Downloading to temp file ..."
urllib.urlretrieve(url, tmpfile_path)
#Normally it would try to clean up the file we urlretrieved after this Python
#process ends. Thank BDFL there are no access restrictions on private variables.
urllib._urlopener._URLopener__tempfiles = []

os.execlp(handler, handler, '%s' % tmpfile_path)

#We don't attempt to delete the temporary file because:
# 1. Firefox also doesn't in such cases.
# 2. It's problematic in some instances, such as when the subprocess (this
#     script used to call the handler in a subprocess) finds another copy
#     of itself running, hands the file over to it and exits. Meanwhile, we
#     would be over here deleting the file while the subprocess'es brother
#     hadn't tried to open it yet.

What it does:

  1. Makes a unique filename in the user's Temp directory (same place where Firefox stores files in such cases).

  2. Makes sure that the extension of the temp file will be sane, even with a URL including query strings and hash-anchors (urlretrieve(..) without a second argument handles the former, but not the latter). This is useful, because it tells Vim how to syntax-highlight the file.

  3. Downloads the file from the URL to the current user's Temp directory.

  4. Opens the file with gvim.exe (or an editor of your choice — see below).

How to use this solution:

  1. Save the above Python script as somewhere where you keep such scripts.

  2. Install the Open With Firefox extension at the above link and restart Firefox.

  3. Go to Tools > Add-ons > Extensions > Open With > Options. There:

    (a). (Unless you plan to use Open With for its intended purpose, "Hide" all the browsers in the list.)

    (b). "Add..." python.exe.

    (c). Set its "Arguments..." to the path of the script followed by the editor's executable filename or path. For me, this would be
    C:\E\infrastructure\ gvim.exe

    (d). "Rename..." it to "gVim".

  4. Make sure that gvim.exe is in the PATH variable. I recommend the EditPATH Autohotkey script, which is compilable to an EXE using AHK tools (place it into the Quick Launch folder for convenience — editing PATH becomes three clicks, rather than having to go through the Control Panel memory test yet again.) Otherwise, you must supply the whole path of gvim.exe in step 3(c).

  5. That's it. Now find a link to a file in Firefox, right-click it, and choose "Open Link with gVim".

Screenshot of context menu

(Guess how I got the correct icon there :)

Bonus: if you set the relevant setting in the Open With extension's Options, you can right-click on a Firefox tab and open (most) web pages in Vim too — i.e. like "View Source" except using Vim.

Note that this solution applies just as well to Emacs, Notepad++, and many other software not restricted to text editors. For example, I just tried it with The GIMP, and it opened a PNG file. (To do that, replace gvim.exe above with the path to GIMP. Note: to open an arbitrary image this way, not just a link, you could View Image, and then right-click on its tab.)

Historical note: initially I went for writing a BAT script, but that became untenable after it failed on this test case:
That's because cmd.exe has problems with arguments containing the = character. Furthermore, it was not just a matter of calling gvim.exe with the URL as the command-line argument (though Vim does accept URLs), because it cannot handle this test case — just opens a blank instance of Vim. And for parsing the URL, I'd have to resort to Powershell, which restricts the portability of the solution somewhat. In the end I decided that having an installation of Python as a prerequisite isn't too much to ask.