;;; 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
;;
(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
(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,
: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."
"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"
"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.
;; 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
(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))
(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'."
(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))
(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)))
(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
(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))
(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
(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))))))
(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
((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."
(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))
(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,
;; 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.
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))
;; 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)
(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 ()
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))))
(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
(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)))