nnimap.el (nnimap-open-connection): Look for the "imaps" entry in the .authinfo if...
[bpt/emacs.git] / lisp / ido.el
index 8e99834..858ee3e 100644 (file)
@@ -1,7 +1,7 @@
 ;;; ido.el --- interactively do things with buffers and files.
 
 ;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-;;   2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+;;   2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Kim F. Storm <storm@cua.dk>
 ;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
 
 ;;; Code:
 
-(defvar cua-inhibit-cua-keys)
+(defvar recentf-list)
 
 ;;; User Variables
 ;;
@@ -366,16 +366,6 @@ use either \\[customize] or the function `ido-mode'."
                  (const :tag "Switch off all" nil))
   :group 'ido)
 
-(defcustom ido-everywhere nil
-  "Use ido everywhere for reading file names and directories.
-Setting this variable directly does not work.  Use `customize' or
-call the function `ido-everywhere'."
-  :set #'(lambda (symbol value)
-          (ido-everywhere (if value 1 -1)))
-  :initialize 'custom-initialize-default
-  :type 'boolean
-  :group 'ido)
-
 (defcustom ido-case-fold case-fold-search
   "Non-nil if searching of buffer and file names should ignore case."
   :type 'boolean
@@ -770,7 +760,7 @@ Obsolete.  Set 3rd element of `ido-decorations' instead."
 
 (defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")
   "List of strings used by ido to display the alternatives in the minibuffer.
-There are 10 elements in this list:
+There are 11 elements in this list:
 1st and 2nd elements are used as brackets around the prospect list,
 3rd element is the separator between prospects (ignored if `ido-separator' is set),
 4th element is the string inserted at the end of a truncated list of prospects,
@@ -784,6 +774,24 @@ can be completed using TAB,
   :type '(repeat string)
   :group 'ido)
 
+(defcustom ido-use-virtual-buffers nil
+  "If non-nil, refer to past buffers as well as existing ones.
+Essentially it works as follows: Say you are visiting a file and
+the buffer gets cleaned up by mignight.el.  Later, you want to
+switch to that buffer, but find it's no longer open.  With
+virtual buffers enabled, the buffer name stays in the buffer
+list (using the `ido-virtual' face, and always at the end), and if
+you select it, it opens the file back up again.  This allows you
+to think less about whether recently opened files are still open
+or not.  Most of the time you can quit Emacs, restart, and then
+switch to a file buffer that was previously open as if it still
+were.
+    This feature relies upon the `recentf' package, which will be
+enabled if this variable is configured to a non-nil value."
+  :version "24.1"
+  :type 'boolean
+  :group 'ido)
+
 (defcustom ido-use-faces t
   "Non-nil means use ido faces to highlighting first match, only match and
 subdirs in the alternatives."
@@ -808,6 +816,11 @@ subdirs in the alternatives."
   "Face used by ido for highlighting subdirs in the alternatives."
   :group 'ido)
 
+(defface ido-virtual '((t (:inherit font-lock-builtin-face)))
+  "Face used by ido for matching virtual buffer names."
+  :version "24.1"
+  :group 'ido)
+
 (defface ido-indicator  '((((min-colors 88) (class color))
                                (:foreground "yellow1"
                                 :background "red1"
@@ -1040,6 +1053,11 @@ so that it doesn't interfere with other minibuffer usage.")
   "Non-nil means to explicitly cursor on entry to minibuffer.
 Value is an integer which is number of chars to right of prompt.")
 
+(defvar ido-virtual-buffers nil
+  "List of virtual buffers, that is, past visited files.
+This is a copy of `recentf-list', pared down and with faces applied.
+Only used if `ido-use-virtual-buffers' is non-nil.")
+
 ;;; Variables with dynamic bindings.
 ;;; Declared here to keep the byte compiler quiet.
 
@@ -1449,6 +1467,25 @@ Removes badly formatted data and ignored directories."
   ;; ido kill emacs hook
   (ido-save-history))
 
+(define-minor-mode ido-everywhere
+  "Toggle using ido speed-ups everywhere file and directory names are read.
+With ARG, turn ido speed-up on if arg is positive, off otherwise."
+  :global t
+  :group 'ido
+  (when (get 'ido-everywhere 'file)
+    (setq read-file-name-function (car (get 'ido-everywhere 'file)))
+    (put 'ido-everywhere 'file nil))
+  (when (get 'ido-everywhere 'buffer)
+    (setq read-buffer-function (car (get 'ido-everywhere 'buffer)))
+    (put 'ido-everywhere 'buffer nil))
+  (when ido-everywhere
+    (when (memq ido-mode '(both file))
+      (put 'ido-everywhere 'file (cons read-file-name-function nil))
+      (setq read-file-name-function 'ido-read-file-name))
+    (when (memq ido-mode '(both buffer))
+      (put 'ido-everywhere 'buffer (cons read-buffer-function nil))
+      (setq read-buffer-function 'ido-read-buffer))))
+
 (defvar ido-minor-mode-map-entry nil)
 
 ;;;###autoload
@@ -1492,15 +1529,21 @@ This function also adds a hook to the minibuffer."
        (define-key map [remap insert-file] 'ido-insert-file)
        (define-key map [remap list-directory] 'ido-list-directory)
        (define-key map [remap dired] 'ido-dired)
-       (define-key map [remap find-file-other-window] 'ido-find-file-other-window)
-       (define-key map [remap find-file-read-only-other-window] 'ido-find-file-read-only-other-window)
-       (define-key map [remap find-file-other-frame] 'ido-find-file-other-frame)
-       (define-key map [remap find-file-read-only-other-frame] 'ido-find-file-read-only-other-frame))
+       (define-key map [remap find-file-other-window]
+          'ido-find-file-other-window)
+       (define-key map [remap find-file-read-only-other-window]
+          'ido-find-file-read-only-other-window)
+       (define-key map [remap find-file-other-frame]
+          'ido-find-file-other-frame)
+       (define-key map [remap find-file-read-only-other-frame]
+          'ido-find-file-read-only-other-frame))
 
       (when (memq ido-mode '(buffer both))
        (define-key map [remap switch-to-buffer] 'ido-switch-buffer)
-       (define-key map [remap switch-to-buffer-other-window] 'ido-switch-buffer-other-window)
-       (define-key map [remap switch-to-buffer-other-frame] 'ido-switch-buffer-other-frame)
+       (define-key map [remap switch-to-buffer-other-window]
+          'ido-switch-buffer-other-window)
+       (define-key map [remap switch-to-buffer-other-frame]
+          'ido-switch-buffer-other-frame)
        (define-key map [remap insert-buffer] 'ido-insert-buffer)
        (define-key map [remap kill-buffer] 'ido-kill-buffer)
        (define-key map [remap display-buffer] 'ido-display-buffer))
@@ -1513,28 +1556,6 @@ This function also adds a hook to the minibuffer."
   (message "Ido mode %s" (if ido-mode "enabled" "disabled")))
 
 
-(defun ido-everywhere (arg)
-  "Toggle using ido speed-ups everywhere file and directory names are read.
-With ARG, turn ido speed-up on if arg is positive, off otherwise."
-  (interactive "P")
-  (setq ido-everywhere (if arg
-                          (> (prefix-numeric-value arg) 0)
-                        (not ido-everywhere)))
-  (when (get 'ido-everywhere 'file)
-    (setq read-file-name-function (car (get 'ido-everywhere 'file)))
-    (put 'ido-everywhere 'file nil))
-  (when (get 'ido-everywhere 'buffer)
-    (setq read-buffer-function (car (get 'ido-everywhere 'buffer)))
-    (put 'ido-everywhere 'buffer nil))
-  (when ido-everywhere
-    (when (memq ido-mode '(both file))
-      (put 'ido-everywhere 'file (cons read-file-name-function nil))
-      (setq read-file-name-function 'ido-read-file-name))
-    (when (memq ido-mode '(both buffer))
-      (put 'ido-everywhere 'buffer (cons read-buffer-function nil))
-      (setq read-buffer-function 'ido-read-buffer))))
-
-
 ;;; IDO KEYMAP
 (defun ido-init-completion-maps ()
   "Set up the completion keymaps used by `ido'."
@@ -1602,7 +1623,6 @@ With ARG, turn ido speed-up on if arg is positive, off otherwise."
     (define-key map "\C-o" 'ido-copy-current-word)
     (define-key map "\C-w" 'ido-copy-current-file-name)
     (define-key map [(meta ?l)] 'ido-toggle-literal)
-    (define-key map "\C-v" 'ido-toggle-vc)
     (set-keymap-parent map ido-file-dir-completion-map)
     (setq ido-file-completion-map map))
 
@@ -1611,6 +1631,7 @@ With ARG, turn ido speed-up on if arg is positive, off otherwise."
     (define-key map "\C-x\C-f" 'ido-enter-find-file)
     (define-key map "\C-x\C-b" 'ido-fallback-command)
     (define-key map "\C-k" 'ido-kill-buffer-at-head)
+    (define-key map "\C-o" 'ido-toggle-virtual-buffers)
     (set-keymap-parent map ido-common-completion-map)
     (setq ido-buffer-completion-map map)))
 
@@ -2160,9 +2181,13 @@ If cursor is not at the end of the user input, move to end of input."
           (ido-current-directory nil)
           (ido-directory-nonreadable nil)
           (ido-directory-too-big nil)
+          (ido-use-virtual-buffers (if (eq method 'kill)
+                                       nil    ;; Don't consider virtual buffers for killing
+                                     ido-use-virtual-buffers))
           (require-match (confirm-nonexistent-file-or-buffer))
           (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default
-                                  require-match initial)))
+                                  require-match initial))
+          filename)
 
       ;; Choose the buffer name: either the text typed in, or the head
       ;; of the list of matches
@@ -2198,6 +2223,16 @@ If cursor is not at the end of the user input, move to end of input."
                 (point))))
          (ido-visit-buffer buf method t)))
 
+       ;; check for a virtual buffer reference
+       ((and ido-use-virtual-buffers ido-virtual-buffers
+            (setq filename (assoc buf ido-virtual-buffers)))
+       (ido-visit-buffer (find-file-noselect (cdr filename)) method t))
+
+       ((and (eq ido-create-new-buffer 'prompt)
+            (null require-match)
+            (not (y-or-n-p (format "No buffer matching `%s', create one? " buf))))
+       nil)
+
        ;; buffer doesn't exist
        ((and (eq ido-create-new-buffer 'never)
             (null require-match))
@@ -2279,7 +2314,8 @@ If cursor is not at the end of the user input, move to end of input."
           (or ido-use-url-at-point ido-use-filename-at-point))
       (let (fn d)
        (require 'ffap)
-       ;; Duplicate code from ffap-guesser as we want different behavior for files and URLs.
+       ;; Duplicate code from ffap-guesser as we want different
+       ;; behavior for files and URLs.
        (cond
         ((with-no-warnings
            (and ido-use-url-at-point
@@ -2295,7 +2331,10 @@ If cursor is not at the end of the user input, move to end of input."
                              (ffap-guesser)
                            (ffap-string-at-point))))
               (not (string-match "^http:/" fn))
-              (setq d (file-name-directory fn))
+              (let ((absolute-fn (expand-file-name fn)))
+                (setq d (if (file-directory-p absolute-fn)
+                            (file-name-as-directory absolute-fn)
+                          (file-name-directory absolute-fn))))
               (file-directory-p d))
          (setq ido-current-directory d)
          (setq initial (file-name-nondirectory fn))))))
@@ -2668,6 +2707,16 @@ C-x C-f ... C-d  enter `dired' on current directory."
        (setq ido-exit 'keep)
        (exit-minibuffer))))
 
+(defun ido-toggle-virtual-buffers ()
+  "Toggle the use of virtual buffers.
+See `ido-use-virtual-buffers' for explanation of virtual buffer."
+  (interactive)
+  (when (and ido-mode (eq ido-cur-item 'buffer))
+    (setq ido-use-virtual-buffers (not ido-use-virtual-buffers))
+    (setq ido-text-init ido-text)
+    (setq ido-exit 'refresh)
+    (exit-minibuffer)))
+
 (defun ido-reread-directory ()
   "Read current directory again.
 May be useful if cached version is no longer valid, but directory
@@ -2766,7 +2815,7 @@ If no buffer or file exactly matching the prompt exists, maybe create a new one.
    ((eq this-original-command 'viper-del-backward-char-in-insert)
     (funcall this-original-command))
    (t
-    (delete-backward-char (prefix-numeric-value count)))))
+    (delete-char (- (prefix-numeric-value count))))))
 
 (defun ido-delete-backward-word-updir (count)
   "Delete all chars backwards, or at beginning of buffer, go up one level."
@@ -2982,8 +3031,7 @@ If repeated, insert text from buffer instead."
 (defun ido-copy-current-word (all)
   "Insert current word (file or directory name) from current buffer."
   (interactive "P")
-  (let ((word (save-excursion
-               (set-buffer ido-entry-buffer)
+  (let ((word (with-current-buffer ido-entry-buffer
                (let ((p (point)) start-line end-line start-name name)
                  (if (and mark-active (/= p (mark)))
                      (setq start-name (mark))
@@ -3353,14 +3401,38 @@ for first matching file."
        (nconc ido-temp-list ido-current-buffers)
       (setq ido-temp-list ido-current-buffers))
     (if default
-       (progn
-         (setq ido-temp-list
-               (delete default ido-temp-list))
-         (setq ido-temp-list
-               (cons default ido-temp-list))))
+        (setq ido-temp-list
+              (cons default (delete default ido-temp-list))))
     (run-hooks 'ido-make-buffer-list-hook)
     ido-temp-list))
 
+(defun ido-add-virtual-buffers-to-list ()
+  "Add recently visited files, and bookmark files, to the buffer list.
+This is to make them appear as if they were \"virtual buffers\"."
+  ;; If no buffers matched, and virtual buffers are being used, then
+  ;; consult the list of past visited files, to see if we can find
+  ;; the file which the user might thought was still open.
+  (unless recentf-mode (recentf-mode 1))
+  (setq ido-virtual-buffers nil)
+  (let (name)
+    (dolist (head recentf-list)
+      (and (setq name (file-name-nondirectory head))
+           (null (get-file-buffer head))
+           (not (assoc name ido-virtual-buffers))
+           (not (member name ido-temp-list))
+           (not (ido-ignore-item-p name ido-ignore-buffers))
+           ;;(file-exists-p head)
+           (push (cons name head) ido-virtual-buffers))))
+  (when ido-virtual-buffers
+    (if ido-use-faces
+       (dolist (comp ido-virtual-buffers)
+         (put-text-property 0 (length (car comp))
+                            'face 'ido-virtual
+                            (car comp))))
+    (setq ido-temp-list
+         (nconc ido-temp-list
+                (nreverse (mapcar #'car ido-virtual-buffers))))))
+
 (defun ido-make-choice-list (default)
   ;; Return the current list of choices.
   ;; If DEFAULT is non-nil, and corresponds to an element of choices,
@@ -3400,7 +3472,7 @@ for first matching file."
     ;; Strip method:user@host: part of tramp completions.
     ;; Tramp completions do not include leading slash.
     (let* ((len (1- (length dir)))
-          (tramp-completion-mode t)
+          (non-essential t)
           (compl
            (or (file-name-all-completions "" dir)
                ;; work around bug in ange-ftp.
@@ -3660,6 +3732,7 @@ for first matching file."
              matches (cdr error))))
     (when prefix-matches
       (ido-trace "prefix match" prefix-matches)
+      ;; Bug#2042.
       (setq matches (nconc prefix-matches matches)))
     (when suffix-matches
       (ido-trace "suffix match" (list text suffix-re suffix-matches))
@@ -3763,7 +3836,7 @@ for first matching file."
   ;; Return dotted pair (RES . 1).
   (cons res 1))
 
-(defun ido-choose-completion-string (choice buffer mini-p base-size)
+(defun ido-choose-completion-string (choice &rest ignored)
   (when (ido-active)
     ;; Insert the completion into the buffer where completion was requested.
     (if (get-buffer ido-completion-buffer)
@@ -3845,15 +3918,26 @@ If cursor is not at the end of the user input, delete to end of input."
   (if (not (eobp))
       (delete-region (point) (line-end-position))
     (let ((enable-recursive-minibuffers t)
-         (buf (ido-name (car ido-matches))))
-      (when buf
-       (kill-buffer buf)
-       ;; Check if buffer still exists.
-       (if (get-buffer buf)
-           ;; buffer couldn't be killed.
+         (buf (ido-name (car ido-matches)))
+         (nextbuf (cadr ido-matches)))
+      (when (get-buffer buf)
+       ;; If next match names a buffer use the buffer object; buffer
+       ;; name may be changed by packages such as uniquify; mindful
+       ;; of virtual buffers.
+       (when (and nextbuf (get-buffer nextbuf))
+         (setq nextbuf (get-buffer nextbuf)))
+       (if (null (kill-buffer buf))
+           ;; Buffer couldn't be killed.
            (setq ido-rescan t)
-         ;; else buffer was killed so remove name from list.
-         (setq ido-cur-list (delq buf ido-cur-list)))))))
+         ;; Else `kill-buffer' succeeds so re-make the buffer list
+         ;; taking into account packages like uniquify may rename
+         ;; buffers.
+         (if (bufferp nextbuf)
+             (setq nextbuf (buffer-name nextbuf)))
+         (setq ido-default-item nextbuf
+               ido-text-init ido-text
+               ido-exit 'refresh)
+         (exit-minibuffer))))))
 
 ;;; DELETE CURRENT FILE
 (defun ido-delete-file-at-head ()
@@ -4190,8 +4274,7 @@ For details of keybindings, see `ido-find-file'."
            ido-text-init contents
            ido-rotate-temp t
            ido-exit 'refresh)
-      (save-excursion
-       (set-buffer buffer)
+      (with-current-buffer buffer
        (ido-tidy))
       (throw 'ido contents))))
 
@@ -4444,7 +4527,7 @@ For details of keybindings, see `ido-find-file'."
     (cond ((null comps)
           (cond
            (ido-show-confirm-message
-            (or (nth 11 ido-decorations) " [Confirm]"))
+            (or (nth 10 ido-decorations) " [Confirm]"))
            (ido-directory-nonreadable
             (or (nth 8 ido-decorations) " [Not readable]"))
            (ido-directory-too-big
@@ -4511,7 +4594,6 @@ For details of keybindings, see `ido-find-file'."
   (when (ido-active)
     (add-hook 'pre-command-hook 'ido-tidy nil t)
     (add-hook 'post-command-hook 'ido-exhibit nil t)
-    (setq cua-inhibit-cua-keys t)
     (when (featurep 'xemacs)
       (ido-exhibit)
       (goto-char (point-min)))