ambevar-dotfiles/.emacs.d/lisp/init-eww.el

228 lines
9.1 KiB
EmacsLisp
Raw Normal View History

;;; EWW
;; DONE: Bookmarks: Check if count is correct after saving.
;; DONE: Bookmarks: Check sorting.
;; DONE: Bookmarks: Fix encoding.
;; TODO: Fix `eww-forward-url' infinite forwarding.
;; TODO: Extend the history / bookmarks view to display tags, etc.
;; TODO: Make something useful with the tags. Helm function? Could chain two
;; functions: tag selection then filtered bookmark selection, then tag selection
;; again, etc.
;; Alternative: use special syntax in prompt, like find-files does. This does
;; not allow for listing tags though.
(require 'package-helm-eww nil t)
(setq eww-bookmarks-directory "~/personal/bookmarks"
eww-download-directory "~/temp")
;; (add-to-list 'auto-mode-alist '("eww-bookmarks$" . emacs-lisp-mode))
(defun ambrevar/eww-copy-page-title ()
"Copy the URL of the current page into the kill ring."
(interactive)
(message "%s" (plist-get eww-data :title))
(kill-new (plist-get eww-data :title)))
2018-03-24 15:33:40 +01:00
(defun ambrevar/eww-next-url (&optional backward)
"Like `eww-next-url' but if no next URL is found, go to next URL numerically.
The URL index is the last number after the last '/'."
(interactive)
(condition-case nil
(if backward
(eww-previous-url)
(eww-next-url))
(user-error
(when (eq major-mode 'eww-mode)
(require 'rx)
(let* ((url (plist-get eww-data :url))
(re (rx (group (one-or-more digit))
(zero-or-more (not (any "/")))
line-end)))
(if (and (string-match re url)
(or (not backward)
(> (string-to-number (match-string 1 url)) 0)))
(eww
(replace-regexp-in-string
re
(format (format "%%0.%dd" (length (match-string 1 url))) ; In case matched number is zero-padded.
(funcall (if backward '1- '1+) (string-to-number (match-string 1 url))))
url nil nil 1))
(message "No index in URL.")))))))
(defun ambrevar/eww-previous-url ()
"Like `eww-previous-url' but if no next URL is found, go to next URL numerically.
The URL index is the last number after the last '/'."
(interactive)
(ambrevar/eww-next-url 'backward))
(defun ambrevar/eww-reload-all (&optional buffers)
"Like `eww-reload' but for multiple EWW BUFFERS.
If BUFFERS is not specified, then reload all buffers."
(interactive)
(dolist (b (or buffers (buffer-list)))
(with-current-buffer b
(when (derived-mode-p 'eww-mode)
(eww-reload)))))
(defun ambrevar/eww-switch-back ()
"Switch to the *eww* buffer."
(interactive)
(let (buffer-info)
(dolist (buffer (buffer-list))
(with-current-buffer buffer
(when (derived-mode-p 'eww-mode)
(push buffer buffer-info))))
(setq buffer-info (nreverse buffer-info))
(if buffer-info
(if (derived-mode-p 'eww-mode)
(if (fboundp 'helm-eww)
(helm-eww)
(switch-to-buffer (completing-read "EWW: " (mapcar 'buffer-name buffer-info))))
(switch-to-buffer (car buffer-info)))
(if (fboundp 'helm-eww)
(helm-eww)
(call-interactively 'eww)))))
(defun ambrevar/eww (url)
"Fetch URL and render the page.
If the input doesn't look like an URL or a domain name, the
word(s) will be searched for via `eww-search-prefix'."
(interactive
(let* ((uris (eww-suggested-uris))
(prompt (concat "Enter URL or keywords: "))) ; PATCH
(list (read-string prompt (car uris) nil uris)))) ; PATCH
(setq url (eww--dwim-expand-url url))
(pop-to-buffer-same-window
(if (eq major-mode 'eww-mode)
(current-buffer)
(get-buffer-create "*eww*")))
(eww-setup-buffer)
;; Check whether the domain only uses "Highly Restricted" Unicode
;; IDNA characters. If not, transform to punycode to indicate that
;; there may be funny business going on.
(let ((parsed (url-generic-parse-url url)))
(when (url-host parsed)
(unless (puny-highly-restrictive-domain-p (url-host parsed))
(setf (url-host parsed) (puny-encode-domain (url-host parsed)))
(setq url (url-recreate-url parsed)))))
(plist-put eww-data :url url)
(plist-put eww-data :title "")
(eww-update-header-line-format)
(let ((inhibit-read-only t))
(insert (format "Loading %s..." url))
(goto-char (point-min)))
(url-retrieve url 'eww-render
(list url nil (current-buffer))))
(advice-add 'eww :override 'ambrevar/eww)
(defun ambrevar/eww-open-in-new-buffer (url)
"Fetch URL and render the page.
If the input doesn't look like an URL or a domain name, the
word(s) will be searched for via `eww-search-prefix'."
(interactive
(let* ((uris (eww-suggested-uris))
(prompt (concat "Open URL or keywords in new buffer: ")))
(list (read-string prompt (car uris) nil uris))))
(setq url (eww--dwim-expand-url url))
(pop-to-buffer-same-window
(if (eq major-mode 'eww-mode)
(clone-buffer)
(generate-new-buffer "*eww*")))
(unless (equal url (eww-current-url))
(eww-mode)
(eww (if (consp url) (car url) url))))
(advice-add 'eww-open-in-new-buffer :override 'ambrevar/eww-open-in-new-buffer)
(defun ambrevar/eww-name-buffer-with-title ()
"Include the page title in current EWW buffer name."
(interactive)
(when (derived-mode-p 'eww-mode)
(rename-buffer (format "*eww: %s*" (plist-get eww-data :title)) t)))
(defun ambrevar/eww-update-header-line-format ()
(setq header-line-format
(and eww-header-line-format
(let ((title (plist-get eww-data :title))
(peer (plist-get eww-data :peer)))
(when (zerop (length title))
(setq title "[untitled]"))
;; This connection has is https.
(when peer
(setq title
(propertize title 'face
(if (plist-get peer :warnings)
'eww-invalid-certificate
'eww-valid-certificate))))
(replace-regexp-in-string
"%" "%%"
(format-spec
eww-header-line-format
`((?u . ,(or (plist-get eww-data :url) ""))
(?t . ,title)))))))
;; PATCH
(ambrevar/eww-name-buffer-with-title))
(advice-add 'eww-update-header-line-format :override 'ambrevar/eww-update-header-line-format)
;; TODO: Implement quickmarks. Then merge them.
;; TODO: Implement search engines. Then merge them too.
;; If only one word is found as a non-ambiguous mark, use it as quickmark.
;; If several words and first word is a non-ambiguous mark where search-engine
;; is provided, search.
;; Search-engine is either appended if not starting with https?, or a full
;; URL otherwise. Append search terms like eww already does. Use %s as a place
;; holder.
;; TODO: Add bookmark editing functions such as edit title, tags, quickmark,
;; search-engine. Use eww-buffers and Helm.
(defun ambrevar/eww-add-bookmark ()
"Bookmark the current page."
(interactive)
(eww-read-bookmarks)
(let (tag-list)
(dolist (bookmark eww-bookmarks)
(when (equal
;; PATCH: Ignore protocol when sorting.
;; TODO: Include "sort-bookmarks": Warn for unique tags, warn for same URL up to paragraph. Make this customizable.
(replace-regexp-in-string "^https?" "" (plist-get eww-data :url))
(replace-regexp-in-string "^https?" "" (plist-get bookmark :url)))
(user-error "Already bookmarked"))
(setq tag-list (append tag-list (plist-get bookmark :tags))))
(delete-duplicates tag-list)
(let ((tags (completing-read-multiple "Tags for bookmark (comma separated): " tag-list))
(title (replace-regexp-in-string "[\n\t\r]" " "
(plist-get eww-data :title))))
(setq title (replace-regexp-in-string "\\` +\\| +\\'" "" title))
(push `(:url ,(plist-get eww-data :url)
:title ,title
:time ,(current-time-string)
,@(if tags (list :tags tags)))
eww-bookmarks)
(eww-write-bookmarks)
(message "Bookmarked %s (%s)" (plist-get eww-data :url)
(plist-get eww-data :title)))))
(advice-add 'eww-add-bookmark :override 'ambrevar/eww-add-bookmark)
(defun ambrevar/eww-write-bookmarks ()
(require 'rx)
;; PATCH
(setq eww-bookmarks
(sort eww-bookmarks
(lambda (a b) (string<
;; Ignore protocol when sorting.
(replace-regexp-in-string "^[a-zA-Z]+://" "" (plist-get a :url))
(replace-regexp-in-string "^[a-zA-Z]+://" "" (plist-get b :url))))))
(with-temp-file (expand-file-name "eww-bookmarks" eww-bookmarks-directory)
;; PATCH: Remove newline for tags.
(insert
(replace-regexp-in-string
(rx ":tags" ?\n (1+ space)) ":tags "
(with-temp-buffer
(insert ";; Auto-generated file; don't edit -*- mode: emacs-lisp; -*-\n")
(pp eww-bookmarks (current-buffer))
(buffer-string))))))
(advice-add 'eww-write-bookmarks :override 'ambrevar/eww-write-bookmarks)
(provide 'init-eww)