(or emacs irrelevant)

Emacs Web Wowser (EWW) got ace-link

Emacs goodness incoming

I've discovered a nice Emacs-related blog - Content AND Presentation. Unlike The Axis of Eval, the blog that I mentioned yesterday, this one is pretty self-contained, i.e. it doesn't link to many external information sources. So I thought that it's perfect for trying EWW to read it.

Not so fast! Configure first.

For modes that don't require to self-insert (and even for some that do), I like to navigate with h/j/k/l as arrows. These arrows are on the home row, so navigation becomes a pleasant and relaxed experience. But for EWW I decided to add a little twist: if the point is in the first column, j/k will move down/up not by one line, but by one paragraph. This is great for concentration: I navigate to a paragraph, read it, navigate to the next one. The point shows me the paragraph that I'm reading, everything before the point I've already read. So every time I press j, I get a tiny warm feeling of accomplishment. I can also pair this with v, which I bind to recenter the current line to the top.

So here's what my key setup currently looks like:

(defun oleh-eww-hook ()
  (define-key eww-mode-map "j" 'oww-down)
  (define-key eww-mode-map "k" 'oww-up)
  (define-key eww-mode-map "l" 'forward-char)
  (define-key eww-mode-map "L" 'eww-back-url)
  (define-key eww-mode-map "h" 'backward-char)
  (define-key eww-mode-map "v" 'recenter-top-bottom)
  (define-key eww-mode-map "V" 'eww-view-source)
  (define-key eww-mode-map "m" 'eww-follow-link)
  (define-key eww-mode-map "a" 'move-beginning-of-line)
  (define-key eww-mode-map "e" 'move-end-of-line)
  (define-key eww-mode-map "o" 'ace-link-eww)
  (define-key eww-mode-map "y" 'eww))
(add-hook 'eww-mode-hook 'oleh-eww-hook)

As you see, I was careful to re-assign eww-back-url and eww-view-source - the commands that I've displaced from l and v. And here's the implementation of the arrows:

(defun oww-down (arg)
  (interactive "p")
  (if (bolp)
      (progn
        (forward-paragraph arg)
        (forward-line 1))
    (line-move arg)))

(defun oww-up (arg)
  (interactive "p")
  (if (bolp)
      (progn
        (forward-line -1)
        (backward-paragraph arg)
        (forward-line 1))
    (line-move (- arg))))

Cherry on the top

And while I was at it, I've added ace-link support for EWW. It was pretty easy, basically the same routine as for help-mode and info-mode. The only hard part was to figure out what part of the code keeps binding shr-save-contents to o, my preferred binding for ace-link. Turns out it was eww-link-keymap, and not shr-map. So here's the new key binding code:

(defun ace-link-setup-default ()
  "Setup the defualt shortcuts."
  (eval-after-load "info"
    '(define-key Info-mode-map "o" 'ace-link-info))
  (eval-after-load "help-mode"
    '(define-key help-mode-map "o" 'ace-link-help))
  (eval-after-load "eww"
    '(progn
      (define-key eww-link-keymap "o" 'ace-link-eww)
      (define-key eww-mode-map "o" 'ace-link-eww))))

If you haven't tried ace-link before, you can get it from MELPA. The minimal configuration that you need is this:

(ace-link-setup-default)

Here's the setup that I'm actually using:

(use-package ace-link
    :load-path "~/git/ace-link"
    :init (ace-link-setup-default))

I'm using it from my git folder since when I want to edit a project, I like to use smex's jump-to-definition.

And use-package is useful for the cases when my ~/git/ happens not to contain ace-link. In that case, instead of getting a debugger error on starting Emacs, I get only a polite "Could not load package ace-link" in my *Messages* buffer.