[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Fixing session management for individual buffers [PATCH]
- From: Boruch Baum <boruch_baum@xxxxxxx>
- Date: Thu, 15 Feb 2018 23:29:53 -0500
- X-ml-name: emacs-w3m
- X-mail-count: 12907
This has been a long time coming, and I hope I got it all okay. Please
triple-check the work.
Before trying the patch, observe the current behavior by performing
the following: exit emacs-w3m, back up your .sessions file (by default
stored in ~/.w3m/.sessions, delete the original, start emacs-w3m, open
a single url, save the session (M-S) as "test1", open a second url,
save the session (M-S) as "test2", open a few more urls, and save the
session a few more times. All this in order to give you material to
play with.
Now let's observe some of the current problems. Enter session
management (M-s) and view all your sessions. Navigate to one of larger
ones, and press (M-s) again to view the detailed list of all that
session's buffers (tabs). Rename and delete a few. Exit back to the
parent list of sessions by pressing `q' or C-g'.
The attached patch should make that all work (please, G-d). It seems
to be reliably working for me at this point.
The patch also corrects grammar in some of the prompts, and adds some
documentation.
--
hkp://keys.gnupg.net
CA45 09B5 5351 7C11 A9D1 7286 0036 9E45 1595 8BC0
Index: ChangeLog
===================================================================
RCS file: /storage/cvsroot/emacs-w3m/ChangeLog,v
retrieving revision 1.3646
diff -u -r1.3646 ChangeLog
--- ChangeLog 15 Feb 2018 08:05:52 -0000 1.3646
+++ ChangeLog 16 Feb 2018 04:11:45 -0000
@@ -1,3 +1,16 @@
+2018-02-15 Boruch Baum <boruch_baum@xxxxxxx>
+
+ * w3m-session.el: Add commentary, correct grammar of prompts..
+ (w3m-session-group-open): New variable
+ (w3m-session-select-quit): Quitting a session-group display returns to
+ its parent session list display.
+ (w3m-session-select-open-session-group, w3m-session-select-rename)
+ (w3m-session-select-delete): Stay on proper line when within
+ session-group display, after renaming or deleting an entry. This
+ required adding an optional arg to the function.
+ (w3m-session-rename): Allow renaming individual tabs of a session.
+ (w3m-session-delete): Allow deleting individual tabs of a session.
+
2018-02-14 Boruch Baum <boruch_baum@xxxxxxx>
* w3m.el (w3m-external-view): Fix regex for url's that contain uri
Index: w3m-session.el
===================================================================
RCS file: /storage/cvsroot/emacs-w3m/w3m-session.el,v
retrieving revision 1.41
diff -u -r1.41 w3m-session.el
--- w3m-session.el 22 Dec 2017 07:17:25 -0000 1.41
+++ w3m-session.el 16 Feb 2018 04:11:45 -0000
@@ -5,6 +5,7 @@
;; Author: Hideyuki SHIRAI <shirai@xxxxxxxxxxx>
;; Keywords: w3m, WWW, hypermedia
+;; Homepage: http://emacs-w3m.namazu.org/
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -23,10 +24,64 @@
;;; Commentary:
-;; w3m-session.el is the add-on program of emacs-w3m to save and load
-;; sessions. For more detail about emacs-w3m, see:
-;;
-;; http://emacs-w3m.namazu.org/
+;; w3m-session.el is an add-on program of emacs-w3m to save, load,
+;; delete, and rename sessions or their selected tabs.
+
+;; You need not load or restore an entire session. You can examine and
+;; manage the contents (individual tabs) of any session, including
+;; deleting, renaming, or loading them one at a time.
+
+;; A session is any collection of buffers (tabs) open at any given
+;; time. Be aware, however, that unfortunately much of the code and
+;; documentation uses the terms session and buffer interchangeably.
+;; There is also a term 'session-group' which is identical to a
+;; session which has more than buffer. Yes, this does need to be
+;; refactored!
+
+;; Session management does its best to automatically keep track of the
+;; current collection of w3m buffers so that should a catastrophic
+;; crash occur, the entire session can be restored. Upon restarting
+;; emacs-w3m after a crash, the user will be prompted whether to
+;; recover the prior session. Additionally, the user may at any time
+;; manually save the current session, or restore the tabs of a prior
+;; session. Note that restoring a prior session is not destructive; it
+;; only adds new tabs into the current session for each tab of the
+;; saved session.
+
+;; Session information is also saved when one quits emacs-w3m using
+;; the `w3m-quit' command, bound by default to `Q'.
+
+;; The session information for all sessions are stored as a single
+;; elisp object, by default in file ~/.w3m/.session. Tab content is
+;; NOT stored. What is stored for each tab is the url, title, cursor
+;; position, and tab history. Even so, this can eventually become a
+;; monstrously large data structure, and probably needlessly, if one
+;; accumulates large history records for each tab.
+
+;;;; Typical usage and tutorial
+
+;; One enters session management by evaluating `w3m-session-select'
+;; (M-s). Typically, there will be at least one session automatically
+;; present, either labeled as a crash recovery session or an
+;; automatically saved one. Next to each session name will be a number
+;; in brackets representing the number of tab (buffers) in the
+;; session. There will also be column entries for the session
+;; timestamp, and summary URL entries. One exits session management
+;; with either `q' or `C-g'.
+
+;; From any emacs-w3m buffer one may save a session by evaluating
+;; `w3m-session-save' (M-S).
+
+;; From within session management, one can rename (`r') or delete
+;; (`d') any session. Selecting a session using the RET key will load
+;; ALL of that session's tabs. You can examine the details of a
+;; session by pressing `M-s' (the same key binding you used to enter
+;; the session management). At this point, you can rename, delete, or
+;; load any individual tab. Note that the first entry on the list
+;; gives you a second chance to load ALL the tabs. Quitting returns
+;; you to the session list.
+
+;; All changes are saved to disk immediately.
;;; Code:
@@ -48,6 +103,16 @@
(autoload 'w3m-load-list "w3m")
(autoload 'w3m-save-list "w3m"))
+(defvar w3m-session-group-open nil
+ "If a session-group is currently open, ie. when displaying a
+ list of buffers for an individual session, this should be set
+ to the session (session-group) number.
+
+ There is a legacy terminology problem that needs to be addressed
+ here. The documentation and symbol names currently confuse
+ 'sessions', 'buffers`, and 'session-groups'. A 'session-group'
+ is identical to a 'session' that has more than one 'buffer'.")
+
(defcustom w3m-session-file
(expand-file-name ".sessions" w3m-profile-directory)
"*File name to keep sessions."
@@ -118,18 +183,20 @@
:type 'string)
(defcustom w3m-session-load-last-sessions nil
- "*Whether to load the last sessions when emacs-w3m starts."
+ "*Whether to re-load the most recent session when emacs-w3m
+starts."
:group 'w3m
- :type '(radio (const :format "Load the last sessions automatically." t)
- (const :format "Ask whether to load the last sessions." ask)
- (const :format "Never load the last sessions automatically." nil)))
+ :type '(radio (const :format "Re-load the last session automatically." t)
+ (const :format "Ask whether to re-load the last session." ask)
+ (const :format "Never re-load the last session automatically." nil)))
(defcustom w3m-session-load-crashed-sessions 'ask
- "*Whether to load the crashed sessions when emacs-w3m starts."
+ "*Whether to re-load a crashed session when emacs-w3m starts.
+This is used when emacs-w3m determines that the most recent session crashed."
:group 'w3m
- :type '(radio (const :format "Load the crashed sessions automatically." t)
- (const :format "Ask whether to load the crashed sessions." ask)
- (const :format "Never load the crashed sessions automatically." nil)))
+ :type '(radio (const :format "RelLoad the crashed session automatically." t)
+ (const :format "Ask whether to re-load the crashed session." ask)
+ (const :format "Never re-load the crashed session automatically." nil)))
(defface w3m-session-select
`((((class color) (background light) (type nil))
@@ -171,7 +238,7 @@
(list x)))
(copy-sequence (w3m-history-slimmed-history-flat))))))
-;; format of sessin file.
+;; format of session file.
;; '((sessiontitle1 time1 ((url11 pos11 hflat11 urltitle11)
;; (url12 pos12 hflat12 urltitle12) ...) current1)
;; ...
@@ -183,22 +250,26 @@
(error
(if (and (file-exists-p w3m-session-file)
(yes-or-no-p (format
- "\
-Sorry, an error found in \"%s\"; may we remove it? "
+ "An error was found in \"%s\"; may we remove it? "
,(if (featurep 'xemacs)
'(abbreviate-file-name w3m-session-file t)
'(abbreviate-file-name w3m-session-file)))))
(progn
(delete-file w3m-session-file)
(run-at-time 0.1 nil #'message
- "\"%s\" has been removed; try again"
+ "\"%s\" has been removed; try again."
(abbreviate-file-name w3m-session-file))
(keyboard-quit))
(signal (car err) (cdr err))))))
;;;###autoload
(defun w3m-session-save ()
- "Save list of displayed session."
+ "Save the current session (all currently open emacs-w3m buffers).
+
+The user will be prompted for a name for the saved session. The
+saved session information will include, for each currently open
+emacs-w3m buffer: the current url and page title, and the
+buffer's url history."
(interactive)
(w3m-session-ignore-errors
(let ((sessions (w3m-load-list w3m-session-file))
@@ -221,9 +292,9 @@
(setq title (completing-read prompt titles nil nil nil nil title)))
(if (or (string= title "")
(and (assoc title sessions)
- (not (y-or-n-p (format "\"%s\" is exist. Overwrite? "
+ (not (y-or-n-p (format "\"%s\" exists. Overwrite? "
title)))))
- (setq prompt "Again New session title: ")
+ (setq prompt "New session title: ")
(throw 'loop t))))
(setq cbuf (current-buffer))
(save-current-buffer
@@ -240,16 +311,14 @@
w3m-current-title)
urls)))))
(if (not urls)
- (message "%s: no session save...done" title)
+ (message "%s: no buffers saved...done" title)
(setq len (length urls))
(setq urls (nreverse urls))
(when (assoc title sessions)
(setq sessions (delq (assoc title sessions) sessions)))
(setq sessions (cons (list title (current-time) urls cnum) sessions))
(w3m-save-list w3m-session-file sessions)
- (if (= len 1)
- (message "%s: 1 session save...done" title)
- (message "%s: %d sessions save...done" title len))
+ (message "%s: %d buffer%s saved...done" title len (if (= len 1) "" "s"))
(when (and (setq buf (get-buffer " *w3m-session select*"))
(get-buffer-window buf 'visible))
(save-selected-window (w3m-session-select)))))))
@@ -435,11 +504,12 @@
major-mode 'w3m-session-select-mode
w3m-session-select-sessions sessions
buffer-read-only t)
+ (setq w3m-session-group-open nil)
(use-local-map w3m-session-select-mode-map)
(w3m-session-select-list-all-sessions))))
(defun w3m-session-select-list-all-sessions ()
- "List up all saved sessions."
+ "List all saved sessions."
(let ((sessions w3m-session-select-sessions)
(num 0)
(max 0)
@@ -496,6 +566,11 @@
(setq buffer-read-only t))))
(defun w3m-session-select-list-session-group (arg)
+ "List all buffers (ie. tabs) within a session.
+
+The list can be acted upon similarly to a session list, ie.
+entries can be individually deleted, renamed, or opened as a new
+buffer in the current session."
(let ((session (nth 2 (nth arg w3m-session-select-sessions)))
(num 0)
(max 0)
@@ -578,11 +653,15 @@
(defun w3m-session-select-quit ()
"Exit from w3m session select mode."
(interactive)
- (let ((buffer (current-buffer))
- (wincfg w3m-session-select-wincfg))
- (or (one-window-p) (delete-window))
- (kill-buffer buffer)
- (set-window-configuration wincfg)))
+ (if w3m-session-group-open
+ (let ((num w3m-session-group-open))
+ (setq w3m-session-group-open nil)
+ (w3m-session-select-list-all-sessions))
+ (let ((buffer (current-buffer))
+ (wincfg w3m-session-select-wincfg))
+ (or (one-window-p) (delete-window))
+ (kill-buffer buffer)
+ (set-window-configuration wincfg))))
(defun w3m-session-select-select ()
"Select the session."
@@ -590,30 +669,30 @@
(beginning-of-line)
(let* ((num (get-text-property
(point) 'w3m-session-number))
- (item (if (consp num)
+ (item (if (consp num)
(nth (cdr num)
- (caddr (nth (car num)
+ (caddr (nth (car num)
w3m-session-select-sessions)))
(nth num w3m-session-select-sessions)))
(session (if (consp num)
(list (or (cadddr item) w3m-session-unknown-title)
nil
- (list item)
+ (list item)
nil)
item)))
(w3m-session-select-quit)
(w3m-session-goto-session session)))
-(defun w3m-session-select-open-session-group ()
+(defun w3m-session-select-open-session-group (&optional arg)
"Open the session group."
(interactive)
(beginning-of-line)
- (let ((num (get-text-property
- (point) 'w3m-session-number))
+ (let ((num (or arg (get-text-property (point) 'w3m-session-number)))
wheight)
(if (consp num)
- (message "There is no session group.")
- (setq wheight
+ (message "This is not a session group.")
+ (setq w3m-session-group-open num)
+ (setq wheight
(max (+ (length (caddr (nth num w3m-session-select-sessions))) 6)
window-min-height))
(condition-case nil
@@ -624,7 +703,7 @@
(defun w3m-session-select-save ()
"Save the session."
(interactive)
- (when (y-or-n-p "Save this sessions? ")
+ (when (y-or-n-p "Save this session? ")
(w3m-session-select-quit)
(w3m-session-save)
(w3m-session-select)))
@@ -637,18 +716,25 @@
(point) 'w3m-session-number))
(sessions w3m-session-select-sessions))
(w3m-session-rename sessions num)
- (w3m-session-select num)))
+ (if (not w3m-session-group-open)
+ (w3m-session-select num)
+ (w3m-session-select-open-session-group w3m-session-group-open))))
(defun w3m-session-select-delete ()
- "Delete the session."
+ "Delete an entry (either a session or a buffer)."
(interactive)
- (when (y-or-n-p "Delete this session? ")
+ (when (y-or-n-p "Delete this entry? ")
(beginning-of-line)
(let ((num (get-text-property
(point) 'w3m-session-number))
(sessions w3m-session-select-sessions))
(w3m-session-delete sessions num)
- (w3m-session-select (min num (1- (length sessions)))))))
+;; (w3m-session-select)
+;; (forward-line (min num (- (line-number-at-pos (point-max)) 4))))))
+ (if (not w3m-session-group-open)
+ (w3m-session-select (min num (1- (length sessions))))
+ (w3m-session-select-open-session-group w3m-session-group-open)
+ (forward-line (min (cdr num) (- (line-number-at-pos (point-max)) 4)))))))
;;;###autoload
(defun w3m-session-select (&optional n)
@@ -724,41 +810,63 @@
(message "Session goto(%s)...done" title)))
(defun w3m-session-rename (sessions num)
- (if (consp num)
- (message
- "This command must be run from the `w3m-session-select' minibuffer.")
- ; OK, but why do we allow `w3m-session-delete' to run otherwise?
- (let* ((default-prompt "Enter new session title (C-g to abort): ")
- (prompt default-prompt)
- overwrite
- title
- (tmp (nth num sessions))
- (otitle (car tmp)))
- (while (not title)
- ;; A devious way to emulate INITIAL-INPUT that is deprecated.
- (let ((minibuffer-setup-hook (lambda nil (insert otitle))))
- (setq title (read-from-minibuffer prompt nil nil nil nil otitle)))
- (cond
- ((string= title "")
- (setq title nil
- prompt default-prompt))
- ((string= title otitle)
- (setq prompt (concat title
- " is same as original title (C-g to abort): ")
- title nil))
- ((assoc title sessions)
- (if (not (y-or-n-p (format "\"%s\" exists. Overwrite? " title)))
- (setq prompt default-prompt
- title nil))
- (setq sessions (delq (assoc title sessions) sessions))
- (setq num (seq-position sessions (assoc otitle sessions))))))
- ; in this case, wrapper must decrement its copy of num
- (setcar tmp title)
- (setcar (nthcdr num sessions) tmp)
- (w3m-save-list w3m-session-file sessions))))
+ ; When num is a cons cell, we are not dealing with a session, but
+ ; with a single buffer entry (ie. a tab) within a session. The car
+ ; of the cons will be the session number, and the cdr will be the
+ ; buffer number.
+ (let* ((default-prompt "Enter new session title (C-g to abort): ")
+ (prompt default-prompt)
+ overwrite
+ title
+ (group (if (consp num) (nth 2 (nth (car num) sessions)) nil))
+ (tmp (if group (nth (cdr num) group) (nth num sessions)))
+ (otitle (if (consp num) (nth 2 (cdr tmp)) (car tmp))))
+ (while (not title)
+ ;; A devious way to emulate INITIAL-INPUT that is deprecated.
+ (let ((minibuffer-setup-hook (lambda nil (insert otitle))))
+ (setq title (read-from-minibuffer prompt nil nil nil nil otitle)))
+ (cond
+ ((string= title "")
+ (setq title nil
+ prompt default-prompt))
+ ((string= title otitle)
+ (setq prompt (concat title
+ " is same as original title (C-g to abort): ")
+ title nil))
+ ((assoc title (if group nil sessions)
+ (if (not (y-or-n-p (format "\"%s\" exists. Overwrite? " title)))
+ (setq prompt default-prompt
+ title nil))
+ (cond
+ (group ; handle *buffer* rename within a session ("session-group")
+ (setq prompt "Not yet supported. Manually delete the other entry, or try again."
+ title nil))
+ (t
+ (setq sessions (delq (assoc title sessions) sessions))
+ (setq num (seq-position sessions (assoc otitle sessions)))))))))
+ ; in this case, wrapper must decrement its copy of num
+ ; BB_2018-02-15: I don't understand that comment
+ (cond
+ (group ; handle *buffer* rename within a session ("session-group")
+ (setf (nth 2 (cdr tmp)) title)
+ (setf (nth (cdr num) group) tmp)
+ (setf (nth 2 (nth (car num) sessions)) group))
+ ; BB_2018-02-15: The good news is that this seems to be working;
+ ; the bad news is that an examination of the .sessions file
+ ; reveals a format difference, in that the original buffer name
+ ; was encoded with text properties, like so:
+ ; #("w3m_home_page.html" 0 1 (idx 0))
+ ; and the replacement is just a string. The text property may
+ ; just be cruft for the purpose of this file, but I'm not sure.
+ (t
+ (setcar tmp title)
+ (setcar (nthcdr num sessions) tmp)))
+ (w3m-save-list w3m-session-file sessions)))
(defun w3m-session-delete (sessions num)
(if (consp num)
+ ; When num is a cons cell, we are not dealing with a session,
+ ; but with a single buffer entry (ie. a tab) within a session
(let* ((item (nth 2 (nth (car num) sessions)))
(tmp (delq (nth (cdr num) item) item)))
(setf (nth 2 (nth (car num) sessions)) tmp))