From 1b0abee054235ea4ac7589dd92d3939e1386d24a Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Tue, 12 Oct 2010 23:39:29 +0200 Subject: Initial contents --- net/jao-w3m-session.el | 410 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 net/jao-w3m-session.el (limited to 'net/jao-w3m-session.el') diff --git a/net/jao-w3m-session.el b/net/jao-w3m-session.el new file mode 100644 index 0000000..7b8979b --- /dev/null +++ b/net/jao-w3m-session.el @@ -0,0 +1,410 @@ +;;; w3m-session.el --- Persistent emacs-w3m sessions + +;; Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 Jose A Ortega Ruiz + +;; Author: Jose A Ortega Ruiz +;; Version: 0.3.6 +;; Keywords: hypermedia, w3m, WWW + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: + +;; INTRODUCTION: +;; +;; jao-w3m-session provides persistent emacs-w3m browsing sessions. When +;; quitting w3m (or, if you request it, at any other time while using +;; it) you can save the current w3m session (that is, the set of open +;; tabs and the URLs they're visiting). Upon restarting emacs-w3m +;; (possibly after restarting Emacs itself) you'll have the possibity +;; of recovering the saved session (that is, of re-opening the saved +;; tabs and URLs). You also have at your disposal a command to recover +;; the saved session at any other time. +;; +;; INSTALLATION: +;; +;; Just put this file somewhere on your Emacs load path and add the +;; following line to your .emacs file: +;; +;; (require 'jao-w3m-session) +;; +;; After restarting Emacs (or evaluating the form above), each time +;; you start emacs-w3m with 'w3m' you'll get a prompt asking whether +;; your last browsing session should be loaded. Likewise, when +;; quitting the browser, you'll have the possibility of saving your +;; current session (overwriting the previous one). +;; +;; In addition, two new interactive functions are defined: +;; +;; jao-w3m-session-load -- load the last stored session +;; jao-w3m-session-save -- save the current session +;; +;; These functions can be invoked at any time while running emacs-w3m. +;; Optionally, you can bind them to key shortcuts with the proper +;; variations of the following elisp magic in your .emacs: +;; (defun w3m-add-keys () +;; (define-key w3m-mode-map "S" 'jao-w3m-session-save) +;; (define-key w3m-mode-map "L" 'jao-w3m-session-load)) +;; (add-hook 'w3m-mode-hook 'w3m-add-keys) +;; +;; CUSTOMIZATION: +;; +;; A new customization group, jao-w3m-session, is available. There you can +;; customize the following variables: +;; +;; jao-w3m-session-load-always -- if t, `jao-w3m-session-load' will *not* ask +;; for confirmation (default nil) +;; jao-w3m-session-save-always -- if t, `jao-w3m-session-save' will *not* ask +;; for confirmation (default nil) +;; jao-w3m-session-show-titles -- if t, the load prompt will list the +;; session URL titles (default t) +;; jao-w3m-session-duplicate-tabs -- what to do when loading a session that +;; contains a URL already open +;; jao-w3m-session-file -- the file where w3m session info +;; is stored (default "~/.jao-w3m-session") +;; jao-w3m-session-autosave-period -- the period, in seconds, for automatic +;; session backup file updating. +;; +;; +;; You can also customize them in your .emacs file, to wit: +;; +;; (setq jao-w3m-session-file "~/.emacs.d/jao-w3m-session") +;; (setq jao-w3m-session-save-always nil) +;; (setq jao-w3m-session-load-always nil) +;; (setq jao-w3m-session-show-titles t) +;; (setq jao-w3m-session-duplicate-tabs 'ask) ; 'never, 'always, 'ask +;; +;; HISTORY: +;; +;; Version 0.3.7 : +;; +;; - `jao-w3m-session-deactivate-builtin-sessions', to do what it +;; says. +;; +;; Version 0.3.6 (Sat Apr 19, 2008): +;; +;; - w3m-session -> jao-w3m-session to avoid collisions with +;; emacs-w3m's session manager. +;; +;; Version 0.3.5 (Sun Jan 14, 2007): +;; +;; - automatic session backup every `jao-w3m-session-autosave-period' +;; seconds. +;; +;; Version 0.3.4 (Wed Jul 19, 2006): +;; +;; - save session file on quitting Emacs (without using +;; desktop.el) +;; +;; Version 0.3.3 (Thu Jun 8, 2006): +;; +;; - save session file with pretty print. +;; - handle correctly multiple emacs-w3m (re)starts during a +;; single emacs session. +;; - save URLs in hexified form to allow & in them. +;; - code cleanup. +;; +;; Version 0.3.2 (Mon Sep 29, 2003): +;; +;; - bug fix: when searching or going to home/bookmarks/etc, +;; keep the current tab's focus. +;; +;; Version 0.3.1 (Tue Aug 26, 2003): +;; +;; - type of `jao-w3m-session-file' set to 'file' in customisation +;; buffer. +;; - bug fix: syntax error due to a typo in `jao-w3m-session-file' +;; +;; Version 0.3 (Mon Aug 25, 2003): +;; +;; - the load session tab lists the titles of the session's pages +;; (customizable via 'jao-w3m-session-show-titles'). +;; - the duplicated tab prompt displays also the URL's title. +;; - bug fix: active tab in session now is correctly saved. +;; +;; Version 0.2 (Fri Aug 22, 2003): +;; +;; - the session info now includes the active tab, which gets +;; displayed when the session is reloaded. +;; - when reloading a session in a running emacs-w3m, if the +;; session contains a URL that is already being displayed by the +;; browser, the tab can be reused or duplicated (customizable +;; via `jao-w3m-session-duplicate-tabs'). +;; +;; Version 0.1 (Wed Aug 20, 2003) -- Initial release. +;; + + +;;; Code: + +;;; Dependencies: + +(require 'w3m) +(require 'advice) +(require 'url-util) + +;;; Custom variables: + +(defgroup jao-w3m-session nil + "w3m - session saving in w3m." + :group 'w3m + :prefix "jao-w3m-session-") + +(defcustom jao-w3m-session-save-always nil + "If on, always save w3m session without asking." + :group 'jao-w3m-session + :type 'boolean) + +(defcustom jao-w3m-session-load-always nil + "If on, always load w3m session without asking." + :group 'jao-w3m-session + :type 'boolean) + +(defcustom jao-w3m-session-show-titles t + "If on, show URL titles in the load prompt." + :group 'jao-w3m-session + :type 'boolean) + +(defcustom jao-w3m-session-duplicate-tabs 'never + "How to treat session URL already being visited. + +When loading a session with `jao-w3m-session-load', if one of the URLs in +the session is already displayed in a w3m tab, jao-w3m-session can: +- `never' create a new tab (just reload it), or +- `always' duplicate the URL in a new tab, or +- `ask' the user what to do." + :group 'jao-w3m-session + :type '(choice (const :value never) + (const :value always) + (const :value ask))) + +(defcustom jao-w3m-session-file "~/.jao-w3m-session" + "File to save the w3m session data." + :group 'jao-w3m-session + :type 'file) + +(defvar jao-w3m-session-autosave-period 180 + "A backup of the current session is saved with this period (in secs).") + +(defvar jao-w3m-url-filters nil "URL filters.") + +;;; Interactive functions: + +(defun jao-w3m-session-save () + "Save the current w3m session." + (interactive) + (when (and (w3m-alive-p) + (or jao-w3m-session-save-always + (y-or-n-p "Save current w3m session? "))) + (jao-w3m-session-current-to-file) + (jao-w3m-session--restart--autosave))) + +(defun jao-w3m-session-load () + "Load last stored session into w3m." + (interactive) + (let ((s (jao-w3m-session-load-aux))) + (when s + (jao-w3m-session--restart--autosave) + (let* ((urls (jao-w3m-session-url s)) + (offset (jao-w3m-session-offset s)) + (buffers (unless (equal jao-w3m-session-duplicate-tabs 'always) + (jao-w3m-session-find-duplicated urls)))) + (w3m-goto-url-new-session urls t) + (when buffers (jao-w3m-session-close-buffers buffers)) + (unless (zerop offset) (w3m-next-buffer offset)))))) + +(defun jao-w3m-session-set-autosave-period (secs) + "Set new value for the period between session backup autosaves." + (interactive "p") + (let ((secs (or secs (read-number "New period (secs): " 0)))) + (when (> secs 0) + (setq jao-w3m-session-autosave-period secs) + (jao-w3m-session--restart--autosave)))) + +(defun jao-w3m-session-deactivate-builtin-sessions () + "Deactivate emacs-w3m's builtin session handling." + (setq w3m-session-deleted-save nil + w3m-session-autosave nil + w3m-session-deleted-keep-number 0 + w3m-session-crash-recovery nil)) + +;;; Internals: + +;;;; advice w3m to use session management + +(defadvice w3m (before jao-load-session activate) + "Optionally load last w3m session on startup." + (interactive + (let ((s (jao-w3m-session-load-aux))) + (list (or (and s (jao-w3m-session-url s)) w3m-home-page) t t)))) + +(defadvice w3m (after jao-select-tab activate) + "Goto the saved focused tab" + (interactive) + (let ((offset (jao-w3m-session-offset))) + (unless (zerop offset) + (w3m-next-buffer offset)) + (ad-deactivate 'w3m))) + +(defadvice w3m-quit (before jao-save-session activate) + "Save session before quitting." + (interactive) + (jao-w3m-session-save) + ;; this is a little hack: when quitting a w3m session with a tab + ;; selected other than the first, the frame is not automatically + ;; closed as should be when w3m-pop-up-frames is t: + (switch-to-buffer (car (w3m-list-buffers))) + (ad-activate 'w3m)) + +;;;; save session on exit +(add-to-list 'kill-emacs-query-functions + '(lambda () (jao-w3m-session-save) t)) + + +;;;; auxiliary functions + +(defvar jao-w3m-current-session '(jao-w3m-session 0 nil)) + +(defun jao-w3m-session--filter (url filters) + (cond ((not filters) url) + ((string-match-p (caar filters) url) + (cond ((functionp (cdar filters)) (funcall (cadr filters) url)) + ((stringp (cdar filters)) (cdar filters)))) + (t (jao-w3m-session--filter url (cdr filters))))) + +(defun jao-w3m-session--current-urls () + (let ((urls) + (current-buffer (w3m-alive-p)) + (pos 0) + (count 0)) + (dolist (b (w3m-list-buffers) (list pos (reverse urls))) + (set-buffer b) + (let ((url (jao-w3m-session--filter w3m-current-url jao-w3m-url-filters))) + (when url + (when (eq b current-buffer) (setq pos count)) + (setq count (1+ count)) + (push (cons (url-hexify-string url) (w3m-buffer-title b)) urls)))))) + +(defun jao-w3m-session-url (&optional s) + (let ((s (or s jao-w3m-current-session))) + (concat "group:" + (mapconcat 'car (nth 2 s) "&")))) + +(defun jao-w3m-session-offset (&optional s) + (let ((s (or s jao-w3m-current-session))) + (nth 1 s))) + +(defun jao-w3m-session-titles (&optional s) + (let ((s (or s jao-w3m-current-session))) + (mapcar 'cdr (nth 2 s)))) + +(defun jao-w3m-session-current (&optional s) + (save-current-buffer + (setq jao-w3m-current-session + (or s (cons 'jao-w3m-session (jao-w3m-session--current-urls)))))) + +(defun jao-w3m-session-current-url () + (when (w3m-alive-p) + (save-current-buffer + (concat "group:" + (mapconcat (lambda (b) (set-buffer b) w3m-current-url) + (w3m-list-buffers) "&"))))) + +(defun jao-w3m-session-find-duplicated (urls) + (when (w3m-alive-p) + (save-current-buffer + (let* ((duplicate-p + (lambda (b) + (y-or-n-p + (format "'%s' (%s) is already open. Duplicate tab? " + (w3m-buffer-title b) w3m-current-url)))) + (test-b + (lambda (b) + (set-buffer b) + (if (and + (string-match (regexp-quote w3m-current-url) urls) + (or (equal jao-w3m-session-duplicate-tabs 'never) + (not (funcall duplicate-p b)))) + b 'not))) + (buffers (mapcar test-b (w3m-list-buffers)))) + (delete 'not buffers))))) + +(defun jao-w3m-session-close-buffers (buffers) + (save-current-buffer + (mapc 'kill-buffer buffers))) + +(defun jao-w3m-session-load-aux () + (let ((new-session (jao-w3m-session-from-file + (expand-file-name jao-w3m-session-file)))) + (if (and new-session + (or jao-w3m-session-load-always + (y-or-n-p + (if jao-w3m-session-show-titles + (format "Load last w3m session %S? " + (jao-w3m-session-titles new-session)) + "Load last w3m session? ")))) + (jao-w3m-session-current new-session) + nil))) + +(defun jao-w3m-session-from-file (fname) + (let ((fname (jao-w3m-session--check--backup fname))) + (if (file-readable-p fname) + (with-temp-buffer + (insert-file-contents fname) + (goto-char (point-min)) + (let ((sexp (read (current-buffer)))) + (and (equal 'jao-w3m-session (car sexp)) sexp))) + nil))) + +(defsubst jao-w3m-session-current-to-file () + (jao-w3m-session--to--file jao-w3m-session-file)) + +(defun jao-w3m-session--to--file (filename &optional is-auto) + (require 'pp) + (let ((msg (if is-auto (current-message)))) + (with-temp-buffer + (insert ";;;; File generated by jao-w3m-session. DO NOT EDIT!\n") + (pp (jao-w3m-session-current) (current-buffer)) + (insert "\n" ";;;; End of " + (file-name-nondirectory jao-w3m-session-file) "\n") + (write-region (point-min) (point-max) (expand-file-name filename))) + (if is-auto (message msg)))) + +(defvar jao-w3m-session--timer nil) + +(defun jao-w3m-session--backup-name (fname) + (concat (expand-file-name fname) ".bak")) + +(defun jao-w3m-session--check--backup (fname) + (let ((bfname (jao-w3m-session--backup-name fname))) + (if (and (file-newer-than-file-p bfname fname) + (y-or-n-p "A newer autosaved session exists. Use it? ")) + bfname + fname))) + +(defun jao-w3m-session--restart--autosave () + (when (> jao-w3m-session-autosave-period 0) + (if jao-w3m-session--timer (cancel-timer jao-w3m-session--timer)) + (setq jao-w3m-session--timer + (run-at-time jao-w3m-session-autosave-period + jao-w3m-session-autosave-period + 'jao-w3m-session--to--file + (jao-w3m-session--backup-name jao-w3m-session-file) + t)))) + +(provide 'jao-w3m-session) + +;;; jao-w3m-session.el ends here -- cgit v1.2.3