* calendar/todos.el: Extend and improve item filtering and handling of
[bpt/emacs.git] / lisp / bookmark.el
index 2ce63fb..75a8d9f 100644 (file)
@@ -1,8 +1,6 @@
 ;;; bookmark.el --- set bookmarks, maybe annotate them, jump to them later
 
-;; Copyright (C) 1993, 1994, 1995, 1996, 1997, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009, 2010, 2011
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1993-1997, 2001-2012 Free Software Foundation, Inc.
 
 ;; Author: Karl Fogel <kfogel@red-bean.com>
 ;; Maintainer: Karl Fogel <kfogel@red-bean.com>
@@ -35,7 +33,7 @@
 ;;; Code:
 
 (require 'pp)
-(eval-when-compile (require 'cl))
+(eval-when-compile (require 'cl-lib))
 
 ;;; Misc comments:
 ;;
@@ -67,7 +65,7 @@
 --> t means save bookmarks when Emacs is killed.
 --> Otherwise, it should be a number that is the frequency with which
     the bookmark list is saved (i.e.: the number of times which
-    Emacs' bookmark list may be modified before it is automatically
+    Emacs's bookmark list may be modified before it is automatically
     saved.).  If it is a number, Emacs will also automatically save
     bookmarks when it is killed.
 
@@ -85,7 +83,7 @@ To specify the file in which to save them, modify the variable
   "The `.emacs.bmk' file used to be called this name.")
 
 
-;; defvarred to avoid a compilation warning:
+;; defvared to avoid a compilation warning:
 (defvar bookmark-file nil
   "Old name for `bookmark-default-file'.")
 
@@ -279,8 +277,8 @@ through a file easier.")
 (defvar bookmark-current-buffer nil
   "The buffer in which a bookmark is currently being set or renamed.
 Functions that insert strings into the minibuffer use this to know
-the source buffer for that information; see `bookmark-yank-word' and
-`bookmark-insert-current-bookmark' for example.")
+the source buffer for that information; see `bookmark-yank-word'
+for example.")
 
 
 (defvar bookmark-yank-point 0
@@ -475,6 +473,12 @@ equivalently just return ALIST without NAME.")
 (defun bookmark-make-record ()
   "Return a new bookmark record (NAME . ALIST) for the current location."
   (let ((record (funcall bookmark-make-record-function)))
+    ;; Set up defaults.
+    (bookmark-prop-set
+     record 'defaults
+     (delq nil (delete-dups (append (bookmark-prop-get record 'defaults)
+                                   (list bookmark-current-bookmark
+                                         (bookmark-buffer-name))))))
     ;; Set up default name.
     (if (stringp (car record))
         ;; The function already provided a default name.
@@ -740,10 +744,6 @@ This expects to be called from `point-min' in a bookmark file."
   (let ((map (make-sparse-keymap)))
     (set-keymap-parent map minibuffer-local-map)
     (define-key map "\C-w" 'bookmark-yank-word)
-    ;; This C-u binding might not be very useful any more now that we
-    ;; provide access to the default via the standard M-n binding.
-    ;; Maybe we should just remove it?  --Stef-08
-    (define-key map "\C-u" 'bookmark-insert-current-bookmark)
     map))
 
 ;;;###autoload
@@ -774,7 +774,19 @@ the list of bookmarks.)"
   (interactive (list nil current-prefix-arg))
   (unwind-protect
        (let* ((record (bookmark-make-record))
-              (default (car record)))
+              ;; `defaults' is a transient element of the
+              ;; extensible format described above in the section
+              ;; `File format stuff'.  Bookmark record functions
+              ;; can use it to specify a list of default values
+              ;; accessible via M-n while reading a bookmark name.
+              (defaults (bookmark-prop-get record 'defaults))
+              (default (if (consp defaults) (car defaults) defaults)))
+
+         (if defaults
+             ;; Don't store default values in the record.
+             (setq record (assq-delete-all 'defaults record))
+           ;; When no defaults in the record, use its first element.
+           (setq defaults (car record) default defaults))
 
          (bookmark-maybe-load-default-file)
          ;; Don't set `bookmark-yank-point' and `bookmark-current-buffer'
@@ -790,7 +802,7 @@ the list of bookmarks.)"
                      (format "Set bookmark (%s): " default)
                      nil
                      bookmark-minibuffer-read-name-map
-                     nil nil default))))
+                     nil nil defaults))))
            (and (string-equal str "") (setq str default))
            (bookmark-store str (cdr record) no-overwrite)
 
@@ -830,11 +842,11 @@ annotations."
          "#  Date:    " (current-time-string) "\n"))
 
 
+(define-obsolete-variable-alias 'bookmark-read-annotation-text-func
+  'bookmark-edit-annotation-text-func "23.1")
 (defvar bookmark-edit-annotation-text-func 'bookmark-default-annotation-text
   "Function to return default text to use for a bookmark annotation.
 It takes one argument, the name of the bookmark, as a string.")
-(define-obsolete-variable-alias 'bookmark-read-annotation-text-func
-  'bookmark-edit-annotation-text-func "23.1")
 
 (defvar bookmark-edit-annotation-mode-map
   (let ((map (make-sparse-keymap)))
@@ -890,18 +902,6 @@ Lines beginning with `#' are ignored."
   (bookmark-edit-annotation-mode bookmark-name-or-record))
 
 
-(defun bookmark-insert-current-bookmark ()
-  "Insert into the bookmark name currently being set the value of
-`bookmark-current-bookmark' in `bookmark-current-buffer', defaulting
-to the buffer's file name if `bookmark-current-bookmark' is nil."
-  (interactive)
-  (let ((str
-        (with-current-buffer bookmark-current-buffer
-          (or bookmark-current-bookmark
-               (bookmark-buffer-name)))))
-    (insert str)))
-
-
 (defun bookmark-buffer-name ()
   "Return the name of the current buffer in a form usable as a bookmark name.
 If the buffer is associated with a file or directory, use that name."
@@ -1060,7 +1060,7 @@ compatibility only."
 (defun bookmark-handle-bookmark (bookmark-name-or-record)
   "Call BOOKMARK-NAME-OR-RECORD's handler or `bookmark-default-handler'
 if it has none.  This changes current buffer and point and returns nil,
-or signals a `file-error'. 
+or signals a `file-error'.
 
 If BOOKMARK-NAME-OR-RECORD has no file, this is a no-op.  If
 BOOKMARK-NAME-OR-RECORD has a file, but that file no longer exists,
@@ -1477,8 +1477,7 @@ method buffers use to resolve name collisions."
 
 (defvar bookmark-bmenu-mode-map
   (let ((map (make-keymap)))
-    (suppress-keymap map t)
-    (define-key map "q" 'quit-window)
+    (set-keymap-parent map special-mode-map)
     (define-key map "v" 'bookmark-bmenu-select)
     (define-key map "w" 'bookmark-bmenu-locate)
     (define-key map "2" 'bookmark-bmenu-2-window)
@@ -1498,7 +1497,6 @@ method buffers use to resolve name collisions."
     (define-key map "n" 'next-line)
     (define-key map "p" 'previous-line)
     (define-key map "\177" 'bookmark-bmenu-backup-unmark)
-    (define-key map "?" 'describe-mode)
     (define-key map "u" 'bookmark-bmenu-unmark)
     (define-key map "m" 'bookmark-bmenu-mark)
     (define-key map "l" 'bookmark-bmenu-load)
@@ -1508,9 +1506,7 @@ method buffers use to resolve name collisions."
     (define-key map "a" 'bookmark-bmenu-show-annotation)
     (define-key map "A" 'bookmark-bmenu-show-all-annotations)
     (define-key map "e" 'bookmark-bmenu-edit-annotation)
-    ;; The original binding of M-g hides the M-g prefix map.
-    ;; If someone has a better idea than M-g s, I'm open to suggestions.
-    (define-key map [?\M-g ?s] 'bookmark-bmenu-search)
+    (define-key map "/" 'bookmark-bmenu-search)
     (define-key map [mouse-2] 'bookmark-bmenu-other-window-with-mouse)
     map))
 
@@ -1545,9 +1541,7 @@ deletion, or > if it is flagged for displaying."
   (bookmark-maybe-load-default-file)
   (let ((buf (get-buffer-create "*Bookmark List*")))
     (if (called-interactively-p 'interactive)
-        (if (or (window-dedicated-p) (window-minibuffer-p))
-            (pop-to-buffer buf)
-          (switch-to-buffer buf))
+        (switch-to-buffer buf)
       (set-buffer buf)))
   (let ((inhibit-read-only t))
     (erase-buffer)
@@ -1588,7 +1582,7 @@ deletion, or > if it is flagged for displaying."
 
 
 
-(defun bookmark-bmenu-mode ()
+(define-derived-mode bookmark-bmenu-mode special-mode "Bookmark Menu"
   "Major mode for editing a list of bookmarks.
 Each line describes one of the bookmarks in Emacs.
 Letters do not insert themselves; instead, they are commands.
@@ -1621,13 +1615,8 @@ Bookmark names preceded by a \"*\" have annotations.
   in another buffer.
 \\[bookmark-bmenu-show-all-annotations] -- show the annotations of all bookmarks in another buffer.
 \\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current bookmark."
-  (kill-all-local-variables)
-  (use-local-map bookmark-bmenu-mode-map)
   (setq truncate-lines t)
-  (setq buffer-read-only t)
-  (setq major-mode 'bookmark-bmenu-mode)
-  (setq mode-name "Bookmark Menu")
-  (run-mode-hooks 'bookmark-bmenu-mode-hook))
+  (setq buffer-read-only t))
 
 
 (defun bookmark-bmenu-toggle-filenames (&optional show)
@@ -1854,7 +1843,7 @@ With a prefix arg, prompts for a file to save them in."
         (menu (current-buffer))
         (pop-up-windows t))
     (delete-other-windows)
-    (switch-to-buffer (other-buffer))
+    (switch-to-buffer (other-buffer) nil t)
     (bookmark--jump-via bmrk 'pop-to-buffer)
     (bury-buffer menu)))
 
@@ -2028,11 +2017,11 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
         (tmp-list     ()))
     (while
         (let ((char (read-key (concat prompt bookmark-search-pattern))))
-          (case char
-            ((?\e ?\r) nil) ; RET or ESC break the search loop.
+          (pcase char
+            ((or ?\e ?\r) nil) ; RET or ESC break the search loop.
             (?\C-g (setq bookmark-quit-flag t) nil)
             (?\d (pop tmp-list) t) ; Delete last char of pattern with DEL
-            (t
+            (_
              (if (characterp char)
                  (push char tmp-list)
                (setq unread-command-events
@@ -2047,9 +2036,9 @@ To carry out the deletions that you've marked, use \\<bookmark-bmenu-mode-map>\\
 (defun bookmark-bmenu-filter-alist-by-regexp (regexp)
   "Filter `bookmark-alist' with bookmarks matching REGEXP and rebuild list."
   (let ((bookmark-alist
-         (loop for i in bookmark-alist
-               when (string-match regexp (car i)) collect i into new
-               finally return new)))
+         (cl-loop for i in bookmark-alist
+                  when (string-match regexp (car i)) collect i into new
+                  finally return new)))
     (bookmark-bmenu-list)))
 
 
@@ -2128,36 +2117,36 @@ strings returned are not."
 ;;;###autoload
 (defvar menu-bar-bookmark-map
   (let ((map (make-sparse-keymap "Bookmark functions")))
-    (define-key map [load]
-      `(menu-item ,(purecopy "Load a Bookmark File...") bookmark-load
-                 :help ,(purecopy "Load bookmarks from a bookmark file)")))
-    (define-key map [write]
-      `(menu-item ,(purecopy "Save Bookmarks As...") bookmark-write
-                 :help ,(purecopy "Write bookmarks to a file (reading the file name with the minibuffer)")))
-    (define-key map [save]
-      `(menu-item ,(purecopy "Save Bookmarks") bookmark-save
-                 :help ,(purecopy "Save currently defined bookmarks")))
-    (define-key map [edit]
-      `(menu-item ,(purecopy "Edit Bookmark List") bookmark-bmenu-list
-                 :help ,(purecopy "Display a list of existing bookmarks")))
-    (define-key map [delete]
-      `(menu-item ,(purecopy "Delete Bookmark...") bookmark-delete
-                 :help ,(purecopy "Delete a bookmark from the bookmark list")))
-    (define-key map [rename]
-      `(menu-item ,(purecopy "Rename Bookmark...") bookmark-rename
-                 :help ,(purecopy "Change the name of a bookmark")))
-    (define-key map [locate]
-      `(menu-item ,(purecopy "Insert Location...") bookmark-locate
-                 :help ,(purecopy "Insert the name of the file associated with a bookmark")))
-    (define-key map [insert]
-      `(menu-item ,(purecopy "Insert Contents...") bookmark-insert
-                 :help ,(purecopy "Insert the text of the file pointed to by a bookmark")))
-    (define-key map [set]
-      `(menu-item ,(purecopy "Set Bookmark...") bookmark-set
-                 :help ,(purecopy "Set a bookmark named inside a file.")))
-    (define-key map [jump]
-      `(menu-item ,(purecopy "Jump to Bookmark...") bookmark-jump
-                 :help ,(purecopy "Jump to a bookmark (a point in some file)")))
+    (bindings--define-key map [load]
+      '(menu-item "Load a Bookmark File..." bookmark-load
+                 :help "Load bookmarks from a bookmark file)"))
+    (bindings--define-key map [write]
+      '(menu-item "Save Bookmarks As..." bookmark-write
+                 :help "Write bookmarks to a file (reading the file name with the minibuffer)"))
+    (bindings--define-key map [save]
+      '(menu-item "Save Bookmarks" bookmark-save
+                 :help "Save currently defined bookmarks"))
+    (bindings--define-key map [edit]
+      '(menu-item "Edit Bookmark List" bookmark-bmenu-list
+                 :help "Display a list of existing bookmarks"))
+    (bindings--define-key map [delete]
+      '(menu-item "Delete Bookmark..." bookmark-delete
+                 :help "Delete a bookmark from the bookmark list"))
+    (bindings--define-key map [rename]
+      '(menu-item "Rename Bookmark..." bookmark-rename
+                 :help "Change the name of a bookmark"))
+    (bindings--define-key map [locate]
+      '(menu-item "Insert Location..." bookmark-locate
+                 :help "Insert the name of the file associated with a bookmark"))
+    (bindings--define-key map [insert]
+      '(menu-item "Insert Contents..." bookmark-insert
+                 :help "Insert the text of the file pointed to by a bookmark"))
+    (bindings--define-key map [set]
+      '(menu-item "Set Bookmark..." bookmark-set
+                 :help "Set a bookmark named inside a file."))
+    (bindings--define-key map [jump]
+      '(menu-item "Jump to Bookmark..." bookmark-jump
+                 :help "Jump to a bookmark (a point in some file)"))
     map))
 
 ;;;###autoload
@@ -2177,11 +2166,11 @@ strings returned are not."
   "Hook run at the end of loading library `bookmark.el'.")
 
 ;; Exit Hook, called from kill-emacs-hook
+(define-obsolete-variable-alias 'bookmark-exit-hooks
+  'bookmark-exit-hook "22.1")
 (defvar bookmark-exit-hook nil
   "Hook run when Emacs exits.")
 
-(define-obsolete-variable-alias 'bookmark-exit-hooks 'bookmark-exit-hook "22.1")
-
 (defun bookmark-exit-hook-internal ()
   "Save bookmark state, if necessary, at Emacs exit time.
 This also runs `bookmark-exit-hook'."
@@ -2190,7 +2179,8 @@ This also runs `bookmark-exit-hook'."
        (bookmark-time-to-save-p t)
        (bookmark-save)))
 
-(add-hook 'kill-emacs-hook 'bookmark-exit-hook-internal)
+(unless noninteractive
+  (add-hook 'kill-emacs-hook 'bookmark-exit-hook-internal))
 
 (defun bookmark-unload-function ()
   "Unload the Bookmark library."