From: "Sebastián Monía" <sebastian@sebasmonia.com>
To: Jim Porter <jporterbugs@gmail.com>
Cc: emacs-devel@gnu.org
Subject: Re: [PATCH] Use vtable for eww-bookmarks
Date: Sun, 01 Dec 2024 00:33:42 -0500 [thread overview]
Message-ID: <87ldx0vufd.fsf@sebasmonia.com> (raw)
In-Reply-To: <5f52e217-6eb9-968b-300c-faaf5b18e84e@gmail.com> (Jim Porter's message of "Thu, 28 Nov 2024 11:49:02 -0800")
[-- Attachment #1: Type: text/plain, Size: 733 bytes --]
Jim Porter <jporterbugs@gmail.com> writes:
> Given that, let's go with your implementation, though I do have one
> last concern with the "undo sort": the keybinding ("u") is the same as
> what other table-like modes (e.g. dired, list-packages) use for
> "unmark". Currently we don't support marking/unmarking in the
> bookmarks menu, but that seems like a useful thing we might add one
> day: you could mark several bookmarks in order to open them all,
> delete them all, add some kind of tag to them, etc.
This is a good idea.
> I'm not sure what a better key would be though. Maybe "C" for "clear sort"?
Attached a patch that uses "c" ("c", not "C") and renames the function
to match.
Let me know what you think!
Thanks,
Seb
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: New patch --]
[-- Type: text/x-patch, Size: 8911 bytes --]
From 066a9f856a5d2796a99c1418c7eeefc633ced3ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Mon=C3=ADa?= <code@sebasmonia.com>
Date: Sun, 1 Dec 2024 00:29:08 -0500
Subject: [PATCH] Use vtable in eww-list-bookmarks
---
lisp/net/eww.el | 174 +++++++++++++++++++++++++++---------------------
1 file changed, 98 insertions(+), 76 deletions(-)
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 4d4d4d6beac..20c7892e599 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -2378,115 +2378,124 @@ eww-read-bookmarks
(user-error "No bookmarks are defined"))))
;;;###autoload
-(defun eww-list-bookmarks ()
- "Display the bookmarks."
+(defun eww-list-bookmarks (&optional build-only)
+ "Display the eww bookmarks.
+Optional argument BUILD-ONLY, when non-nil, means to build the buffer
+without popping it."
(interactive)
(eww-read-bookmarks t)
- (pop-to-buffer "*eww bookmarks*")
- (eww-bookmark-prepare))
-
-(defun eww-bookmark-prepare ()
- (set-buffer (get-buffer-create "*eww bookmarks*"))
- (eww-bookmark-mode)
- (let* ((width (/ (window-width) 2))
- (format (format "%%-%ds %%s" width))
- (inhibit-read-only t)
- start title)
+ (with-current-buffer (get-buffer-create "*eww bookmarks*")
+ (eww-bookmark-mode)
+ (eww--bookmark-prepare))
+ (unless build-only
+ (pop-to-buffer "*eww bookmarks*")))
+
+(defun eww--bookmark-prepare ()
+ "Display a table with the list of eww bookmarks.
+Will remove all buffer contents first."
+ (let ((inhibit-read-only t))
(erase-buffer)
- (setq header-line-format (concat " " (format format "Title" "URL")))
- (dolist (bookmark eww-bookmarks)
- (setq start (point)
- title (plist-get bookmark :title))
- (when (> (length title) width)
- (setq title (truncate-string-to-width title width)))
- (insert (format format title (plist-get bookmark :url)) "\n")
- (put-text-property start (1+ start) 'eww-bookmark bookmark))
- (goto-char (point-min))))
+ (make-vtable
+ :columns '((:name "Title" :min-width "25%" :max-width "50%")
+ (:name "URL"))
+ :objects-function #'eww--bookmark-format-data
+ ;; use fixed-font face
+ :face 'default)))
+
+(defun eww--bookmark-format-data ()
+ "Format `eww-bookmarks' for use in a vtable.
+The data is returned as list of (title url bookmark) triplets, for use
+in of `eww-bookmark-mode'."
+ (mapcar (lambda (bm)
+ (list (plist-get bm :title)
+ (plist-get bm :url)
+ bm))
+ eww-bookmarks))
(defvar eww-bookmark-kill-ring nil)
+(defun eww--bookmark-abort-if-sorted ()
+ "Signal a user error if the bookmark vtable at point has been sorted."
+ (when (and (vtable-current-table)
+ (vtable-sort-by (vtable-current-table)))
+ (user-error "Can't kill/yank bookmarks after the table has been sorted")))
+
(defun eww-bookmark-kill ()
"Kill the current bookmark."
(interactive nil eww-bookmark-mode)
- (let* ((start (line-beginning-position))
- (bookmark (get-text-property start 'eww-bookmark))
- (inhibit-read-only t))
- (unless bookmark
+ (eww--bookmark-abort-if-sorted)
+ (let ((bookmark-at-point (nth 2 (vtable-current-object)))
+ (position (point)))
+ (unless bookmark-at-point
(user-error "No bookmark on the current line"))
(forward-line 1)
- (push (buffer-substring start (point)) eww-bookmark-kill-ring)
- (delete-region start (point))
- (setq eww-bookmarks (delq bookmark eww-bookmarks))
- (eww-write-bookmarks)))
+ (push bookmark-at-point eww-bookmark-kill-ring)
+ (setq eww-bookmarks (delq bookmark-at-point eww-bookmarks))
+ (eww-write-bookmarks)
+ (vtable-revert-command)
+ (goto-char position)))
(defun eww-bookmark-yank ()
"Yank a previously killed bookmark to the current line."
(interactive nil eww-bookmark-mode)
+ (eww--bookmark-abort-if-sorted)
(unless eww-bookmark-kill-ring
(user-error "No previously killed bookmark"))
- (beginning-of-line)
- (let ((inhibit-read-only t)
- (start (point))
- bookmark)
- (insert (pop eww-bookmark-kill-ring))
- (setq bookmark (get-text-property start 'eww-bookmark))
- (if (= start (point-min))
- (push bookmark eww-bookmarks)
- (let ((line (count-lines start (point))))
- (setcdr (nthcdr (1- line) eww-bookmarks)
- (cons bookmark (nthcdr line eww-bookmarks)))))
- (eww-write-bookmarks)))
+ (let* ((bookmark-at-point (nth 2 (vtable-current-object)))
+ (index-bap (seq-position eww-bookmarks bookmark-at-point))
+ (position (point)))
+ ;; TODO: a simpler way of doing this?
+ (setq eww-bookmarks (seq-concatenate
+ 'list
+ (seq-subseq eww-bookmarks 0 index-bap)
+ (list (pop eww-bookmark-kill-ring))
+ (seq-subseq eww-bookmarks index-bap)))
+ (eww-write-bookmarks)
+ (vtable-revert-command)
+ (goto-char position)))
(defun eww-bookmark-browse ()
"Browse the bookmark under point in eww."
(interactive nil eww-bookmark-mode)
- (let ((bookmark (get-text-property (line-beginning-position) 'eww-bookmark)))
- (unless bookmark
+ (let ((bookmark-at-point (nth 2 (vtable-current-object))))
+ (unless bookmark-at-point
(user-error "No bookmark on the current line"))
(quit-window)
- (eww-browse-url (plist-get bookmark :url))))
+ (eww-browse-url (plist-get bookmark-at-point :url))))
(defun eww-next-bookmark ()
"Go to the next bookmark in the list."
(interactive nil eww-bookmark-mode)
- (let ((first nil)
- bookmark)
+ (let (fresh-buffer target-bookmark)
(unless (get-buffer "*eww bookmarks*")
- (setq first t)
- (eww-read-bookmarks t)
- (eww-bookmark-prepare))
+ (setq fresh-buffer t)
+ (eww-list-bookmarks t))
(with-current-buffer "*eww bookmarks*"
- (when (and (not first)
- (not (eobp)))
- (forward-line 1))
- (setq bookmark (get-text-property (line-beginning-position)
- 'eww-bookmark))
- (unless bookmark
- (user-error "No next bookmark")))
- (eww-browse-url (plist-get bookmark :url))))
+ (unless fresh-buffer
+ (forward-line 1))
+ (setq target-bookmark (nth 2 (vtable-current-object))))
+ (unless target-bookmark
+ ;; usually because we moved past end of the table
+ (user-error "No next bookmark"))
+ (eww-browse-url (plist-get target-bookmark :url))))
(defun eww-previous-bookmark ()
"Go to the previous bookmark in the list."
(interactive nil eww-bookmark-mode)
- (let ((first nil)
- bookmark)
+ (let (fresh-buffer target-bookmark)
(unless (get-buffer "*eww bookmarks*")
- (setq first t)
- (eww-read-bookmarks t)
- (eww-bookmark-prepare))
+ (setq fresh-buffer t)
+ (eww-list-bookmarks t))
(with-current-buffer "*eww bookmarks*"
- (if first
- (goto-char (point-max))
- (beginning-of-line))
- ;; On the final line.
- (when (eolp)
- (forward-line -1))
- (if (bobp)
- (user-error "No previous bookmark")
- (forward-line -1))
- (setq bookmark (get-text-property (line-beginning-position)
- 'eww-bookmark)))
- (eww-browse-url (plist-get bookmark :url))))
+ (when fresh-buffer
+ (vtable-end-of-table))
+ ;; didn't move to a previous line, because we
+ ;; were already on the first one
+ (unless (= -1 (forward-line -1))
+ (setq target-bookmark (nth 2 (vtable-current-object)))))
+ (unless target-bookmark
+ (user-error "No previous bookmark"))
+ (eww-browse-url (plist-get target-bookmark :url))))
(defun eww-bookmark-urls ()
"Get the URLs from the current list of bookmarks."
@@ -2494,16 +2503,29 @@ eww-bookmark-urls
(eww-read-bookmarks)
(mapcar (lambda (x) (plist-get x :url)) eww-bookmarks))
+(defun eww-bookmark-clear-sort ()
+ "Clear any sorting by column of the bookmarks vtable.
+This is required before killing and yanking bookmarks to re-arrange
+them."
+ (interactive)
+ (let ((bookmark-at-point (vtable-current-object)))
+ (setf (vtable-sort-by (vtable-current-table)) nil)
+ (vtable-revert-command)
+ (while (not (equal (vtable-current-object)
+ bookmark-at-point))
+ (forward-line 1))))
+
(defvar-keymap eww-bookmark-mode-map
"C-k" #'eww-bookmark-kill
"C-y" #'eww-bookmark-yank
+ "c" #'eww-bookmark-clear-sort
"RET" #'eww-bookmark-browse
:menu '("Eww Bookmark"
["Exit" quit-window t]
["Browse" eww-bookmark-browse
- :active (get-text-property (line-beginning-position) 'eww-bookmark)]
+ :active (nth 2 (vtable-current-object))]
["Kill" eww-bookmark-kill
- :active (get-text-property (line-beginning-position) 'eww-bookmark)]
+ :active (nth 2 (vtable-current-object))]
["Yank" eww-bookmark-yank
:active eww-bookmark-kill-ring]))
--
2.47.0
[-- Attachment #3: Type: text/plain, Size: 58 bytes --]
--
Sebastián Monía
https://site.sebasmonia.com/
next prev parent reply other threads:[~2024-12-01 5:33 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-05 22:53 [PATCH] Use vtable for eww-bookmarks Sebastián Monía
2024-11-06 12:21 ` Eli Zaretskii
2024-11-06 13:36 ` Sebastián Monía
2024-11-06 14:33 ` Eli Zaretskii
2024-11-06 14:43 ` Visuwesh
2024-11-06 16:52 ` Sebastián Monía
2024-11-06 20:49 ` Sebastián Monía
2024-11-07 2:00 ` Visuwesh
2024-11-07 2:00 ` Visuwesh
2024-11-20 19:27 ` Sebastián Monía
2024-11-11 7:38 ` Jim Porter
2024-11-23 19:12 ` Jim Porter
2024-11-27 20:02 ` Sebastián Monía
2024-11-28 19:49 ` Jim Porter
2024-12-01 5:33 ` Sebastián Monía [this message]
2024-12-01 6:39 ` Adam Porter
2024-12-01 16:17 ` Sebastián Monía
2024-12-01 19:31 ` Jim Porter
2024-12-01 22:12 ` Sebastián Monía
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ldx0vufd.fsf@sebasmonia.com \
--to=sebastian@sebasmonia.com \
--cc=emacs-devel@gnu.org \
--cc=jporterbugs@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).