Emacs/EWW Hacks
Collection of emacs snippets to enhance the eww experience.
Quick Search
Quick search prompts the user for a search query. Type anything into the field and press enter to search using duckduckgo.com. If the first word is a keyword, such as "wiki", a different search engine will be used.
(defun my-is-url (string)
"Checks if STRING is a valid URL."
(let ((url-parts (url-generic-parse-url string)))
(and url-parts (url-type url-parts))))
(defvar my-eww-search-engines
'(("w" . "https://en.wikipedia.org/w/index.php?search=%s")
("wiki" . "https://en.wikipedia.org/w/index.php?search=%s")
("wikipedia" . "https://en.wikipedia.org/w/index.php?search=%s")
("yt" . "https://yewtu.be/search?q=%s")
("yewt" . "https://yewtu.be/search?q=%s")
("yewtu" . "https://yewtu.be/search?q=%s")
("wu" . "https://www.catalog.update.microsoft.com/Search.aspx?q=%s")
("wuc" . "https://www.catalog.update.microsoft.com/Search.aspx?q=%s")
("winup" . "https://www.catalog.update.microsoft.com/Search.aspx?q=%s")
("winupdate" . "https://www.catalog.update.microsoft.com/Search.aspx?q=%s")
("windowsupdate" . "https://www.catalog.update.microsoft.com/Search.aspx?q=%s")
("ns" . "https://www.nslookup.io/domains/%s/dns-records/")
("nslookup" . "https://www.nslookup.io/domains/%s/dns-records/")
("who" . "https://www.whois.com/whois/%s")
("whois" . "https://www.whois.com/whois/%s"))
"Alist mapping search keywords to URL templates.")
(defun my-eww-search (query)
"Perform a keyword-based search using EWW or Gemini AI when keyword is 'ai'."
(interactive "sSearch Query: ")
(let* ((parts (split-string query " "))
(keyword (downcase (car parts)))
(engine-url (cdr (assoc keyword my-eww-search-engines))))
(cond
;; Case 1: Known keyword-based search
(engine-url
(let ((search-terms (mapconcat #'identity (cdr parts) " "))
(url (format engine-url (url-hexify-string (mapconcat #'identity (cdr parts) " ")))))
(switch-to-buffer (generate-new-buffer "*eww-search*"))
(eww-mode)
(eww url)
(evil-normal-state)))
;; Case 2: No keyword -> use full query in DuckDuckGo
(t
(let ((url (format "https://lite.duckduckgo.com/lite/?q=%s"
(url-hexify-string query))))
(switch-to-buffer (generate-new-buffer "*eww-search*"))
(eww-mode)
(eww url)
(evil-normal-state))))))
Redirect to the archive.org
Use this to redirect some pages to another site. Redirection requires Emacs be built with libxml2 support.
(defun eww-reddit-redirect(url) "Redirect reddit.com to old.reddit.com
automatically." (replace-regexp-in-string "https://www.reddit.com"
"https://web.archive.org/web/2/https://old.reddit.com" url))
(defun eww-archive-org-redirect(url) "Redirects stackoverflow to use the Archive.org"
(replace-regexp-in-string "https://stackoverflow.com"
"https://web.archive.org/web/2/https://stackoverflow.com" url))
(setq eww-url-transformers '(eww-remove-tracking eww-reddit-redirect eww-archive-org-redirect))
Open page with Archive.org
Run M-x eww-open-latest-archived-page to open the current page using the
archive.org. This can bypass JavaScript requirements and firewalls
(defun eww-open-latest-archived-page ()
"Open the latest archived version of the current EWW page using the Wayback Machine."
(interactive)
(if (eq major-mode 'eww-mode)
(let ((url (plist-get eww-data :url)))
(if url
(eww-browse-url (concat "https://web.archive.org/web/2/" url))
(message "No URL found in EWW buffer.")))
(message "Not in an EWW buffer.")))
Quasi Default Web Browser
With this code, Emacs will prompt the user to open a link with EWW before defaulting a graphical web browser.
(defalias 'gk-urls-external-browser 'browse-url-xdg-open)
(defun gk-browse-url (&rest args)
"Prompt for whether or not to browse with EWW, if no browse
with external browser."
(apply
(if (y-or-n-p "Browse with EWW? ")
'eww-browse-url
#'gk-urls-external-browser)
args))
(setq browse-url-browser-function #'gk-browse-url)
Open EWW at startup
(defun my/open-eww-in-background()
(switch-to-buffer (generate-new-buffer "eww"))
(eww-mode)
(eww "https://lite.duckduckgo.com/lite/")
(switch-to-buffer "*scratch*")
)
(my/open-eww-in-background)
Auto Rename Buffers
Automatically sets the buffername to be the name of the current website.
(setq eww-auto-rename-buffer t)
Simple Styling
(setq browse-url-browser-function 'eww-browse-url) ; Use eww as the default browser
(setq shr-use-fonts nil) ; No special fonts
(setq shr-use-colors nil) ; No colours
(setq shr-indentation 4) ; Left-side margin
(setq shr-width 70) ; Fold text to 70 columns
(setq eww-search-prefix "https://lite.duckduckgo.com/lite/?q=") ; Use another engine for searching
Force EWW to open new buffers by default
Typically EWW only runs as a single buffer, similar to Eshell. This function will make a new EWW buffer by default instead of replacing the previous.
(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)
Search highlighted region
Highlighting a url will open it using EWW. If you highlight text, it'll google the string instead.
(defun my/eww-search-selected (start end)
"Searches the selected text in EWW. If it's a URL, opens it directly. If not, searches Google."
(interactive "r")
(when (use-region-p)
(let ((region (buffer-substring-no-properties start end)))
(if (my/is-url region)
(eww-browse-url region)
(split-window-right)
(balance-windows)
(other-window 1)
(let ((query (replace-regexp-in-string "\n" " " region)))
(eww-browse-url (concat "https://www.google.com/search?q=" (url-hexify-string query))))))))
(define-key map (kbd "C-c s") 'my/eww-search-selected)