;;; ido.el --- interactively do things with buffers and files.
-;; Copyright (C) 1996-2004 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2004, 2005 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
"Switch between files using substrings."
:group 'extensions
:group 'convenience
+ :version "22.1"
:link '(emacs-commentary-link :tag "Commentary" "ido.el")
:link '(emacs-library-link :tag "Lisp File" "ido.el"))
:require 'ido
:link '(emacs-commentary-link "ido.el")
:set-after '(ido-save-directory-list-file)
- :version "21.4"
:type '(choice (const :tag "Turn on only buffer" buffer)
(const :tag "Turn on only file" file)
(const :tag "Turn on both buffer and file" both)
:type 'boolean
:group 'ido)
+(defcustom ido-file-extensions-order nil
+ "*List of file extensions specifying preferred order of file selections.
+Each element is either a string with `.' as the first char, an empty
+string matching files without extension, or t which is the default order
+of for files with an unlisted file extension."
+ :type '(repeat (choice string
+ (const :tag "Default order" t)))
+ :group 'ido)
+
(defcustom ido-ignore-directories
'("\\`CVS/" "\\`\\.\\./" "\\`\\./")
"*List of regexps or functions matching sub-directory names to ignore."
"*Font used by ido for highlighting only match."
:group 'ido)
-(defface ido-subdir-face '((((class color))
+(defface ido-subdir-face '((((min-colors 88) (class color))
+ (:foreground "red1"))
+ (((class color))
(:foreground "red"))
(t (:underline t)))
"*Font used by ido for highlighting subdirs in the alternatives."
:group 'ido)
-(defface ido-indicator-face '((((class color))
+(defface ido-indicator-face '((((min-colors 88) (class color))
+ (:foreground "yellow1"
+ :background "red1"
+ :width condensed))
+ (((class color))
(:foreground "yellow"
:background "red"
:width condensed))
(setq ido-set-default-item t))))
;; Handling the require-match must be done in a better way.
- ((and require-match (not (ido-existing-item-p)))
+ ((and require-match
+ (not (if ido-directory-too-big
+ (file-exists-p (concat ido-current-directory ido-final-text))
+ (ido-existing-item-p))))
(error "must specify valid item"))
(t
;; Internal function for ido-find-file and friends
(unless item
(setq item 'file))
- (let* ((ido-current-directory (ido-expand-directory default))
- (ido-directory-nonreadable (ido-nonreadable-directory-p ido-current-directory))
- (ido-directory-too-big (and (not ido-directory-nonreadable)
- (ido-directory-too-big-p ido-current-directory)))
- (ido-context-switch-command switch-cmd)
- filename)
-
- (cond
- ((or (not ido-mode) (ido-is-slow-ftp-host))
- (setq filename t
- ido-exit 'fallback))
-
- ((and (eq item 'file)
+ (let ((ido-current-directory (ido-expand-directory default))
+ (ido-context-switch-command switch-cmd)
+ ido-directory-nonreadable ido-directory-too-big
+ filename)
+
+ (if (or (not ido-mode) (ido-is-slow-ftp-host))
+ (setq filename t
+ ido-exit 'fallback)
+ (setq ido-directory-nonreadable
+ (ido-nonreadable-directory-p ido-current-directory)
+ ido-directory-too-big
+ (and (not ido-directory-nonreadable)
+ (ido-directory-too-big-p ido-current-directory))))
+
+ (when (and (eq item 'file)
(or ido-use-url-at-point ido-use-filename-at-point))
(let (fn d)
(require 'ffap)
(setq d (file-name-directory fn))
(file-directory-p d))
(setq ido-current-directory d)
- (setq initial (file-name-nondirectory fn)))))))
+ (setq initial (file-name-nondirectory fn))))))
(let (ido-saved-vc-hb
(vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
(defun ido-fallback-command ()
"Fallback to non-ido version of current command."
(interactive)
+ (let ((i (length ido-text)))
+ (while (> i 0)
+ (push (aref ido-text (setq i (1- i))) unread-command-events)))
(setq ido-exit 'fallback)
(exit-minibuffer))
(t nil))))
-(defun ido-sort-list (items)
- ;; Simple list of file or buffer names
- (sort items (lambda (a b) (string-lessp (ido-no-final-slash a)
- (ido-no-final-slash b)))))
+;; File list sorting
+
+(defun ido-file-lessp (a b)
+ ;; Simple compare two file names.
+ (string-lessp (ido-no-final-slash a) (ido-no-final-slash b)))
+
+
+(defun ido-file-extension-lessp (a b)
+ ;; Compare file names according to ido-file-extensions-order list.
+ (let ((n (compare-strings a 0 nil b 0 nil nil))
+ lessp p)
+ (if (eq n t)
+ nil
+ (if (< n 0)
+ (setq n (1- (- n))
+ p a a b b p
+ lessp t)
+ (setq n (1- n)))
+ (cond
+ ((= n 0)
+ lessp)
+ ((= (aref a n) ?.)
+ (ido-file-extension-aux a b n lessp))
+ (t
+ (while (and (> n 2) (/= (aref a n) ?.))
+ (setq n (1- n)))
+ (if (> n 1)
+ (ido-file-extension-aux a b n lessp)
+ lessp))))))
+
+(defun ido-file-extension-aux (a b n lessp)
+ (let ((oa (ido-file-extension-order a n))
+ (ob (ido-file-extension-order b n)))
+ (cond
+ ((= oa ob)
+ lessp)
+ ((and oa ob)
+ (if lessp
+ (> oa ob)
+ (< oa ob)))
+ (oa
+ (not lessp))
+ (ob
+ lessp)
+ (t
+ lessp))))
+
+(defun ido-file-extension-order (s n)
+ (let ((l ido-file-extensions-order)
+ (i 0) o do)
+ (while l
+ (cond
+ ((eq (car l) t)
+ (setq do i
+ l (cdr l)))
+ ((eq (compare-strings s n nil (car l) 0 nil nil) t)
+ (setq o i
+ l nil))
+ (t
+ (setq l (cdr l))))
+ (setq i (1+ i)))
+ (or o do)))
+
(defun ido-sort-merged-list (items promote)
;; Input is list of ("file" . "dir") cons cells.
;; created to allow the user to further modify the order of the file names
;; in this list.
(let ((ido-temp-list (ido-make-file-list1 ido-current-directory)))
- (setq ido-temp-list (ido-sort-list ido-temp-list))
+ (setq ido-temp-list (sort ido-temp-list
+ (if ido-file-extensions-order
+ #'ido-file-extension-lessp
+ #'ido-file-lessp)))
(let ((default-directory ido-current-directory))
(ido-to-end ;; move ftp hosts and visited files to end
(delq nil (mapcar
;; created to allow the user to further modify the order of the
;; directory names in this list.
(let ((ido-temp-list (ido-make-dir-list1 ido-current-directory)))
- (setq ido-temp-list (ido-sort-list ido-temp-list))
+ (setq ido-temp-list (sort ido-temp-list #'ido-file-lessp))
(ido-to-end ;; move . files to end
(delq nil (mapcar
(lambda (x) (if (string-equal (substring x 0 1) ".") x))
(setq display-it t))
(if display-it
(with-output-to-temp-buffer ido-completion-buffer
- (let ((completion-list (ido-sort-list
+ (let ((completion-list (sort
(cond
(ido-use-merged-list
(ido-flatten-merged-list (or ido-matches ido-cur-list)))
((or full-list ido-completion-buffer-all-completions)
(ido-all-completions))
(t
- (copy-sequence (or ido-matches ido-cur-list)))))))
+ (copy-sequence (or ido-matches ido-cur-list))))
+ #'ido-file-lessp)))
(if (featurep 'xemacs)
;; XEmacs extents are put on by default, doesn't seem to be
;; any way of switching them off.