]> code.delx.au - gnu-emacs/blobdiff - lisp/url/url-history.el
(url-handler-unhandled-file-name-directory):
[gnu-emacs] / lisp / url / url-history.el
index 040f83ad2f2a41bd7d04a6f57bac881d616b63f8..6650ae74756068d3392a7e0b52a8b4f51c325015 100644 (file)
@@ -1,6 +1,7 @@
 ;;; url-history.el --- Global history tracking for URL package
 
-;; Copyright (c) 1996 - 1999,2004  Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2004,
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Keywords: comm, data, processes, hypermedia
 
@@ -8,7 +9,7 @@
 ;;
 ;; GNU Emacs 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 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 ;;
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -27,7 +28,6 @@
 
 ;; This can get a recursive require.
 ;;(require 'url)
-(eval-when-compile (require 'cl))
 (require 'url-parse)
 (autoload 'url-do-setup "url")
 
   :group 'url)
 
 (defcustom url-history-track nil
-  "*Controls whether to keep a list of all the URLS being visited.
-If non-nil, url will keep track of all the URLS visited.
+  "*Controls whether to keep a list of all the URLs being visited.
+If non-nil, the URL package will keep track of all the URLs visited.
 If set to t, then the list is saved to disk at the end of each Emacs
 session."
-  :type 'boolean
+  :set #'(lambda (var val)
+          (set-default var val)
+          (and (bound-and-true-p url-setup-done)
+               (url-history-setup-save-timer)))
+  :type '(choice (const :tag "off" nil)
+                (const :tag "on" t)
+                (const :tag "within session" 'session))
   :group 'url-history)
 
 (defcustom url-history-file nil
@@ -56,141 +62,125 @@ is parsed at startup and used to provide URL completion."
 Default is 1 hour.  Note that if you change this variable outside of
 the `customize' interface after `url-do-setup' has been run, you need
 to run the `url-history-setup-save-timer' function manually."
-  :set (function (lambda (var val)
-                  (set-default var val)
-                  (and (featurep 'url)
-                       (fboundp 'url-history-setup-save-timer)
-                        (let ((def (symbol-function
-                                    'url-history-setup-save-timer)))
-                          (not (and (listp def) (eq 'autoload (car def)))))
-                       (url-history-setup-save-timer))))
+  :set #'(lambda (var val)
+          (set-default var val)
+          (if (bound-and-true-p url-setup-done)
+              (url-history-setup-save-timer)))
   :type 'integer
   :group 'url-history)
 
 (defvar url-history-timer nil)
 
-(defvar url-history-list nil
-  "List of urls visited this session.")
-
 (defvar url-history-changed-since-last-save nil
   "Whether the history list has changed since the last save operation.")
 
-(defvar url-history-hash-table nil
+(defvar url-history-hash-table (make-hash-table :size 31 :test 'equal)
   "Hash table for global history completion.")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;;;###autoload
 (defun url-history-setup-save-timer ()
   "Reset the history list timer."
   (interactive)
-  (ignore-errors
-    (cond ((fboundp 'cancel-timer) (cancel-timer url-history-timer))
-         ((fboundp 'delete-itimer) (delete-itimer url-history-timer))))
+  (condition-case nil
+      (cancel-timer url-history-timer)
+    (error nil))
   (setq url-history-timer nil)
-  (if url-history-save-interval
-      (setq url-history-timer
-           (cond
-            ((fboundp 'run-at-time)
-             (run-at-time url-history-save-interval
-                          url-history-save-interval
-                          'url-history-save-history))
-            ((fboundp 'start-itimer)
-             (start-itimer "url-history-saver" 'url-history-save-history
-                           url-history-save-interval
-                           url-history-save-interval))))))
-
-;;;###autoload
+  (if (and (eq url-history-track t) url-history-save-interval)
+      (setq url-history-timer (run-at-time url-history-save-interval
+                                          url-history-save-interval
+                                          'url-history-save-history))))
+
 (defun url-history-parse-history (&optional fname)
   "Parse a history file stored in FNAME."
   ;; Parse out the mosaic global history file for completions, etc.
   (or fname (setq fname (expand-file-name url-history-file)))
   (cond
    ((not (file-exists-p fname))
-    (message "%s does not exist." fname))
+    ;; It's completely normal for this file not to exist, so don't complain.
+    ;; (message "%s does not exist." fname)
+    )
    ((not (file-readable-p fname))
     (message "%s is unreadable." fname))
    (t
     (condition-case nil
        (load fname nil t)
-      (error (message "Could not load %s" fname)))))
-  (if (not url-history-hash-table)
-      (setq url-history-hash-table (make-hash-table :size 31 :test 'equal))))
+      (error (message "Could not load %s" fname))))))
 
 (defun url-history-update-url (url time)
   (setq url-history-changed-since-last-save t)
-  (puthash (if (vectorp url) (url-recreate-url url) url) time url-history-hash-table))
+  (puthash (if (vectorp url) (url-recreate-url url) url) time
+           url-history-hash-table))
+
+(autoload 'url-make-private-file "url-util")
 
-;;;###autoload
 (defun url-history-save-history (&optional fname)
   "Write the global history file into `url-history-file'.
 The type of data written is determined by what is in the file to begin
 with.  If the type of storage cannot be determined, then prompt the
 user for what type to save as."
   (interactive)
-  (or fname (setq fname (expand-file-name url-history-file)))
-  (cond
-   ((not url-history-changed-since-last-save) nil)
-   ((not (file-writable-p fname))
-    (message "%s is unwritable." fname))
-   (t
-    (let ((make-backup-files nil)
-         (version-control nil)
-         (require-final-newline t))
-      (save-excursion
-       (set-buffer (get-buffer-create " *url-tmp*"))
-       (erase-buffer)
-       (let ((count 0))
-         (maphash (function
-                      (lambda (key value)
-                        (while (string-match "[\r\n]+" key)
-                          (setq key (concat (substring key 0 (match-beginning 0))
-                                            (substring key (match-end 0) nil))))
-                        (setq count (1+ count))
-                        (insert "(puthash \"" key "\""
-                                (if (not (stringp value)) " '" "")
-                                (prin1-to-string value)
-                                " url-history-hash-table)\n")))
-                     url-history-hash-table)
-         (goto-char (point-min))
-         (insert (format
-                  "(setq url-history-hash-table (make-hash-table :size %d :test 'equal))\n"
-                  (/ count 4)))
-         (goto-char (point-max))
+  (when url-history-changed-since-last-save
+    (or fname (setq fname (expand-file-name url-history-file)))
+    (if (condition-case nil
+            (progn
+              (url-make-private-file fname)
+              nil)
+          (error t))
+        (message "Error accessing history file `%s'" fname)
+      (let ((make-backup-files nil)
+            (version-control nil)
+            (require-final-newline t)
+            (count 0))
+        (with-temp-buffer
+          (maphash (lambda (key value)
+                     (while (string-match "[\r\n]+" key)
+                       (setq key (concat (substring key 0 (match-beginning 0))
+                                         (substring key (match-end 0) nil))))
+                     (setq count (1+ count))
+                     (insert "(puthash \"" key "\""
+                             (if (not (stringp value)) " '" "")
+                             (prin1-to-string value)
+                             " url-history-hash-table)\n"))
+                   url-history-hash-table)
+          ;; We used to add this in the file, but it just makes the code
+          ;; more complex with no benefit.  Worse: it makes it harder to
+          ;; preserve preexisting history when loading the history file.
+         ;; (goto-char (point-min))
+         ;; (insert (format
+         ;;          "(setq url-history-hash-table (make-hash-table :size %d :test 'equal))\n"
+         ;;          (/ count 4)))
+         ;; (goto-char (point-max))
          (insert "\n")
-         (write-file fname))
-       (kill-buffer (current-buffer))))))
-  (setq url-history-changed-since-last-save nil))
+         (write-file fname)))
+      (setq url-history-changed-since-last-save nil))))
 
 (defun url-have-visited-url (url)
   (url-do-setup)
-  (and url-history-hash-table
-       (gethash url url-history-hash-table nil)))
+  (gethash url url-history-hash-table nil))
 
 (defun url-completion-function (string predicate function)
+  ;; Completion function to complete urls from the history.
+  ;; This is obsolete since we can now pass the hash-table directly as a
+  ;; completion table.
   (url-do-setup)
   (cond
    ((eq function nil)
     (let ((list nil))
-      (maphash (function (lambda (key val)
-                             (setq list (cons (cons key val)
-                                              list))))
-                 url-history-hash-table)
+      (maphash (lambda (key val) (push key list))
+               url-history-hash-table)
+      ;; Not sure why we bother reversing the list.  --Stef
       (try-completion string (nreverse list) predicate)))
    ((eq function t)
-    (let ((stub (concat "^" (regexp-quote string)))
+    (let ((stub (concat "\\`" (regexp-quote string)))
          (retval nil))
       (maphash
-       (function
-       (lambda (url time)
-         (if (string-match stub url)
-             (setq retval (cons url retval)))))
+       (lambda (url time)
+         (if (string-match stub url) (push url retval)))
        url-history-hash-table)
       retval))
    ((eq function 'lambda)
-    (and url-history-hash-table
-        (gethash string url-history-hash-table)
-        t))
+    (and (gethash string url-history-hash-table) t))
    (t
     (error "url-completion-function very confused"))))