WThreeMTabs

In the WThreeM webbrowser one can have multiple buffers open at the same time, just like in any other modern, decent browser. By default all the available buffers are shows as tabs at the top edge of the w3m window. All of the basic functionality is explained in the InfoMode manual for WThreeM at node (emacs-w3m) Working with buffers, but summarized here too.

Navigating the buffers

So… you can click on the tab to switch to that buffer or use w3m-next-buffer and w3m-previous-buffer (C-c C-n and C-c C-p by default) to hop among them.

There’s also w3m-switch-buffer (C-c C-a) that provides a convenient interactive way to switch from the minibuffer with the common M-n and M-p keys. One more alternative is shipped with w3m, namely the w3m-select-buffer at C-c C-s. This will open a temporary buffer on the righthand side of the frame listing all open w3m buffers. Move among these as instructed in the EchoArea.

Zajcev Evgeny wrote Lisp:wl-list.el to browse active w3m buffers, not unlike w3m-select-buffer.

Here’s yet another function for buffer-switching, and its installation:

 (defun my-w3m-switch-to-buffer (arg)
   "Select the ARG'th w3m buffer."
   (interactive "p")
   (let (buf)
     (if (= arg 0)
	 (setq arg 10)
       (setq arg (1- arg)))
     (if (and (> arg -1) (setq buf (nth arg (w3m-list-buffers))))
	 (progn
	   (switch-to-buffer buf)
	   (run-hooks 'w3m-select-buffer-hook)
	   (w3m-select-buffer-update))
       (message "No such buffer!"))))
 (add-hook 'w3m-mode-hook
	   (lambda ()
	     (dolist (bufnum '(0 1 2 3 4 5 6 7 8 9))
	       (let* ((bufstr (number-to-string bufnum))
		      (funcname (concat "my-w3m-switch-to-buffer-" bufstr)))
		 (eval `(defun ,(intern funcname) ()
			  (interactive)
			  (my-w3m-switch-to-buffer ,bufnum)))
		 (define-key w3m-mode-map bufstr
		   (intern funcname))))))

A more generic Emacs buffer switching tool, BufferQuickSwitcher, could be used with w3m context too.

I find that customizing w3m to give its buffers more sensible names than “w3m” and “w3m<many>” makes it interact much better with things like InteractivelyDoThings and IbufferMode that help manage lots of buffers:

 (defun my-w3m-rename-buffer (url)
   "more useful buffer names, thanks to forcer on freenode."
   (rename-buffer url t))
 (add-hook 'w3m-display-hook 'my-w3m-rename-buffer)

This just uses the url as buffer name. Disadvantage is that it puts a lot of stuff on the modeline (the url as buffer name as well as the title which w3m puts there by default) but now I can switch between w3m buffers by typing C-x b followed by a small part of the url (thanks to InteractivelyDoThings) or get a somewhat readable list of open w3m buffers by using ibuffer limited to the w3m-mode major mode. I like that better than learning a w3m-specific way of switching buffers. YMMV, of course.

I guess it might be even better to use the page title as buffer name (and convince w3m to not add the title to the mode line too).

A modification to the function above achieves that:

    (defun my-w3m-rename-buffer (url)
      "base buffer name on title"
      (let* ((size 32)
             (title w3m-current-title)
             (name (truncate-string-to-width 
                    (replace-regexp-in-string " " "_" title)
                    size)))
        (rename-buffer name t)))

Now we prevent w3m from adding its (truncated) title to the modeline:

    (defadvice w3m-modeline-title (around my-w3m-modeline-title)
      "prevent original function from running; cleanup remnants"
      (setq w3m-modeline-separator ""
            w3m-modeline-title-string ""))
    (ad-activate 'w3m-modeline-title)
    

Alternatively, you can just use this functionality built right into w3m… (setq w3m-use-title-buffer-name t)

This was mentioned on my blog, but there are no references to it in the source of Emacs-W3M 0.5.2, and it doesn’t work for me. – ieure

Spawning and slaying buffers

New buffers are generated in a number of ways. Either one can use the w3m-goto-url-new-session at G and give an URI to visit at the prompt, follow a link with w3m-view-this-url-new-session with S-RET or explicitly make a copy of the current buffer with w3m-copy-buffer at C-c C-t. Because this is a copy of an existing buffer, it takes extra time to render the page if one merely wishes to have a brand new buffer. Here’s a tiny-weeny function to create a new, empty buffer.

 (defun w3m-new-buffer nil
   "Opens a new, empty w3m buffer."
   "As opposed to `w3m-copy-buffer', which opens a non-empty buffer.
 This ought to be snappier, as the old buffer needs not to be rendered.
 To be quite honest, this new function doesn't open a buffer completely
 empty, but visits the about: pseudo-URI that is going to have to
 suffice for now."
   (interactive)
   (w3m-goto-url-new-session "about://"))

To close a buffer, one invokes w3m-delete-buffer with C-c C-w.

Discussion

Tabs is not the way I feel and look. They uses my screen space for nothing :). w3m-switch-buffer is surely needs enhancement.
As a long time Emacs user, I can appreciate that not everyone works the same way. I just wanted to state (other than the facts of how w3m.el works above) that I really like the way the tabs work. It only cost me one extra line of my display and gives me a pretty good visual cue for both how many w3m buffers I have open and what’s in them. I don’t mind sacrificing a line for that. Of course, my main emacs window is 59 lines tall.

See Also: WThreeM, CategoryHypermedia