Customizing Firefox (without sputtering with rage)

Posted on Wed, 13 Aug 2008 in Technology
Last edited Wed, 13 Aug 2008

If you have ever tried to figure out how to add a custom keybind to Firefox, you know it is a frustrating, infuriating, and futile task. There is no reasonable way to do it. There's a way that seems to have worked six years ago, and requires you to edit the firefox installation instead of your profile. There's extensions that might add the keybinds you want, but they all suck in one way or another. There's an extension that lets you add keybinds with the GUI, but it stores them in your user prefs so there's no way to sync them between machines. You could make your own extension, but then you have to figure out all the stupid boilerplate that extensions require and reinstall it every time you make a change.

All I really want is a text file somewhere I can edit. When I add a binding to emacs, I add a single line to a single text file. The file is in a git repository, so syncing changes is easy. This blissful state of affairs actually can be achieved in firefox; and here's how you do it:

Firefox can load an extension from a path outside the profile directory. So you just create an extension with your personal customizations, and just edit it directly. After you make a change you just restart firefox. There's no need to make a XPI and install it. I keep mine in ~/config/dot-firefox. Aside from the boilerplate, there's just two files.

overlay.js for your javascript:

// from mozless
function tabRelativeSelect(delta)
{
  var oldTab = gBrowser.selectedTab;
  var newTab = null;
  var length = gBrowser.tabContainer.childNodes.length;
  var index;
  for (index=0; index<length; index++) {
    if (gBrowser.tabContainer.childNodes[index] == oldTab) {
      var new_index = index + delta;
      if (new_index < 0) new_index += length;
      else if (new_index >= length) new_index -= length;
      newTab = gBrowser.tabContainer.childNodes[new_index];
      break;
    }
  }
  if (newTab && newTab != oldTab)
    gBrowser.selectedTab = newTab;
}

and overlay.xul for your XUL:

<?xml version="1.0"?>

<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script src="overlay.js"/>
  <keyset id="mainKeyset">
    <key key="k" oncommand="goDoCommand('cmd_scrollLineUp')" />
    <key key="h" oncommand="goDoCommand('cmd_scrollLeft')" />
    <key key="j" oncommand="goDoCommand('cmd_scrollLineDown')" />
    <key key="l" oncommand="goDoCommand('cmd_scrollRight')" />
    <key key="d" oncommand="goDoCommand('cmd_scrollPageDown')" />
    <key key="u" oncommand="goDoCommand('cmd_scrollPageUp')" />
    <key modifiers="shift" key="B" oncommand="BrowserBack()" />
    <key modifiers="shift" key="F" oncommand="BrowserForward()" />
    <key key="." oncommand="tabRelativeSelect(1)" />
    <key key="," oncommand="tabRelativeSelect(-1)" />
  </keyset>
</overlay>

To get firefox to load it:

$ echo ~/config/dot-firefox > $firefox_profile_dir/extensions/dot-firefox@elder-gods.org

If you wanna see/copy the boilerplate, it's all in this git repo.

Trackback pings for this entry are listed below. The URL to ping for this entry is: http://elder-gods.org/~larry/blog/trackback/104
(let ((x (quote (quasiquote (let ((x (quote (unquote x)))) (unquote x))))))
  (quasiquote (let ((x (quote (unquote x)))) (unquote x))))