54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
1 ;;; url-history.el --- Global history tracking for URL package
|
54797
|
2
|
64748
|
3 ;; Copyright (C) 1996, 1997, 1998, 1999, 2004,
|
75347
|
4 ;; 2005, 2006, 2007 Free Software Foundation, Inc.
|
54797
|
5
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
6 ;; Keywords: comm, data, processes, hypermedia
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
7
|
54797
|
8 ;; This file is part of GNU Emacs.
|
|
9 ;;
|
|
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
11 ;; it under the terms of the GNU General Public License as published by
|
78222
|
12 ;; the Free Software Foundation; either version 3, or (at your option)
|
54797
|
13 ;; any later version.
|
|
14 ;;
|
|
15 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
18 ;; GNU General Public License for more details.
|
|
19 ;;
|
|
20 ;; You should have received a copy of the GNU General Public License
|
|
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
|
64084
|
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
23 ;; Boston, MA 02110-1301, USA.
|
54797
|
24
|
|
25 ;;; Commentary:
|
|
26
|
|
27 ;;; Code:
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
28
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
29 ;; This can get a recursive require.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
30 ;;(require 'url)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
31 (eval-when-compile (require 'cl))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
32 (require 'url-parse)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
33 (autoload 'url-do-setup "url")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
34
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
35 (defgroup url-history nil
|
63991
|
36 "History variables in the URL package."
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
37 :prefix "url-history"
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
38 :group 'url)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
39
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
40 (defcustom url-history-track nil
|
67237
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
41 "*Controls whether to keep a list of all the URLs being visited.
|
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
42 If non-nil, the URL package will keep track of all the URLs visited.
|
63991
|
43 If set to t, then the list is saved to disk at the end of each Emacs
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
44 session."
|
67237
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
45 :set #'(lambda (var val)
|
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
46 (set-default var val)
|
67240
|
47 (and (bound-and-true-p url-setup-done)
|
67237
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
48 (url-history-setup-save-timer)))
|
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
49 :type '(choice (const :tag "off" nil)
|
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
50 (const :tag "on" t)
|
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
51 (const :tag "within session" 'session))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
52 :group 'url-history)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
53
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
54 (defcustom url-history-file nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
55 "*The global history file for the URL package.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
56 This file contains a list of all the URLs you have visited. This file
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
57 is parsed at startup and used to provide URL completion."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
58 :type '(choice (const :tag "Default" :value nil) file)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
59 :group 'url-history)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
60
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
61 (defcustom url-history-save-interval 3600
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
62 "*The number of seconds between automatic saves of the history list.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
63 Default is 1 hour. Note that if you change this variable outside of
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
64 the `customize' interface after `url-do-setup' has been run, you need
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
65 to run the `url-history-setup-save-timer' function manually."
|
67310
|
66 :set #'(lambda (var val)
|
|
67 (set-default var val)
|
|
68 (if (bound-and-true-p url-setup-done)
|
|
69 (url-history-setup-save-timer)))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
70 :type 'integer
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
71 :group 'url-history)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
72
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
73 (defvar url-history-timer nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
74
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
75 (defvar url-history-changed-since-last-save nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
76 "Whether the history list has changed since the last save operation.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
77
|
68056
|
78 (defvar url-history-hash-table (make-hash-table :size 31 :test 'equal)
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
79 "Hash table for global history completion.")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
80
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
81 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
54797
|
82
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
83 (defun url-history-setup-save-timer ()
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
84 "Reset the history list timer."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
85 (interactive)
|
63416
|
86 (ignore-errors
|
67310
|
87 (cancel-timer url-history-timer))
|
54797
|
88 (setq url-history-timer nil)
|
67237
40f77d1e999e
(url-history-track): Call url-history-setup-save-timer in :set function.
Richard M. Stallman <rms@gnu.org>
diff
changeset
|
89 (if (and (eq url-history-track t) url-history-save-interval)
|
67310
|
90 (setq url-history-timer (run-at-time url-history-save-interval
|
|
91 url-history-save-interval
|
|
92 'url-history-save-history))))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
93
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
94 (defun url-history-parse-history (&optional fname)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
95 "Parse a history file stored in FNAME."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
96 ;; Parse out the mosaic global history file for completions, etc.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
97 (or fname (setq fname (expand-file-name url-history-file)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
98 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
99 ((not (file-exists-p fname))
|
68054
30042a8370ce
(url-history-parse-history): Don't complain if the file is missing.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
100 ;; It's completely normal for this file not to exist, so don't complain.
|
30042a8370ce
(url-history-parse-history): Don't complain if the file is missing.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
101 ;; (message "%s does not exist." fname)
|
30042a8370ce
(url-history-parse-history): Don't complain if the file is missing.
Stefan Monnier <monnier@iro.umontreal.ca>
diff
changeset
|
102 )
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
103 ((not (file-readable-p fname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
104 (message "%s is unreadable." fname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
105 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
106 (condition-case nil
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
107 (load fname nil t)
|
68056
|
108 (error (message "Could not load %s" fname))))))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
109
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
110 (defun url-history-update-url (url time)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
111 (setq url-history-changed-since-last-save t)
|
68056
|
112 (puthash (if (vectorp url) (url-recreate-url url) url) time
|
|
113 url-history-hash-table))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
114
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
115 (defun url-history-save-history (&optional fname)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
116 "Write the global history file into `url-history-file'.
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
117 The type of data written is determined by what is in the file to begin
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
118 with. If the type of storage cannot be determined, then prompt the
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
119 user for what type to save as."
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
120 (interactive)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
121 (or fname (setq fname (expand-file-name url-history-file)))
|
68056
|
122 (unless (file-directory-p (file-name-directory fname))
|
|
123 (ignore-errors (make-directory (file-name-directory fname))))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
124 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
125 ((not url-history-changed-since-last-save) nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
126 ((not (file-writable-p fname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
127 (message "%s is unwritable." fname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
128 (t
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
129 (let ((make-backup-files nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
130 (version-control nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
131 (require-final-newline t))
|
68056
|
132 (with-current-buffer (get-buffer-create " *url-tmp*")
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
133 (erase-buffer)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
134 (let ((count 0))
|
68056
|
135 (maphash (lambda (key value)
|
|
136 (while (string-match "[\r\n]+" key)
|
|
137 (setq key (concat (substring key 0 (match-beginning 0))
|
|
138 (substring key (match-end 0) nil))))
|
|
139 (setq count (1+ count))
|
|
140 (insert "(puthash \"" key "\""
|
|
141 (if (not (stringp value)) " '" "")
|
|
142 (prin1-to-string value)
|
|
143 " url-history-hash-table)\n"))
|
|
144 url-history-hash-table)
|
|
145 ;; We used to add this in the file, but it just makes the code
|
|
146 ;; more complex with no benefit. Worse: it makes it harder to
|
|
147 ;; preserve preexisting history when loading the history file.
|
|
148 ;; (goto-char (point-min))
|
|
149 ;; (insert (format
|
|
150 ;; "(setq url-history-hash-table (make-hash-table :size %d :test 'equal))\n"
|
|
151 ;; (/ count 4)))
|
|
152 ;; (goto-char (point-max))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
153 (insert "\n")
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
154 (write-file fname))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
155 (kill-buffer (current-buffer))))))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
156 (setq url-history-changed-since-last-save nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
157
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
158 (defun url-have-visited-url (url)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
159 (url-do-setup)
|
68056
|
160 (gethash url url-history-hash-table nil))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
161
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
162 (defun url-completion-function (string predicate function)
|
68056
|
163 ;; Completion function to complete urls from the history.
|
|
164 ;; This is obsolete since we can now pass the hash-table directly as a
|
|
165 ;; completion table.
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
166 (url-do-setup)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
167 (cond
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
168 ((eq function nil)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
169 (let ((list nil))
|
68056
|
170 (maphash (lambda (key val) (push key list))
|
|
171 url-history-hash-table)
|
|
172 ;; Not sure why we bother reversing the list. --Stef
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
173 (try-completion string (nreverse list) predicate)))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
174 ((eq function t)
|
68056
|
175 (let ((stub (concat "\\`" (regexp-quote string)))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
176 (retval nil))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
177 (maphash
|
68056
|
178 (lambda (url time)
|
|
179 (if (string-match stub url) (push url retval)))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
180 url-history-hash-table)
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
181 retval))
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
182 ((eq function 'lambda)
|
68056
|
183 (and (gethash string url-history-hash-table) t))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
184 (t
|
63416
|
185 (error "url-completion-function very confused"))))
|
54695
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
186
|
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
diff
changeset
|
187 (provide 'url-history)
|
54699
|
188
|
54797
|
189 ;; arch-tag: fbbbaf63-db36-4e88-bc9f-2939aa93afb2
|
|
190 ;;; url-history.el ends here
|