branch: externals/bufferlo commit 255bd7f82c1a44c3bd6b2a75762dfb937e00a7ba Author: shipmints <shipmi...@gmail.com> Commit: shipmints <shipmi...@gmail.com>
Working prototype for bufferlo frame bookmark/frameset sessions. Only function not yet implemented is close. Read that docstring. --- bufferlo.el | 447 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 366 insertions(+), 81 deletions(-) diff --git a/bufferlo.el b/bufferlo.el index 51def81569..c83a77111f 100644 --- a/bufferlo.el +++ b/bufferlo.el @@ -479,7 +479,7 @@ Set to 0 to disable the timer. Units are whole integer seconds." "Bufferlo mode-line format to display the current active frame or tab bookmark." (when bufferlo-mode (let ((fbm (frame-parameter nil 'bufferlo-bookmark-frame-name)) - (tbm (alist-get 'bufferlo-bookmark-tab-name (tab-bar--current-tab-find))) + (tbm (alist-get 'bufferlo-bookmark-tab-name (tab-bar--current-tab-find (frame-parameter nil 'tabs)))) (maybe-space (if (display-graphic-p) "" " "))) ; tty rendering can be off for Ⓕ Ⓣ (concat bufferlo-mode-line-lighter-prefix "[" @@ -1509,7 +1509,7 @@ In contrast to `bufferlo-anywhere-mode', this does not adhere to (mapcar #'bufferlo--bookmark-get-for-buffer (bufferlo--bookmark-filter-buffers frame))))) -(defun bufferlo--bookmark-tab-get (&optional frame) +(defun bufferlo--bookmark-tab-make (&optional frame) "Get the bufferlo tab bookmark for the current tab in FRAME. FRAME specifies the frame; the default value of nil selects the current frame." `((buffer-bookmarks . ,(bufferlo--bookmark-get-for-buffers-in-tab frame)) @@ -1533,7 +1533,7 @@ FRAME specifies the frame; the default value of nil selects the current frame." (defun bufferlo--bookmark-tab-handler (bookmark &optional no-message embedded-tab) "Handle bufferlo tab bookmark. The argument BOOKMARK is the to-be restored tab bookmark created -via `bufferlo--bookmark-tab-get'. If the optional argument +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." @@ -1648,7 +1648,7 @@ this bookmark is embedded in a frame bookmark." (put #'bufferlo--bookmark-tab-handler 'bookmark-handler-type "B-Tab") ; short name here as bookmark-bmenu-list hard codes width of 8 chars -(defun bufferlo--bookmark-frame-get (&optional frame) +(defun bufferlo--bookmark-frame-make (&optional frame) "Get the bufferlo frame bookmark. FRAME specifies the frame; the default value of nil selects the current frame." (let ((orig-tab (1+ (tab-bar--current-tab-index nil frame))) @@ -1658,7 +1658,7 @@ FRAME specifies the frame; the default value of nil selects the current frame." (let* ((curr (alist-get 'current-tab (funcall tab-bar-tabs-function frame))) (name (alist-get 'name curr)) (explicit-name (alist-get 'explicit-name curr)) - (tbm (bufferlo--bookmark-tab-get frame))) + (tbm (bufferlo--bookmark-tab-make frame))) (if explicit-name (push (cons 'tab-name name) tbm) (push (cons 'tab-name nil) tbm)) @@ -1671,7 +1671,7 @@ FRAME specifies the frame; the default value of nil selects the current frame." (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-get'. The optional argument NO-MESSAGE inhibits +`bufferlo--bookmark-frame-make'. The optional argument NO-MESSAGE inhibits the message after successfully restoring the bookmark." (let ((new-frame) (keep-new-frame)) @@ -1777,10 +1777,290 @@ the message after successfully restoring the bookmark." (bookmark-prop-set bookmark-name-or-record 'location (or location "")) bookmark-name-or-record) +(defcustom bufferlo-frameset-restore-geometry 'bufferlo + "Frameset restore geometry handling control. + +\\='native uses Emacs built-in geometry handling. + +\\='bufferlo uses bufferlo's geometry handling. + +Set to nil to ignore geometry handling." + :type '(radio (const :tag "Emacs" native) + (const :tag "Bufferlo" bufferlo) + (const :tag "Ignore" nil))) + +(defcustom bufferlo-frameset-save-filter nil + "Extra Emacs frame parameters to filter before saving a `frameset'. +Use this if you define custom frame parameters, or you use +packages that do, and you want to avoid storing such parameters +in bufferlo framesets." + :type '(repeat symbol)) + +(defcustom bufferlo-frameset-restore-filter nil + "Extra Emacs frame parameters to filter before restoring a `frameset'. +Use this if you define custom frame parameters, or you use +packages that do, and you want to ensure they are filtered in +advance of restoring bufferlo framesets." + :type '(repeat symbol)) + +(defvar bufferlo--frameset-save-filter ; filter out vs. frameset-persistent-filter-alist + '( + alpha + alpha-background + auto-lower + auto-raise + background-color + background-mode + border-color + border-width + bottom-divider-width + buffer-predicate + child-frame-border-width + cursor-color + cursor-type + display + display-type + environment + explicit-name + font + font-parameter + foreground-color + horizontal-scroll-bars + icon-name + icon-type + inhibit-double-buffering + internal-border-width + ;; last-focus-update + left-fringe + line-spacing + menu-bar-lines + minibuffer + modeline + mouse-color + ;; name ; ??? + no-accept-focus + no-focus-on-map + no-special-glyphs + ns-appearance + ns-transparent-titlebar + outer-window-id + override-redirect + right-divider-width + right-fringe + screen-gamma + scroll-bar-background + scroll-bar-foreground + scroll-bar-height + scroll-bar-width + shaded + skip-taskbar + sticky + tabs + tab-bar-lines + title + tool-bar-lines + tool-bar-position + tty + tty-type + undecorated + unsplittable + use-frame-synchronization + vertical-scroll-bars + visibility + wait-for-wm + z-group)) + +(defvar bufferlo--frameset-restore-filter + '( + GUI:bottom + GUI:font + GUI:fullscreen + GUI:height + GUI:left + GUI:right + GUI:top + GUI:width + bottom + fontsize + frameset--text-pixel-height + frameset--text-pixel-width + fullscreen + height + left + right + top + width + )) + +(defun bufferlo--bookmark-session-make (active-bookmark-names frameset) + "Make a bufferlo session bookmark. +FRAMESET is a filtered frame set with bufferlo properties +containing ACTIVE-BOOKMARK-NAMES to define the session." + (let ((bookmark-record (bookmark-make-record-default t t 0))) ; (&optional no-file no-context posn) + (bookmark-prop-set bookmark-record 'bufferlo-bookmark-names (if (consp active-bookmark-names) active-bookmark-names (list active-bookmark-names))) + (bookmark-prop-set bookmark-record 'bufferlo-frameset (prin1-to-string frameset)) + (bookmark-prop-set bookmark-record 'handler #'bufferlo--bookmark-session-handler) + bookmark-record)) + +(defun bufferlo--bookmark-session-handler (bookmark-record &optional no-message) + "Handle bufferlo session bookmark. +The argument BOOKMARK-RECORD is the to-be restored session bookmark created via +`bufferlo--bookmark-session-make'. The optional argument NO-MESSAGE inhibits +the message after successfully restoring the bookmark." + (let* ((bookmark-name (bookmark-name-from-full-record bookmark-record)) + (bufferlo-bookmark-names (bookmark-prop-get bookmark-record 'bufferlo-bookmark-names)) + (abm-names (mapcar #'car (bufferlo--active-bookmarks))) + (active-bookmark-names (seq-intersection bufferlo-bookmark-names abm-names))) + (if (> (length active-bookmark-names) 0) + (message "Close or clear active bufferlo bookmarks: %s" active-bookmark-names) + (let* ((frameset-str (bookmark-prop-get bookmark-record 'bufferlo-frameset)) + (frameset)) + (if (not (readablep frameset-str)) + (message "Bufferlo session bookmark %s: unreadable frameset" bookmark-name) + (setq frameset (car (read-from-string frameset-str))) + (if (not (frameset-valid-p frameset)) + (message "Bufferlo session bookmark %s: invalid frameset" bookmark-name) + (let ((default-frame-alist) + (inhibit-redisplay nil)) ; prevent blinking and redisplay costs REVIEW: buffer loading progress messages will be inhibited and perhaps prompts? + (when (ignore-errors + (frameset-restore frameset + :filters + (when (memq bufferlo-frameset-restore-geometry '(bufferlo nil)) + (let ((filtered-alist (copy-tree frameset-persistent-filter-alist))) + (mapc (lambda (sym) (setf (alist-get sym filtered-alist) :never)) + (seq-union bufferlo--frameset-restore-filter bufferlo-frameset-restore-filter)) + filtered-alist)) + :reuse-frames nil + :force-display t + :force-onscreen (display-graphic-p) + :cleanup-frames nil) + t) + (dolist (frame (frame-list)) + (with-selected-frame frame + (when (frame-parameter nil 'bufferlo--frame-to-restore) + (when-let (fbm-name (frame-parameter nil 'bufferlo-bookmark-frame-name)) + (let ((bufferlo-bookmark-frame-load-make-frame nil) + (bufferlo-bookmark-frame-duplicate-policy 'allow) + (bufferlo-bookmark-frame-load-policy 'replace-frame-adopt-loaded-bookmark) + (bufferlo--bookmark-handler-no-message t)) + (bookmark-jump fbm-name #'ignore)) + (when (and + (display-graphic-p frame) + (eq bufferlo-frameset-restore-geometry 'bufferlo)) + (set-frame-position nil + (frame-parameter nil 'bufferlo--frame-left) + (frame-parameter nil 'bufferlo--frame-top)) + (set-frame-size nil + (frame-parameter nil 'bufferlo--frame-pixel-width) + (frame-parameter nil 'bufferlo--frame-pixel-height) + 'pixelwise)) + (set-frame-parameter nil 'bufferlo--frame-to-restore nil)) + (raise-frame frame)))))) + (unless (or no-message bufferlo--bookmark-handler-no-message) + (message "Restored bufferlo session bookmark %s %s" + bookmark-name bufferlo-bookmark-names)))))))) + +(put #'bufferlo--bookmark-session-handler 'bookmark-handler-type "B-Sess") ; short name here as bookmark-bmenu-list hard codes width of 8 chars + +(defun bufferlo--session-save (bookmark-name active-bookmark-names active-bookmarks &optional no-overwrite) + "Save a bufferlo session bookmark for the specified active bookmarks. +Store the session in BOOKMARK-NAME for the named bookmarks in +ACTIVE-BOOKMARK-NAMES represented in ACTIVE-BOOKMARKS. + +If NO-OVERWRITE is non-nil, record the new bookmark without +throwing away the old one. NO-MESSAGE inhibits the save status +message." + (let* ((abms (seq-filter + (lambda (x) (member (car x) active-bookmark-names)) + active-bookmarks)) + (abm-frames (mapcar (lambda (x) (alist-get 'frame (cadr x))) abms))) + (if (= (length abms) 0) + (message "Specify at least one active bufferlo frame bookmark") + ;; Set a flag we can use to identify restored frames (this is + ;; removed in the handler during frame restoration). Save + ;; frame geometries for more accurate restoration than + ;; frameset-restore provides. + (dolist (frame abm-frames) + (set-frame-parameter frame 'bufferlo--frame-to-restore t) + (set-frame-parameter frame 'bufferlo--frame-left (frame-parameter frame 'left)) + (set-frame-parameter frame 'bufferlo--frame-top (frame-parameter frame 'top)) + (set-frame-parameter frame 'bufferlo--frame-pixel-width (frame-text-width frame)) + (set-frame-parameter frame 'bufferlo--frame-pixel-height (frame-text-height frame))) + (let ((frameset (frameset-save + abm-frames + :app 'bufferlo + :name bookmark-name + :predicate (lambda (x) (not (frame-parameter x 'parent-frame))) + :filters + (let ((filtered-alist (copy-tree frameset-persistent-filter-alist))) + (mapc (lambda (sym) (setf (alist-get sym filtered-alist) :never)) + (seq-union bufferlo--frameset-save-filter bufferlo-frameset-save-filter)) + filtered-alist)))) + (bookmark-store bookmark-name + (bufferlo--bookmark-set-location + (bufferlo--bookmark-session-make active-bookmark-names frameset)) + no-overwrite))))) + +(defun bufferlo-session-save-interactive (bookmark-name &optional no-overwrite) + "Save a bufferlo session bookmark for the specified active bookmarks. +The session will be stored under BOOKMARK-NAME. +Only frame bookmarks can be associated with a session. + +If NO-OVERWRITE is non-nil, record the new bookmark without +throwing away the old one." + (interactive + (list (completing-read + "Save bufferlo session bookmark: " + (bufferlo--bookmark-get-names #'bufferlo--bookmark-session-handler) + nil nil nil 'bufferlo-bookmark-session-history nil))) + (bufferlo--warn) + (let* ((abms (bufferlo--active-bookmarks nil 'fbm)) + (abm-names (mapcar #'car abms)) + (comps + (completion-all-completions + (completing-read (format "Add bookmark(s) to %s: " bookmark-name) + (lambda (str pred flag) + (pcase flag + ('metadata + '(metadata (category . bookmark))) + (_ + (all-completions str abm-names pred))))) + abm-names nil nil)) + (base-size (cdr (last comps)))) + (when base-size (setcdr (last comps) nil)) + (setq comps (seq-uniq (mapcar (lambda (x) (substring-no-properties x)) comps))) + (bufferlo--session-save bookmark-name comps abms no-overwrite))) + +(defun bufferlo-session-load-interactive () + "Prompt for bufferlo session bookmarks to load." + (interactive) + (let ((current-prefix-arg '(64))) ; emulate C-u C-u C-u + (call-interactively 'bufferlo-bookmarks-load-interactive))) + +(defun bufferlo-session-close-interactive () + "TODO: WIP: need to decide a few things. + +Should we consider a session bookmark an active entity or just +leave it as an inactive frameset/bookmark container? + +If active, we could keep track of which sessions are \"open\" in +a global. We could enforce a single session at a time or more +than one. The global would contain the session bookmark name and +the constituent bookmarks. + +There is no infrastructure to track if the constituent bookmarks +are themselves still open but could be done since we know all +active bufferlo bookmarks. + +Same with renaming. A bufferlo bookmark associated with a session +does not rename embedded session bookmark names." + ) + (defvar bufferlo--bookmark-handlers (list #'bufferlo--bookmark-tab-handler - #'bufferlo--bookmark-frame-handler) + #'bufferlo--bookmark-frame-handler + #'bufferlo--bookmark-session-handler) "Bufferlo bookmark handlers.") (defun bufferlo--bookmark-get-names (&rest handlers) @@ -1801,15 +2081,15 @@ the message after successfully restoring the bookmark." (defun bufferlo-bookmark-tab-save (name &optional no-overwrite no-message) "Save the current tab as a bookmark. -NAME is the bookmark's name. If NO-OVERWRITE is non-nil, record -the new bookmark without throwing away the old one. NO-MESSAGE -inhibits the save status message. - -This function persists the current tab's state: -The resulting bookmark stores the window configuration and the local -buffer list of the current tab. In addition, it saves the bookmark -state (not the contents) of the bookmarkable buffers in the tab's local -buffer list." + NAME is the bookmark's name. If NO-OVERWRITE is non-nil, record + the new bookmark without throwing away the old one. NO-MESSAGE + inhibits the save status message. + + This function persists the current tab's state: + The resulting bookmark stores the window configuration and the local + buffer list of the current tab. In addition, it saves the bookmark + state (not the contents) of the bookmarkable buffers in the tab's local + buffer list." (interactive (list (completing-read "Save bufferlo tab bookmark: " @@ -1817,7 +2097,7 @@ buffer list." nil nil nil 'bufferlo-bookmark-tab-history (alist-get 'bufferlo-bookmark-tab-name (bufferlo--current-tab))))) (bufferlo--warn) - (bookmark-store name (bufferlo--bookmark-set-location (bufferlo--bookmark-tab-get)) no-overwrite) + (bookmark-store name (bufferlo--bookmark-set-location (bufferlo--bookmark-tab-make)) no-overwrite) (setf (alist-get 'bufferlo-bookmark-tab-name (cdr (bufferlo--current-tab))) name) @@ -1826,12 +2106,12 @@ buffer list." (defun bufferlo-bookmark-tab-load (name) "Load a tab bookmark. -NAME is the bookmark's name. + NAME is the bookmark's name. -`bufferlo-bookmark-tab-replace-policy' controls if the loaded -bookmark replaces the current tab or makes a new tab. + `bufferlo-bookmark-tab-replace-policy' controls if the loaded + bookmark replaces the current tab or makes a new tab. -Specify a prefix argument to force reusing the current tab." + Specify a prefix argument to force reusing the current tab." (interactive (list (completing-read "Load bufferlo tab bookmark: " @@ -1844,10 +2124,10 @@ Specify a prefix argument to force reusing the current tab." (defun bufferlo-bookmark-tab-save-current () "Save the current tab to its associated bookmark. -The associated bookmark is determined by the name of the bookmark to -which the tab was last saved or (if not yet saved) from which it was -initially loaded. Performs an interactive bookmark selection if no -associated bookmark exists." + The associated bookmark is determined by the name of the bookmark to + which the tab was last saved or (if not yet saved) from which it was + initially loaded. Performs an interactive bookmark selection if no + associated bookmark exists." (interactive) (bufferlo--warn) (if-let (bm (alist-get 'bufferlo-bookmark-tab-name @@ -1857,13 +2137,13 @@ associated bookmark exists." (defun bufferlo-bookmark-tab-load-current () "Load the current tab's associated bookmark. -The associated bookmark is determined by the name of the bookmark to -which the tab was last saved or (if not yet saved) from which it was -initially loaded. Performs an interactive bookmark selection if no -associated bookmark exists. + The associated bookmark is determined by the name of the bookmark to + which the tab was last saved or (if not yet saved) from which it was + initially loaded. Performs an interactive bookmark selection if no + associated bookmark exists. -This reuses the current tab even if -`bufferlo-bookmark-tab-replace-policy' is set to \\='new." + This reuses the current tab even if + `bufferlo-bookmark-tab-replace-policy' is set to \\='new." (interactive) (bufferlo--warn) (if-let (bm (alist-get 'bufferlo-bookmark-tab-name @@ -1875,14 +2155,14 @@ This reuses the current tab even if (defun bufferlo-bookmark-frame-save (name &optional no-overwrite no-message) "Save the current frame as a bookmark. -NAME is the bookmark's name. If NO-OVERWRITE is non-nil, record -the new bookmark without throwing away the old one. If NO-MESSAGE -is non-nil, inhibit the save status message. - -This function persists the current frame's state (the \"session\"): -The resulting bookmark stores the window configurations and the local -buffer lists of all tabs in the frame. In addition, it saves the bookmark -state (not the contents) of the bookmarkable buffers for each tab." + NAME is the bookmark's name. If NO-OVERWRITE is non-nil, record + the new bookmark without throwing away the old one. If NO-MESSAGE + is non-nil, inhibit the save status message. + + This function persists the current frame's state (the \"session\"): + The resulting bookmark stores the window configurations and the local + buffer lists of all tabs in the frame. In addition, it saves the bookmark + state (not the contents) of the bookmarkable buffers for each tab." (interactive (list (completing-read "Save bufferlo frame bookmark: " @@ -1890,17 +2170,17 @@ state (not the contents) of the bookmarkable buffers for each tab." nil nil nil 'bufferlo-bookmark-frame-history (frame-parameter nil 'bufferlo-bookmark-frame-name)))) (bufferlo--warn) - (bookmark-store name (bufferlo--bookmark-set-location (bufferlo--bookmark-frame-get)) no-overwrite) + (bookmark-store name (bufferlo--bookmark-set-location (bufferlo--bookmark-frame-make)) no-overwrite) (set-frame-parameter nil 'bufferlo-bookmark-frame-name name) (unless no-message (message "Saved bufferlo frame bookmark: %s" name))) (defun bufferlo-bookmark-frame-load (name) "Load a frame bookmark. -NAME is the bookmark's name. + NAME is the bookmark's name. -Replace the current frame's state if -`bufferlo-bookmark-frame-load-make-frame' is nil." + Replace the current frame's state if + `bufferlo-bookmark-frame-load-make-frame' is nil." (interactive (list (completing-read "Load bufferlo frame bookmark: " @@ -1913,10 +2193,10 @@ Replace the current frame's state if (defun bufferlo-bookmark-frame-save-current () "Save the current frame to its associated bookmark. -The associated bookmark is determined by the name of the bookmark to -which the frame was last saved or (if not yet saved) from which it was -initially loaded. Performs an interactive bookmark selection if no -associated bookmark exists." + The associated bookmark is determined by the name of the bookmark to + which the frame was last saved or (if not yet saved) from which it was + initially loaded. Performs an interactive bookmark selection if no + associated bookmark exists." (interactive) (bufferlo--warn) (if-let (bm (frame-parameter nil 'bufferlo-bookmark-frame-name)) @@ -1925,10 +2205,10 @@ associated bookmark exists." (defun bufferlo-bookmark-frame-load-current () "Load the current frame's associated bookmark. -The associated bookmark is determined by the name of the bookmark to -which the frame was last saved or (if not yet saved) from which it was -initially loaded. Performs an interactive bookmark selection if no -associated bookmark exists." + The associated bookmark is determined by the name of the bookmark to + which the frame was last saved or (if not yet saved) from which it was + initially loaded. Performs an interactive bookmark selection if no + associated bookmark exists." (interactive) (bufferlo--warn) (if-let (bm (frame-parameter nil 'bufferlo-bookmark-frame-name)) @@ -1948,11 +2228,11 @@ associated bookmark exists." (defun bufferlo--active-bookmarks (&optional frames type) "Produces an alist of active bufferlo bookmarks. -The alist is of the form: + The alist is of the form: ((bookmark-name . - ((\\='type . type) (\\='frame . frame) (\\='tab-number . tab-number))) ...) -for the specified FRAMES, -filtered by TYPE, where type is: + ((\\='type . type) (\\='frame . frame) (\\='tab-number . tab-number))) ...) + for the specified FRAMES, + filtered by TYPE, where type is: \\='fbm for frame bookmarks which include frame only or \\='tbm for tab bookmarks which include frame and tab numbers." (let ((abms)) @@ -1971,12 +2251,12 @@ filtered by TYPE, where type is: (defun bufferlo-bookmarks-save-all-p (_bookmark-name) "This predicate matches all bookmark names. -It is intended to be used in `bufferlo-bookmarks-save-predicate-functions'." + It is intended to be used in `bufferlo-bookmarks-save-predicate-functions'." t) (defun bufferlo-bookmarks-load-all-p (_bookmark-name) "This predicate matches all bookmark names. -It is intended to be used in `bufferlo-bookmarks-load-predicate-functions'." + It is intended to be used in `bufferlo-bookmarks-load-predicate-functions'." t) (defun bufferlo--active-bookmark-duplicates() @@ -1990,7 +2270,7 @@ It is intended to be used in `bufferlo-bookmarks-load-predicate-functions'." (defun bufferlo--bookmarks-save (active-bookmark-names active-bookmarks &optional no-message) "Save the bookmarks in ACTIVE-BOOKMARK-NAMES indexed by ACTIVE-BOOKMARKS. -Specify NO-MESSAGE to inhibit the bookmark save status message." + Specify NO-MESSAGE to inhibit the bookmark save status message." (let ((bookmarks-saved nil) (start-time (current-time))) (let ((bookmark-save-flag nil)) ; inhibit built-in bookmark file saving until we're done @@ -2023,26 +2303,26 @@ Specify NO-MESSAGE to inhibit the bookmark save status message." (defun bufferlo-bookmarks-save (&optional all) "Save active bufferlo bookmarks. -This is invoked via an optional idle timer which runs according -to `bufferlo-bookmarks-auto-save-idle-interval', or and is -optionally invoked at Emacs exit. + This is invoked via an optional idle timer which runs according + to `bufferlo-bookmarks-auto-save-idle-interval', or and is + optionally invoked at Emacs exit. -You may invoke this manually at any time to save active -bookmarks; however, doing so does not reset the save interval -timer. + You may invoke this manually at any time to save active + bookmarks; however, doing so does not reset the save interval + timer. -Each bookmark is filtered according to -`bufferlo-bookmarks-save-predicate-functions'. + Each bookmark is filtered according to + `bufferlo-bookmarks-save-predicate-functions'. -Specify ALL to ignore the predicates and save every active -bufferlo bookmark or use a prefix argument across ALL frames, -overriding `bufferlo-bookmarks-save-frame-policy'. + Specify ALL to ignore the predicates and save every active + bufferlo bookmark or use a prefix argument across ALL frames, + overriding `bufferlo-bookmarks-save-frame-policy'. -Note: if there are duplicate active bufferlo bookmarks, the last -one to be saved will take precedence. + Note: if there are duplicate active bufferlo bookmarks, the last + one to be saved will take precedence. -Duplicate bookmarks are handled according to -`bufferlo-bookmarks-save-duplicates-policy'." + Duplicate bookmarks are handled according to + `bufferlo-bookmarks-save-duplicates-policy'." (interactive) (catch :nosave (when-let ((duplicate-bookmarks (bufferlo--active-bookmark-duplicates)) @@ -2053,8 +2333,8 @@ Duplicate bookmarks are handled according to (read-answer (format "Duplicate active bookmarks %s: Allow to save, Disallow to cancel " duplicate-bookmarks) '(("allow" ?a "Allow duplicate") ("disallow" ?d "Disallow duplicates; cancel saving") - ("help" ?h "Help") - ("quit" ?q "Quit with no changes"))))) + ("help" ?h "Help") + ("quit" ?q "Quit with no changes"))))) ("allow" (setq duplicate-policy 'allow)) ("disallow" (setq duplicate-policy 'disallow)) (_ (throw :nosave t)))) @@ -2162,7 +2442,7 @@ current or new frame according to abm-names nil nil)) (base-size (cdr (last comps)))) (when base-size (setcdr (last comps) nil)) - (setq comps (seq-uniq comps)) + (setq comps (seq-uniq (mapcar (lambda (x) (substring-no-properties x)) comps))) (bufferlo--close-active-bookmarks comps abms))) (defun bufferlo-bookmarks-save-interactive () @@ -2182,19 +2462,21 @@ current or new frame according to abm-names nil nil)) (base-size (cdr (last comps)))) (when base-size (setcdr (last comps) nil)) - (setq comps (seq-uniq comps)) + (setq comps (seq-uniq (mapcar (lambda (x) (substring-no-properties x)) comps))) (bufferlo--bookmarks-save comps abms))) (defun bufferlo-bookmarks-load-interactive () "Prompt for bufferlo bookmarks to load. -Use a prefix argument to narrow the candidates to frame tabs, or -a double prefix argument to narrow to tab bookmark candidates." + +Use a single prefix argument to narrow the candidates to frame +bookmarks, double for bookmarks, triple for session bookmarks." (interactive) (let* ((bookmark-names (apply 'bufferlo--bookmark-get-names (cond ((and (consp current-prefix-arg) (eq (prefix-numeric-value current-prefix-arg) 4)) (list #'bufferlo--bookmark-frame-handler)) ((and (consp current-prefix-arg) (eq (prefix-numeric-value current-prefix-arg) 16)) (list #'bufferlo--bookmark-tab-handler)) + ((and (consp current-prefix-arg) (eq (prefix-numeric-value current-prefix-arg) 64)) (list #'bufferlo--bookmark-session-handler)) (t bufferlo--bookmark-handlers)))) (comps (completion-all-completions @@ -2208,7 +2490,7 @@ a double prefix argument to narrow to tab bookmark candidates." bookmark-names nil nil)) (base-size (cdr (last comps)))) (when base-size (setcdr (last comps) nil)) - (setq comps (seq-uniq comps)) + (setq comps (seq-uniq (mapcar (lambda (x) (substring-no-properties x)) comps))) (dolist (bookmark-name comps) (bookmark-jump bookmark-name #'ignore)))) @@ -2350,7 +2632,7 @@ raised." abm-names nil nil)) (base-size (cdr (last comps)))) (when base-size (setcdr (last comps) nil)) - (setq comps (seq-uniq comps)) + (setq comps (seq-uniq (mapcar (lambda (x) (substring-no-properties x)) comps))) (if (not (= (length comps) 1)) (message "Please select a single bookmark to raise") (when-let* ((abm (assoc (car comps) abms))) @@ -2407,6 +2689,9 @@ OLDFN BOOKMARK-NAME BATCH" (defalias 'bufferlo-bm-frame-load 'bufferlo-bookmark-frame-load) (defalias 'bufferlo-bm-frame-load-curr 'bufferlo-bookmark-frame-load-current) (defalias 'bufferlo-bm-frame-load-merge 'bufferlo-bookmark-frame-load-merge) +(defalias 'bufferlo-sess-save 'bufferlo-session-save-interactive) +(defalias 'bufferlo-sess-load 'bufferlo-session-load-interactive) +(defalias 'bufferlo-sess-close 'bufferlo-session-close-interactive) (provide 'bufferlo)