branch: externals/bufferlo
commit 4eaab7e03fef1e751f50fa64bacc55e0e5700edf
Author: Florian Rommel <[email protected]>
Commit: Florian Rommel <[email protected]>
Streamline frame & tab bookmark loading and saving
Clean up the code.
bufferlo-bookmark-{frame|tab}-save now ignore the policies if they
already have an associated bookmark.
---
bufferlo.el | 237 +++++++++++++++++++++++++++++-------------------------------
1 file changed, 113 insertions(+), 124 deletions(-)
diff --git a/bufferlo.el b/bufferlo.el
index 46d8b0d3a9..6e8a87b8dc 100644
--- a/bufferlo.el
+++ b/bufferlo.el
@@ -1899,34 +1899,40 @@ FRAME specifies the frame; the default value of nil
selects the current frame."
(when-let (replace (assoc (cadr bc) replace-alist))
(setf (cadr bc) (cdr replace)))))))))
-(defun bufferlo--bookmark-get-duplicate-policy (thing default-policy)
+(defun bufferlo--bookmark-get-duplicate-policy (thing default-policy mode)
"Get the duplicate policy for THING bookmarks.
THING should be either \"frame\" or \"tab\".
Ask the user if DEFAULT-POLICY is set to \\='prompt.
-This functions throws :noload when the user quits."
+MODE is either \\='load or \\='save, depending on the invoking action.
+This functions throws :abort when the user quits."
(if (not (eq default-policy 'prompt))
default-policy
(pcase (let ((read-answer-short t))
(with-local-quit
(read-answer
- (concat
- (format "%s bookmark name already active: " (capitalize
thing))
- "Allow, Clear bookmark after loading, Raise existing ")
- '(("allow" ?a "Allow duplicate")
- ("clear" ?c "Clear the bookmark after loading")
- ("raise" ?r (format "Raise the %s with the existing bookmark"
- thing))
+ (format "%s bookmark name already active: Allow, %s, Raise
existing "
+ (capitalize thing)
+ (if (eq mode 'save)
+ "Clear other bookmark"
+ "Clear bookmark after loading"))
+ `(("allow" ?a "Allow duplicate")
+ ("clear" ?c
+ ,(if (eq mode 'save)
+ (format "Clear the other %s's bookmark association"
thing)
+ (format "Clear this %s's bookmark association after
loading" thing)))
+ ("raise" ?r
+ ,(format "Raise the %s with the active bookmark and quit"
thing))
("help" ?h "Help")
- ("quit" ?q "Quit and abort bookmark loading")))))
+ ("quit" ?q "Quit and abort")))))
("allow" 'allow)
("clear" 'clear)
("raise" 'raise)
- (_ (throw :noload t)))))
+ (_ (throw :abort t)))))
(defun bufferlo--bookmark-tab-get-replace-policy ()
"Get the replace policy for tab bookmarks.
Ask the user if `bufferlo-bookmark-tab-replace-policy' is set to \\='prompt.
-This functions throws :noload when the user quits."
+This functions throws :abort when the user quits."
(if (not (eq bufferlo-bookmark-tab-replace-policy 'prompt))
bufferlo-bookmark-frame-load-policy
(pcase (let ((read-answer-short t))
@@ -1935,29 +1941,38 @@ This functions throws :noload when the user quits."
'(("replace" ?o "Replace tab")
("new" ?n "New tab")
("help" ?h "Help")
- ("quit" ?q "Quit and abort bookmark loading")))))
+ ("quit" ?q "Quit and abort")))))
("replace" 'replace)
("new" 'new)
- (_ (throw :noload t)))))
+ (_ (throw :abort t)))))
-(defun bufferlo--bookmark-tab-get-clear-policy ()
+(defun bufferlo--bookmark-tab-get-clear-policy (mode)
"Get the clear policy for tab bookmarks.
Ask the user if `bufferlo-bookmark-tab-in-bookmarked-frame-policy' is
-set to \\='prompt. This functions throws :noload when the user quits."
+set to \\='prompt. This functions throws :abort when the user quits.
+MODE is either \\='load, \\='save, or \\='save-frame, depending on the
+invoking action. This functions throws :abort when the user quits."
(if (not (eq bufferlo-bookmark-tab-in-bookmarked-frame-policy 'prompt))
bufferlo-bookmark-frame-load-policy
(pcase (let ((read-answer-short t))
(with-local-quit
(read-answer
- (concat "Tab bookmark conflicts with frame bookmark: "
- "Allow tab bookmark, Clear tab bookmark ")
- '(("allow" ?a "Allow tab bookmark")
- ("clear" ?c "Clear tab bookmark")
+ (concat
+ (pcase mode
+ ('load "Tab bookmark conflicts with frame bookmark: ")
+ ('save "Frame already bookmarked: ")
+ ('save-frame "Tabs in this frame are bookmarked: "))
+ (format "Allow tab bookmark, Clear %s bookmark "
+ (if (eq mode 'save) "frame" "tab")))
+ `(("allow" ?a "Allow tab bookmark")
+ ("clear" ?c ,(if (eq mode 'save)
+ "Clear frame bookmark, set tab bookmark"
+ "Clear tab bookmark"))
("help" ?h "Help")
- ("quit" ?q "Quit and abort bookmark loading")))))
+ ("quit" ?q "Quit and abort")))))
("allow" 'allow)
("clear" 'clear)
- (_ (throw :noload t)))))
+ (_ (throw :abort t)))))
(defvar bufferlo--bookmark-handler-no-message nil)
@@ -1968,7 +1983,7 @@ via `bufferlo--bookmark-tab-make'. If the optional
argument
NO-MESSAGE is non-nil, inhibit the message after successfully
restoring the bookmark. If EMBEDDED-TAB is non-nil, indicate that
this bookmark is embedded in a frame bookmark."
- (catch :noload
+ (catch :abort
(let* ((bookmark-name (if (not embedded-tab)
(bookmark-name-from-full-record bookmark)
nil))
@@ -1980,8 +1995,7 @@ this bookmark is embedded in a frame bookmark."
;; Bookmark already loaded in another tab?
(when abm
(let ((duplicate-policy (bufferlo--bookmark-get-duplicate-policy
- "tab"
- bufferlo-bookmark-tab-duplicate-policy)))
+ "tab" bufferlo-bookmark-tab-duplicate-policy
'load)))
(pcase duplicate-policy
('allow)
('clear
@@ -1991,7 +2005,7 @@ this bookmark is embedded in a frame bookmark."
(funcall msg-append "cleared tab bookmark"))
('raise
(bufferlo--bookmark-raise abm)
- (throw :noload t)))))
+ (throw :abort t)))))
;; Bookmark not loaded as part of a frame bookmark?
(unless embedded-tab
@@ -2007,7 +2021,7 @@ this bookmark is embedded in a frame bookmark."
;; Handle an independent tab bookmark inside a frame bookmark
(when (and bookmark-name
(frame-parameter nil 'bufferlo-bookmark-frame-name))
- (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy)))
+ (let ((clear-policy (bufferlo--bookmark-tab-get-clear-policy 'load)))
(pcase clear-policy
('clear
(setq disconnect-tbm-p t))
@@ -2016,7 +2030,7 @@ this bookmark is embedded in a frame bookmark."
(funcall msg-append "cleared tab bookmark"))))))
;; Do the real work: restore the tab
- ;; NOTE: No :noload throws after this point
+ ;; NOTE: No :abort throws after this point
(let* ((ws (copy-tree (alist-get 'window bookmark)))
(dummy (generate-new-buffer " *bufferlo dummy buffer*"));
(restore (lambda (bm)
@@ -2083,7 +2097,7 @@ FRAME specifies the frame; the default value of nil
selects the current frame."
(defun bufferlo--bookmark-frame-get-load-policy ()
"Get the load policy for frame bookmarks.
Ask the user if `bufferlo-bookmark-frame-load-policy' is set to \\='prompt.
-This functions throws :noload when the user quits."
+This functions throws :abort when the user quits."
(if (not (eq bufferlo-bookmark-frame-load-policy 'prompt))
bufferlo-bookmark-frame-load-policy
(pcase (let ((read-answer-short t))
@@ -2096,18 +2110,18 @@ This functions throws :noload when the user quits."
("replace" ?r "Replace frame, adopt the loaded bookmark")
("merge" ?m "Merge the new tab content with the existing
bookmark")
("help" ?h "Help")
- ("quit" ?q "Quit and abort bookmark loading")))))
+ ("quit" ?q "Quit and abort")))))
("current" 'replace-frame-retain-current-bookmark)
("replace" 'replace-frame-adopt-loaded-bookmark)
("merge" 'merge)
- (_ (throw :noload t)))))
+ (_ (throw :abort t)))))
(defun bufferlo--bookmark-frame-handler (bookmark &optional no-message)
"Handle bufferlo frame bookmark.
The argument BOOKMARK is the to-be restored frame bookmark created via
`bufferlo--bookmark-frame-make'. The optional argument NO-MESSAGE inhibits
the message after successfully restoring the bookmark."
- (catch :noload
+ (catch :abort
(let* ((bookmark-name (bookmark-name-from-full-record bookmark))
(abm (assoc bookmark-name (bufferlo--active-bookmarks)))
(fbm (frame-parameter nil 'bufferlo-bookmark-frame-name))
@@ -2125,11 +2139,10 @@ the message after successfully restoring the bookmark."
;; Bookmark already loaded in another frame?
(when abm
(setq duplicate-policy (bufferlo--bookmark-get-duplicate-policy
- "frame"
- bufferlo-bookmark-frame-duplicate-policy))
+ "frame"
bufferlo-bookmark-frame-duplicate-policy 'load))
(when (eq duplicate-policy 'raise)
(bufferlo--bookmark-raise abm)
- (throw :noload t)))
+ (throw :abort t)))
;; No currently active bookmark in the frame?
(if (not fbm)
@@ -2142,7 +2155,7 @@ the message after successfully restoring the bookmark."
(when (not (equal fbm bookmark-name)) ; allow reloads of existing
bookmark
(unless no-message
(message "Frame already bookmarked as %s; not loaded." fbm))
- (throw :noload t)))
+ (throw :abort t)))
('replace-frame-retain-current-bookmark
(funcall msg-append (format "retained existing bookmark %s." fbm)))
('replace-frame-adopt-loaded-bookmark
@@ -2153,7 +2166,7 @@ the message after successfully restoring the bookmark."
bookmark-name)))))
;; Do the real work with the target frame selected (current or newly
created)
- ;; NOTE: No :noload throws after this point
+ ;; NOTE: No :abort throws after this point
(with-selected-frame (if new-frame-p
(with-temp-buffer (make-frame))
(selected-frame))
@@ -2656,54 +2669,41 @@ is not recommended."
nil nil nil 'bufferlo-bookmark-tab-history
(alist-get 'bufferlo-bookmark-tab-name (bufferlo--current-tab)))))
(bufferlo--warn)
- (catch :nosave
- (let ((msg))
- (when-let ((abm (assoc name (bufferlo--active-bookmarks)))
- (duplicate-policy bufferlo-bookmark-tab-duplicate-policy))
- (when (eq duplicate-policy 'prompt)
- (pcase (let ((read-answer-short t))
- (with-local-quit
- (read-answer "Tab bookmark name already active: Allow,
Clear existing, Raise existing, Quit "
- '(("allow" ?a "Allow duplicate")
- ("clear" ?c "Clear the active matching tab
bookmarks, preferring new")
- ("raise" ?r "Raise the existing tab
bookmark")
- ("help" ?h "Help")
- ("quit" ?q "Quit with no changes")))))
- ("allow" (setq duplicate-policy 'allow))
- ("clear" (setq duplicate-policy 'clear))
- ("raise" (setq duplicate-policy 'raise))
- (_ (throw :nosave t))))
- (pcase duplicate-policy
- ('allow)
- ('clear
- (bufferlo--clear-tab-bookmarks-by-name name))
- ('clear-warn
- (bufferlo--clear-tab-bookmarks-by-name name)
- (setq msg (concat msg "; cleared duplicate active tab bookmarks")))
- ('raise
- (bufferlo--bookmark-raise abm)
- (throw :nosave t))))
- (when (frame-parameter nil 'bufferlo-bookmark-frame-name)
- (let ((clear-policy bufferlo-bookmark-tab-in-bookmarked-frame-policy))
- (when (eq clear-policy 'prompt)
- (pcase (let ((read-answer-short t))
- (with-local-quit
- (read-answer "Frame already bookmarked: Allow tab
bookmark, Clear frame bookmark, Quit to cancel "
- '(("allow" ?a "Allow tab bookmark, retain
frame bookmark")
- ("clear" ?c "Clear frame bookmark, set
tab bookmark")
- ("help" ?h "Help")
- ("quit" ?q "Quit--retain the frame
bookmark")))))
- ("allow" (setq clear-policy 'allow))
- ("clear" (setq clear-policy 'clear))
- (_ (setq clear-policy nil)))) ; quit case
- (pcase clear-policy
+ (catch :abort
+ (let* ((abm (assoc name (bufferlo--active-bookmarks)))
+ (tbm (alist-get 'bufferlo-bookmark-tab-name
(tab-bar--current-tab-find)))
+ (msg)
+ (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
+
+ ;; Only check policies when the bm is not already associated with this
tab
+ (unless (and tbm (equal tbm (car abm)))
+
+ ;; Bookmark already loaded in another tab?
+ (when abm
+ (pcase (bufferlo--bookmark-get-duplicate-policy
+ "tab" bufferlo-bookmark-tab-duplicate-policy 'save)
+ ('allow)
+ ('clear
+ (bufferlo--clear-tab-bookmarks-by-name name))
+ ('clear-warn
+ (bufferlo--clear-tab-bookmarks-by-name name)
+ (funcall msg-append "cleared duplicate active tab bookmark"))
+ ('raise
+ (bufferlo--bookmark-raise abm)
+ (throw :abort t))))
+
+ ;; Tab inside a frame bookmark?
+ (when (frame-parameter nil 'bufferlo-bookmark-frame-name)
+ (pcase (bufferlo--bookmark-tab-get-clear-policy 'save)
('allow)
('clear
(set-frame-parameter nil 'bufferlo-bookmark-frame-name nil))
('clear-warn
(set-frame-parameter nil 'bufferlo-bookmark-frame-name nil)
- (setq msg (concat msg "; cleared frame bookmark")))
+ (funcall msg-append "cleared frame bookmark"))
(_ ))))
+
+ ;; Finally, save the bookmark
(bufferlo--bookmark-tab-save name no-overwrite no-message msg))))
(defun bufferlo-bookmark-tab-load (name)
@@ -2805,55 +2805,44 @@ but is not recommended."
nil nil nil 'bufferlo-bookmark-frame-history
(frame-parameter nil 'bufferlo-bookmark-frame-name))))
(bufferlo--warn)
- (catch :nosave
- (let ((msg))
- (when-let ((abm (assoc name (bufferlo--active-bookmarks)))
- (duplicate-policy bufferlo-bookmark-frame-duplicate-policy))
- (when (eq duplicate-policy 'prompt)
- (pcase (let ((read-answer-short t))
- (with-local-quit
- (read-answer "Frame bookmark name already active: Allow,
Clear existing, Raise existing, Quit "
- '(("allow" ?a "Allow duplicate")
- ("clear" ?c "Clear the active matching
frame bookmarks, preferring new")
- ("raise" ?r "Raise the existing frame
bookmark")
- ("help" ?h "Help")
- ("quit" ?q "Quit with no changes")))))
- ("allow" (setq duplicate-policy 'allow))
- ("clear" (setq duplicate-policy 'clear))
- ("raise" (setq duplicate-policy 'raise))
- (_ (throw :nosave t))))
- (pcase duplicate-policy
- ('allow)
- ('clear
- (bufferlo--clear-frame-bookmarks-by-name name))
- ('clear-warn
- (bufferlo--clear-frame-bookmarks-by-name name)
- (setq msg (concat msg "; cleared duplicate active frame
bookmarks")))
- ('raise
- (bufferlo--bookmark-raise abm)
- (throw :nosave t))))
- (when (> (length (bufferlo--active-bookmarks (list (selected-frame))
'tbm)) 0)
- (let ((clear-policy bufferlo-bookmark-tab-in-bookmarked-frame-policy))
- (when (eq clear-policy 'prompt)
- (pcase (let ((read-answer-short t))
- (with-local-quit
- (read-answer "Tabs in this frame have bookmarks: Allow
tab bookmarks, Clear tab bookmarks "
- '(("allow" ?a "Allow tab bookmarks")
- ("clear" ?c "Clear tab bookmarks")
- ("help" ?h "Help")
- ("quit" ?q "Quit")))))
- ("allow" (setq clear-policy 'allow))
- ("clear" (setq clear-policy 'clear))
- (_ (throw :nosave t))))
- (pcase clear-policy
+ (catch :abort
+ (let* ((abm (assoc name (bufferlo--active-bookmarks)))
+ (fbm (frame-parameter nil 'bufferlo-bookmark-frame-name))
+ (msg)
+ (msg-append (lambda (s) (setq msg (concat msg "; " s)))))
+
+ ;; Only check policies when the bm is not already associated with this
frame
+ (unless (and fbm (equal fbm (car abm)))
+
+ ;; Bookmark already loaded in another frame?
+ (when abm
+ (pcase (bufferlo--bookmark-get-duplicate-policy
+ "frame" bufferlo-bookmark-frame-duplicate-policy 'save)
+ ('allow)
+ ('clear
+ (bufferlo--clear-frame-bookmarks-by-name name))
+ ('clear-warn
+ (bufferlo--clear-frame-bookmarks-by-name name)
+ (funcall msg-append "cleared duplicate active frame bookmark"))
+ ('raise
+ (bufferlo--bookmark-raise abm)
+ (throw :abort t))))
+
+ ;; Tab bookmarks in this frame?
+ (when (> (length
+ (bufferlo--active-bookmarks (list (selected-frame)) 'tbm))
+ 0)
+ (pcase (bufferlo--bookmark-tab-get-clear-policy 'save-frame)
('clear
(let ((current-prefix-arg '(4))) ; emulate C-u
(bufferlo-clear-active-bookmarks (list (selected-frame)))))
('clear-warn
(let ((current-prefix-arg '(4))) ; emulate C-u
(bufferlo-clear-active-bookmarks (list (selected-frame))))
- (setq msg (concat msg "; cleared tab bookmarks")))
+ (funcall msg-append "cleared tab bookmarks"))
('allow))))
+
+ ;; Finally, save the bookmark
(bufferlo--bookmark-frame-save name no-overwrite no-message msg))))
(defun bufferlo-bookmark-frame-load (name)
@@ -3014,7 +3003,7 @@ one to be saved will take precedence.
Duplicate bookmarks are handled according to
`bufferlo-bookmarks-save-duplicates-policy'."
(interactive)
- (catch :nosave
+ (catch :abort
(when-let ((duplicate-bookmarks (bufferlo--active-bookmark-duplicates))
(duplicate-policy bufferlo-bookmarks-save-duplicates-policy))
(when (eq duplicate-policy 'prompt)
@@ -3027,10 +3016,10 @@ Duplicate bookmarks are handled according to
("quit" ?q "Quit with no changes")))))
("allow" (setq duplicate-policy 'allow))
("disallow" (setq duplicate-policy 'disallow))
- (_ (throw :nosave t))))
+ (_ (throw :abort t))))
(pcase duplicate-policy
('allow)
- (_ (throw :nosave t))))
+ (_ (throw :abort t))))
(let ((bufferlo-bookmarks-save-predicate-functions
(if (or all (consp current-prefix-arg))
(list #'bufferlo-bookmarks-save-all-p)