10

M-x eww prompts for url or keywords and opens a new *eww* buffer. In eww-mode, G is bound to eww, which replaces the content of the single eww buffer.

To make multiple buffers for different webpages, I've resorted to creating a new buffer, setting eww-mode manually, then pressing G (or M-x eww) to visit a URL.

I can easily write a function that does all this for me, but I'm surprised this functionality isn't just built-in. Am I just missing it?

  • Emacs 27 now adds support for calling eww with a prefix argument; see my answer below. – Basil Mar 22 at 12:22
6

You are correct that eww does not automatically create new buffers for you. But I have been using this trick from ergoemacs.org and it works great!

With the below eval'ed, each time you do M-x eww from a non-eww buffer, a unique eww buffer will be created.

;; Auto-rename new eww buffers
(defun xah-rename-eww-hook ()
  "Rename eww browser's buffer so sites open in new page."
  (rename-buffer "eww" t))
(add-hook 'eww-mode-hook #'xah-rename-eww-hook)

If you'd like to spawn a new eww buffer while being in an eww buffer, eval the below advice (you will still need to eval the above so that new eww buffers are assigned unique names).

;; C-u M-x eww will force a new eww buffer
(defun modi/force-new-eww-buffer (orig-fun &rest args)
  "When prefix argument is used, a new eww buffer will be created,
regardless of whether the current buffer is in `eww-mode'."
  (if current-prefix-arg
      (with-temp-buffer
        (apply orig-fun args))
    (apply orig-fun args)))  
(advice-add 'eww :around #'modi/force-new-eww-buffer)
  • This doesn't seem to work for me in Emacs 25 (I'm building from master). I did get a partial fix using rename-uniquely, though, which is effective if I activate eww from a non-eww buffer. If I'm in an eww buffer, however, the hook doesn't fire, because the mode isn't changing. At least I think that's whats happening. – R. P. Dillon Jul 8 '16 at 21:49
  • You're right. What I posted works exactly as intended only if you do M-x eww from a non-eww buffer. It was not clear if you were intending to have a new eww buffer spawn while in an eww buffer. I'll update the solution if I come up with something. I am also on the latest build of master. – Kaushal Modi Jul 8 '16 at 22:01
  • This behavior is in the design of the eww function as seen in the source code: (pop-to-buffer-same-window (if (eq major-mode 'eww-mode) (current-buffer) (get-buffer-create "*eww*"))). – Kaushal Modi Jul 8 '16 at 22:04
  • @R.P.Dillon See the the update with the advice works for you. – Kaushal Modi Jul 8 '16 at 22:17
  • Thanks for the update! The approach using advice doesn't seem to fire, actually. I'm thinking a simpler approach using a function might suit me best. – R. P. Dillon Jul 8 '16 at 22:25
3

It seems eww is designed to avoid this behavior. This function, eww-new, can be called when a new eww buffer is desired:

(defun eww-new ()
  (interactive)
  (let ((url (read-from-minibuffer "Enter URL or keywords: ")))
    (switch-to-buffer (generate-new-buffer "eww"))
    (eww-mode)
    (eww url)))
2

Update

This behaviour was discussed in bug#34374 and merged on 2019-02-15.

So in Emacs 27, calling eww with a prefix argument tells it to use a new buffer instead of reusing the default *eww* buffer.


I'm surprised this functionality isn't just built-in. Am I just missing it?

Yes and no. Similar functionality was added in Emacs 26 as the command eww-open-in-new-buffer, which is bound to M-RET in EWW buffers by default:

eww-open-in-new-buffer is an interactive compiled Lisp function in
‘eww.el’.

It is bound to M-RET, <menu-bar> <Eww> <Follow URL in new buffer>.

(eww-open-in-new-buffer)

Fetch link at point in a new EWW buffer.

The only problem is that, at the time of writing, this command is limited to working only in EWW buffers. In particular, it throws a user-error if no meaningful link is found at point, as determined by the user option eww-suggest-uris:

eww-suggest-uris is a variable defined in ‘eww.el’.
Its value is
(eww-links-at-point url-get-url-at-point eww-current-url)

Documentation:
List of functions called to form the list of default URIs for ‘eww’.
Each of the elements is a function returning either a string or a list
of strings.  The results will be joined into a single list with
duplicate entries (if any) removed.

You can customize this variable.

This variable was introduced, or its default value was changed, in
version 25.1 of Emacs.

A further limitation of the command is that it does not prompt the user for a URL or search terms, as the command eww would.

Here's a simple example of how you could bridge these differences between eww and eww-open-in-new-buffer:

(defun my-eww-new-buffer (url)
  "Like `eww', but fetch URL in a new EWW buffer."
  (interactive (advice-eval-interactive-spec (cadr (interactive-form 'eww))))
  (let ((eww-suggest-uris (list (lambda () url))))
    (eww-open-in-new-buffer)))

What this does is first call the interactive spec of eww, which prompts for URLs or search terms as usual. It then calls eww-open-in-new-buffer with the previously input URLs or search terms as the only suggested URI, so that the command does not throw a tantrum.

This command will work both within and without EWW buffers, so it can act as a drop-in replacement for the default eww-open-in-new-buffer, if you prefer:

(with-eval-after-load 'eww
  (define-key eww-mode-map [remap eww-open-in-new-buffer] #'my-eww-new-buffer))

Either way, you can invoke it from anywhere as M-xmy-eww-new-bufferRET or bind it globally to a more convenient key.

0

I extended a bit R. P. Dillon snippet. Which make it good candidate to create alias like (defalias 'w #'af/eww) and open eww using function below. The only difference is conditional check if the *eww* buffer already exists, then new one is created, if not the native eww is invoked.

(defun af/eww ()
  (interactive)
  (let ((eww-current-buffer (get-buffer "*eww*"))
         (url nil))
    (if (eq eww-current-buffer nil)
      (eww)
      (setq url (read-from-minibuffer "Enter URL or keywords: "))
      (switch-to-buffer (generate-new-buffer "eww"))
      (eww-mode)
      (eww url)
    )))
0

I use Emacs 25.1 and eww-open-in-new-buffer function isn't there. So I have to rename the eww buffer I'm in, usually with some easy title about the page I'm in, and calling again eww from any other buffer opened in Emacs (by example from the buffer-mode buffer, or dired buffers, from scratch, another document, any) takes me to another eww buffer. Finally I go with S to the eww buffers list to select from there. Odd but it works, and with few steps. I wonder why eww-new wasn't built-in from start. Of course it is cleaner with the code above, I'll give that a try. I'm glad to see that the function was added in Emacs 26.

  • In Emacs 27, calling eww with a prefix argument now creates a new EWW buffer; see my answer above. – Basil Mar 22 at 12:19
  • If you don't want to invent a new buffer name, go with M-x rename-uniquely. – Stefan Mar 22 at 13:18
  • Thank you Stefan for the tip. I have Debian 9 and I'm so far of Emacs 27 :( – techapu Apr 2 at 10:15
  • Anyway I'll have to update my Emacs, I use the built-in browser all the time. And w3m breaks my flow with the tabs. Eww is practical and it's all I need. This feature is really important, thanks Basil for the update, the custom command you share seems a clever alternative to the standard behavior. I go between the org files, the info buffers, the terminals and the eww browser all the time and it would be nice to have eww at hand without burying the previous page. – techapu Apr 2 at 10:25
  • @Stefan the problem I see with that solution is that I need to know what in the buffer so I'm returning later there . What would be the rename-uniquely output? – techapu Apr 2 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.