]> code.delx.au - gnu-emacs/blobdiff - lisp/saveplace.el
Add more sanity checks to the last eww after-change-function patch
[gnu-emacs] / lisp / saveplace.el
index 9c3ce077b7ae9d088232caa061ed92aad803376f..a25dba2e39ecf6d658f60233401d747ba6953985 100644 (file)
@@ -1,9 +1,9 @@
 ;;; saveplace.el --- automatically save place in files
 
 ;;; saveplace.el --- automatically save place in files
 
-;; Copyright (C) 1993-1994, 2001-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2001-2014 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
-;; Maintainer: FSF
+;; Maintainer: emacs-devel@gnu.org
 ;; Created: July, 1993
 ;; Keywords: bookmarks, placeholders
 
 ;; Created: July, 1993
 ;; Keywords: bookmarks, placeholders
 
@@ -54,23 +54,22 @@ This alist is saved between Emacs sessions.")
   "Non-nil means automatically save place in each file.
 This means when you visit a file, point goes to the last place
 where it was when you previously visited the same file.
   "Non-nil means automatically save place in each file.
 This means when you visit a file, point goes to the last place
 where it was when you previously visited the same file.
-This variable is automatically buffer-local.
 
 
-If you wish your place in any file to always be automatically saved,
-simply put this in your `~/.emacs' file:
+If you wish your place in any file to always be automatically
+saved, set this to t using the Customize facility, or put the
+following code in your init file:
 
 \(setq-default save-place t)
 
 \(setq-default save-place t)
-\(require 'saveplace)
-
-or else use the Custom facility to set this option."
+\(require 'saveplace)"
   :type 'boolean
   :require 'saveplace
   :group 'save-place)
 
 (make-variable-buffer-local 'save-place)
 
   :type 'boolean
   :require 'saveplace
   :group 'save-place)
 
 (make-variable-buffer-local 'save-place)
 
-(defcustom save-place-file (convert-standard-filename "~/.emacs-places")
+(defcustom save-place-file (locate-user-emacs-file "places" ".emacs-places")
   "Name of the file that records `save-place-alist' value."
   "Name of the file that records `save-place-alist' value."
+  :version "24.4"                       ; added locate-user-emacs-file
   :type 'file
   :group 'save-place)
 
   :type 'file
   :group 'save-place)
 
@@ -101,7 +100,7 @@ value of `version-control'."
 
 The filenames in `save-place-alist' that do not match
 `save-place-skip-check-regexp' are filtered through
 
 The filenames in `save-place-alist' that do not match
 `save-place-skip-check-regexp' are filtered through
-`file-readable-p'. if nil, their alist entries are removed.
+`file-readable-p'.  If nil, their alist entries are removed.
 
 You may do this anytime by calling the complementary function,
 `save-place-forget-unreadable-files'.  When this option is turned on,
 
 You may do this anytime by calling the complementary function,
 `save-place-forget-unreadable-files'.  When this option is turned on,
@@ -132,9 +131,10 @@ removable and network volumes."
 
 (defcustom save-place-ignore-files-regexp
   "\\(?:COMMIT_EDITMSG\\|hg-editor-[[:alnum:]]+\\.txt\\|svn-commit\\.tmp\\|bzr_log\\.[[:alnum:]]+\\)$"
 
 (defcustom save-place-ignore-files-regexp
   "\\(?:COMMIT_EDITMSG\\|hg-editor-[[:alnum:]]+\\.txt\\|svn-commit\\.tmp\\|bzr_log\\.[[:alnum:]]+\\)$"
-  "Regexp matching files for which no location should be recorded.
+  "Regexp matching files for which no position should be recorded.
 Useful for temporary file such as commit message files that are
 Useful for temporary file such as commit message files that are
-automatically created by the VCS."
+automatically created by the VCS.  If set to nil, this feature is
+disabled, i.e., the position is recorded for all files."
   :version "24.1"
   :type 'regexp :group 'save-place)
 
   :version "24.1"
   :type 'regexp :group 'save-place)
 
@@ -147,18 +147,22 @@ even in a later Emacs session.
 If called with a prefix arg, the mode is enabled if and only if
 the argument is positive.
 
 If called with a prefix arg, the mode is enabled if and only if
 the argument is positive.
 
-To save places automatically in all files, put this in your `.emacs' file:
+To save places automatically in all files, put this in your init
+file:
 
 
-\(setq-default save-place t\)"
+\(setq-default save-place t)"
   (interactive "P")
   (interactive "P")
-  (if (not buffer-file-name)
-      (message "Buffer `%s' not visiting a file" (buffer-name))
-    (if (and save-place (or (not parg) (<= parg 0)))
-       (progn
-         (message "No place will be saved in this file")
-         (setq save-place nil))
-      (message "Place will be saved")
-      (setq save-place t))))
+  (if (not (or buffer-file-name (and (derived-mode-p 'dired-mode)
+                                    dired-directory)))
+      (message "Buffer `%s' not visiting a file or directory" (buffer-name))
+    (setq save-place (if parg
+                         (> (prefix-numeric-value parg) 0)
+                       (not save-place)))
+    (message (if save-place
+                 "Place will be saved"
+               "No place will be saved in this file"))))
+
+(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
 
 (defun save-place-to-alist ()
   ;; put filename and point in a cons box and then cons that onto the
 
 (defun save-place-to-alist ()
   ;; put filename and point in a cons box and then cons that onto the
@@ -168,27 +172,41 @@ To save places automatically in all files, put this in your `.emacs' file:
   ;; file.  If not, do so, then feel free to modify the alist.  It
   ;; will be saved again when Emacs is killed.
   (or save-place-loaded (load-save-place-alist-from-file))
   ;; file.  If not, do so, then feel free to modify the alist.  It
   ;; will be saved again when Emacs is killed.
   (or save-place-loaded (load-save-place-alist-from-file))
-  (when (and buffer-file-name
-            (not (string-match save-place-ignore-files-regexp
-                               buffer-file-name)))
-    (let ((cell (assoc buffer-file-name save-place-alist))
-         (position (if (not (eq major-mode 'hexl-mode))
-                       (point)
-                     (with-no-warnings
-                       (1+ (hexl-current-address))))))
-      (if cell
-         (setq save-place-alist (delq cell save-place-alist)))
-      (if (and save-place
-              (not (= position 1)))  ;; Optimize out the degenerate case.
-         (setq save-place-alist
-               (cons (cons buffer-file-name position)
-                     save-place-alist))))))
+  (let ((item (or buffer-file-name
+                  (and (derived-mode-p 'dired-mode)
+                      dired-directory
+                      (expand-file-name (if (consp dired-directory)
+                                            (car dired-directory)
+                                          dired-directory))))))
+    (when (and item
+               (or (not save-place-ignore-files-regexp)
+                   (not (string-match save-place-ignore-files-regexp
+                                      item))))
+      (let ((cell (assoc item save-place-alist))
+            (position (cond ((eq major-mode 'hexl-mode)
+                            (with-no-warnings
+                              (1+ (hexl-current-address))))
+                           ((and (derived-mode-p 'dired-mode)
+                                 dired-directory)
+                            (let ((filename (dired-get-filename nil t)))
+                              (if filename
+                                  `((dired-filename . ,filename))
+                                (point))))
+                           (t (point)))))
+        (if cell
+            (setq save-place-alist (delq cell save-place-alist)))
+        (if (and save-place
+                 (not (and (integerp position)
+                          (= position 1)))) ;; Optimize out the degenerate case.
+            (setq save-place-alist
+                  (cons (cons item position)
+                        save-place-alist)))))))
 
 (defun save-place-forget-unreadable-files ()
   "Remove unreadable files from `save-place-alist'.
 For each entry in the alist, if `file-readable-p' returns nil for the
 
 (defun save-place-forget-unreadable-files ()
   "Remove unreadable files from `save-place-alist'.
 For each entry in the alist, if `file-readable-p' returns nil for the
-filename, remove the entry.  Save the new alist \(as the first pair
-may have changed\) back to `save-place-alist'."
+filename, remove the entry.  Save the new alist (as the first pair
+may have changed) back to `save-place-alist'."
   (interactive)
   ;; the following was adapted from an in-place filtering function,
   ;; `filter-mod', used in the original.
   (interactive)
   ;; the following was adapted from an in-place filtering function,
   ;; `filter-mod', used in the original.
@@ -222,9 +240,7 @@ may have changed\) back to `save-place-alist'."
                       (symbol-name coding-system-for-write)))
       (let ((print-length nil)
             (print-level nil))
                       (symbol-name coding-system-for-write)))
       (let ((print-length nil)
             (print-level nil))
-        (pp (sort save-place-alist
-                  (lambda (a b) (string< (car a) (car b))))
-            (current-buffer)))
+        (pp save-place-alist (current-buffer)))
       (let ((version-control
              (cond
               ((null save-place-version-control) nil)
       (let ((version-control
              (cond
               ((null save-place-version-control) nil)
@@ -253,8 +269,9 @@ may have changed\) back to `save-place-alist'."
                 (insert-file-contents file)
                 (goto-char (point-min))
                 (setq save-place-alist
                 (insert-file-contents file)
                 (goto-char (point-min))
                 (setq save-place-alist
-                      (car (read-from-string
-                            (buffer-substring (point-min) (point-max)))))
+                      (with-demoted-errors "Error reading save-place-file: %S"
+                        (car (read-from-string
+                              (buffer-substring (point-min) (point-max))))))
 
                 ;; If there is a limit, and we're over it, then we'll
                 ;; have to truncate the end of the list:
 
                 ;; If there is a limit, and we're over it, then we'll
                 ;; have to truncate the end of the list:
@@ -287,7 +304,9 @@ may have changed\) back to `save-place-alist'."
       (with-current-buffer (car buf-list)
        ;; save-place checks buffer-file-name too, but we can avoid
        ;; overhead of function call by checking here too.
       (with-current-buffer (car buf-list)
        ;; save-place checks buffer-file-name too, but we can avoid
        ;; overhead of function call by checking here too.
-       (and buffer-file-name (save-place-to-alist))
+       (and (or buffer-file-name (and (derived-mode-p 'dired-mode)
+                                      dired-directory))
+            (save-place-to-alist))
        (setq buf-list (cdr buf-list))))))
 
 (defun save-place-find-file-hook ()
        (setq buf-list (cdr buf-list))))))
 
 (defun save-place-find-file-hook ()
@@ -296,7 +315,29 @@ may have changed\) back to `save-place-alist'."
     (if cell
        (progn
          (or revert-buffer-in-progress-p
     (if cell
        (progn
          (or revert-buffer-in-progress-p
-             (goto-char (cdr cell)))
+             (and (integerp (cdr cell))
+                  (goto-char (cdr cell))))
+          ;; and make sure it will be saved again for later
+          (setq save-place t)))))
+
+(declare-function dired-goto-file "dired" (file))
+
+(defun save-place-dired-hook ()
+  "Position the point in a Dired buffer."
+  (or save-place-loaded (load-save-place-alist-from-file))
+  (let ((cell (assoc (and (derived-mode-p 'dired-mode)
+                         dired-directory
+                         (expand-file-name (if (consp dired-directory)
+                                               (car dired-directory)
+                                             dired-directory)))
+                    save-place-alist)))
+    (if cell
+        (progn
+          (or revert-buffer-in-progress-p
+              (if (integerp (cdr cell))
+                 (goto-char (cdr cell))
+               (and (assq 'dired-filename (cdr cell))
+                    (dired-goto-file (cdr (assq 'dired-filename (cdr cell)))))))
           ;; and make sure it will be saved again for later
           (setq save-place t)))))
 
           ;; and make sure it will be saved again for later
           (setq save-place t)))))
 
@@ -310,6 +351,8 @@ may have changed\) back to `save-place-alist'."
 
 (add-hook 'find-file-hook 'save-place-find-file-hook t)
 
 
 (add-hook 'find-file-hook 'save-place-find-file-hook t)
 
+(add-hook 'dired-initial-position-hook 'save-place-dired-hook)
+
 (unless noninteractive
   (add-hook 'kill-emacs-hook 'save-place-kill-emacs-hook))
 
 (unless noninteractive
   (add-hook 'kill-emacs-hook 'save-place-kill-emacs-hook))