Enhancing Gmail browsing

I use pretty often emacs-w3m to read technical HTML docs within Emacs. When you’re programming, reading manuals, blogs or tutorials without leaving your operating system editor is all but convenient.

Browsing EmacsWikiActually, emacs-w3m does a very, very good job rendering even moderately complex sites, and i’ve been known to use it as my default browser. It is not limited to plain text (Emacs groks images these days), has tabs (shameless plug: take a look at my w3m-session package to add session management) and renders tables and other HTML constructs nicely. And of course, navigating sites like the Emacs wiki without leaving Emacs is just the way to go. Besides, if you don’t like how a page looks in emacs-w3m, opening it in your graphical browser is just a keystroke away (C-h w w3m-view-url-with-external-browser to discover it).

Gmail's login pageI also have usually open a tab with my Gmail account, to quickly check my email every now and then. As you can see in the screenshot on the right, emacs-w3m renders Gmail pages very decently (hint: you’ll need to activate cookies to use Gmail, by setting the variable w3m-use-cookies to a non-nil value). But of course the Gmail page i visit more frequently is the Spam tab, and the operation i want to perform more frequently in there is to mark all the mails and press ‘Delete Forever’. But alas, w3m does not support javascript, and the handy ‘Select All’ link is missing. Obviously, tabbing your way to every single spam mail to select it would be a pain, and one is tempted to follow the advice at the top of the page about a better Gmail experience.

GmailBut wait, this is not your regular browser. We’re inside Emacs, and in here, when we need something, we usually just hack it and keep on working. After all, what we need to do is quite simple: look for occurrences of ‘[ ]’ in the buffer, click them, and leave the pointer over the ‘Delete forever’ button, ready to send all our spam where it deserves. As it happens, our life is even easier thanks to the functions provided by emacs-w3m. w3m-form-goto-next-field allows easy navigation inside a form, and w3m-view-this-url will perform a click for us. So here we go: let’s write an Elisp command that looks for unmarked checkboxes and clicks them:

  (defun jao-w3m-gmail-mark-all ()
    (interactive)
    (beginning-of-buffer)
    (when (search-forward "[ ]" nil t)
      (backward-char 4)
      (w3m-form-goto-next-field)
      (while (looking-at " \\\\]")
        (w3m-view-this-url)
        (w3m-form-goto-next-field))))

That’s it. After evaluating this definition, we just M-x jao-w3m-gmail-mark-all to mark all our mails. Of course, a keyboard shortcut will come in handy:

  (define-key w3m-mode-map (kbd "C-ck") 'jao-w3m-gmail-mark-all)

and now we only need to press C-ck to get the job done. While we’re at it, it would be nice if typing a prefix would unmark mails instead of marking it, wouldn’t it? Well, that only needs a few tweaks in our original definition:

  (defun jao-w3m-gmail-mark-all (unmark)
    (interactive "P")
    (beginning-of-buffer)
    (when (search-forward (if unmark "[*]" "[ ]") nil t)
      (backward-char 4)
      (w3m-form-goto-next-field)
      (while (looking-at (if unmark "\\\\*\\\\]" " \\\\]"))
        (w3m-view-this-url)
        (w3m-form-goto-next-field))))

Now, C-ck will mark, and C-uC-ck will unmark.

As you can see, the limit is just your imagination. For instance, when i’m reading non-spam, i usually mark some mails for deletion. Then i need to go to the ‘More actions…’ menu, select the ‘Delete’ operation and press ‘Go’. Hmm, a bit of a chore. Elisp to the rescue:

  (defun jao-w3m-gmail-delete ()
    (interactive)
    (beginning-of-buffer)
    (when (search-forward "[More Actions" nil t)
      (w3m-view-this-url)
      (search-forward "Trash")
      (beginning-of-line)
      (w3m-form-input-select-set)
      (w3m-form-goto-next-field)))

Admittedly, these little extensions are far from earth-shattering, but i think that they illustrate quite well what having an extensible system means. You control your environment and adapt it to your particular needs, often building upon functionality provided either by the system or by some other extension library. Another nice example of extensibility at work is my w3m-session package: i wanted persistent sessions, so i wrote an extension. And it was easy, thanks to the nice work of the emacs-w3m hackers and, let’s not forget, the dynamic nature of Elisp.

In addition, the programmer in me finds tweaks like this a continuous source of fun. You know, that fuzzy warm feeling… but i digress. Happy hacking!

Advertisements

Define your own keywords

These days i’m programming in and learning about Objective-C and Cocoa. Yesterday, i stumbled upon a blog entry providing The Cocoa Memory Management Regular Expression, that is, a simple regular expression that matchs (most of) the OpenStep functions allocating memory that must be explicitly de-allocated. Here’s the regexp in question:

^retain$|^(alloc|new)|[cC]opy

An immediate application of this regexp is, of course, providing some sort of visual warning to remind you that memory allocation is at play. In Emacs, a way to do that is to fontify the keywords in question using an special face (font-lock-warning-face, for instance). As it happens, this is very easy to do: just call font-lock-add-keywords with the appropriate parameters:

(font-lock-add-keywords 'objc-mode
   '(("\\\\<retain\\\\>" 0 font-lock-warning-face)
     ("\\\\(\\\\<\\\\(alloc\\\\|new\\)\\\\w*\\\\)[]:]" 1 font-lock-warning-face)
     ("\\\\(\\\\w*[cC]opy\\\\w*\\\\)[]:]" 1 font-lock-warning-face)))

Each entry in the association list above consists of a regular expression, the group inside it to be hightlighted (0 means the whole match) and the face used for the highlighting. C-h f font-lock-add-keywords RET for extended help, including further examples (for instance, to highlight your to-dos).