123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- ;;; ido-ubiquitous.el --- Use ido (nearly) everywhere.
- ;; Author: Ryan C. Thompson
- ;; URL: https://github.com/DarwinAwardWinner/ido-ubiquitous
- ;; Version: 1.3
- ;; Created: 2011-09-01
- ;; Keywords: convenience
- ;; EmacsWiki: InteractivelyDoThings
- ;; This file is NOT part of GNU Emacs.
- ;;; Commentary:
- ;; You may have seen the `ido-everywhere' variable in ido.el and got
- ;; excited that you could use ido completion for everything. Then you
- ;; were probably disappointed when you realized that it only applied
- ;; to *file names* and nothing else. Well, ido-ubiquitous is here to
- ;; fulfill the original promise and let you use ido completion for
- ;; (almost) any command that uses `completing-read' to offer you a
- ;; choice of several alternatives.
- ;; This even works in M-x, but for that, you might prefer the "smex"
- ;; package instead.
- ;; As of version 0.7, this package also makes a small modification to
- ;; ido's behavior so as to support a strange corner case of
- ;; `completing-read' that some functions rely on. Since the goal of
- ;; this package is to replace `completing-read' everywhere instead of
- ;; just selectively (as ido itself does), compatibility with all the
- ;; quriks of `completing-read' is important here.
- ;; If you find a case where enabling ido-ubiquitous causes a command
- ;; not to work correctly, please report it by creating an issue on
- ;; GitHub: https://github.com/DarwinAwardWinner/ido-ubiquitous/issues
- ;;; License:
- ;; This program is free software; you can redistribute it and/or modify
- ;; it under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation; either version 3, or (at your option)
- ;; any later version.
- ;;
- ;; This program is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
- ;;
- ;; You should have received a copy of the GNU General Public License
- ;; along with GNU Emacs; see the file COPYING. If not, write to the
- ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- ;; Boston, MA 02110-1301, USA.
- ;;; Code:
- (require 'ido)
- ;;;###autoload
- (defgroup ido-ubiquitous nil
- "Use ido for (almost) all completion."
- :group 'ido)
- ;;;###autoload
- (define-minor-mode ido-ubiquitous-mode
- "Use `ido-completing-read' instead of `completing-read' almost everywhere.
- This mode has no effect unles `ido-mode' is also enabled.
- If this mode causes problems for a function, you can force the
- function to use the original completing read by using the macro
- `ido-ubiquitous-disable-in'. For example, if a
- function `foo' cannot work with ido-style completion, evaluate
- the following (for example by putting it in your .emacs file):
- (ido-ubiquitous-disable-in foo)"
- nil
- :global t
- :group 'ido-ubiquitous)
- ;;;###autoload
- (define-obsolete-variable-alias 'ido-ubiquitous
- 'ido-ubiquitous-mode "0.8")
- ;;;###autoload
- (define-obsolete-function-alias 'ido-ubiquitous
- 'ido-ubiquitous-mode "0.8")
- ;;;###autoload
- (defcustom ido-ubiquitous-command-exceptions '()
- "List of commands that should not be affected by `ido-ubiquitous'.
- Even when `ido-ubiquitous' mode is enabled, these commands will
- continue to use `completing-read' instead of
- `ido-completing-read'.
- Only *interactive* commands should go here. To disable
- ido-ubiquitous in non-interactive functions, customize
- `ido-ubiquitous-function-exceptions'."
- :type '(repeat (symbol :tag "Command"))
- :group 'ido-ubiquitous)
- ;;;###autoload
- (define-obsolete-variable-alias 'ido-ubiquitous-exceptions
- 'ido-ubiquitous-command-exceptions "0.4")
- (defadvice completing-read (around ido-ubiquitous activate)
- (if (or (not ido-mode)
- (not ido-ubiquitous-mode)
- (memq this-command ido-ubiquitous-command-exceptions)
- ;; Avoid infinite recursion from ido calling completing-read
- (boundp 'ido-cur-item))
- ad-do-it
- (let ((allcomp (all-completions "" collection predicate)))
- ;; Only use ido completion if there are actually any completions
- ;; to offer.
- (if allcomp
- (setq ad-return-value
- (ido-completing-read prompt allcomp
- nil require-match initial-input hist def))
- ad-do-it))))
- (defmacro ido-ubiquitous-disable-in (func)
- "Disable ido-ubiquitous in FUNC."
- (let ((docstring
- (format "Disable ido-ubiquitous in %s" func)))
- `(defadvice ,func (around disable-ido-ubiquitous activate)
- ,docstring
- (let (ido-ubiquitous-mode) ad-do-it))))
- (define-obsolete-function-alias
- 'disable-ido-ubiquitous-in
- 'ido-ubiquitous-disable-in
- "0.4")
- (defmacro ido-ubiquitous-enable-in (func)
- "Re-enable ido-ubiquitous in FUNC.
- This reverses the effect of a previous call to
- `ido-ubiquitous-disable-in'."
- `(when (ad-find-advice ',func 'around 'disable-ido-ubiquitous)
- (ad-disable-advice ',func 'around 'disable-ido-ubiquitous)
- (ad-activate ',func)))
- (define-obsolete-function-alias
- 'enable-ido-ubiquitous-in
- 'ido-ubiquitous-enable-in
- "0.4")
- ;; Always disable ido-ubiquitous in `find-file' and similar functions,
- ;; because they are not supposed to use ido.
- (defvar ido-ubiquitous-permanent-function-exceptions
- '(read-file-name
- gnus-emacs-completing-read
- gnus-iswitchb-completing-read
- man)
- "Functions in which ido-ubiquitous should always be disabled.
- If you want to disable ido in a specific function or command, do
- not modify this variable. Instead, try `M-x customize-group
- ido-ubiquitous.")
- (mapc (lambda (func) (eval `(ido-ubiquitous-disable-in ,func)))
- ido-ubiquitous-permanent-function-exceptions)
- (defun ido-ubiquitous--set-difference (list1 list2)
- "Replacement for `set-difference' from `cl'."
- (apply #'nconc
- (mapcar (lambda (elt) (unless (memq elt list2) (list elt)))
- list1)))
- (defun ido-ubiquitous-set-function-exceptions (sym newval)
- (let* ((oldval (when (boundp sym) (eval sym))))
- ;; Filter out the permanent exceptions so we never act on them.
- (setq oldval (ido-ubiquitous--set-difference oldval ido-ubiquitous-permanent-function-exceptions))
- (setq newval (ido-ubiquitous--set-difference newval ido-ubiquitous-permanent-function-exceptions))
- ;; Re-enable ido-ubiquitous on all old functions, in case they
- ;; were removed from the list.
- (dolist (oldfun oldval)
- (eval `(ido-ubiquitous-enable-in ,oldfun)))
- ;; Set the new value
- (set-default sym newval)
- ;; Disable ido-ubiquitous on all new functions
- (dolist (newfun newval)
- (eval `(ido-ubiquitous-disable-in ,newfun)))))
- ;;;###autoload
- (defcustom ido-ubiquitous-function-exceptions
- '(grep-read-files)
- "List of functions in which to disable ido-ubiquitous.
- If you need to add a function to this list, please also file a
- bug report at
- https://github.com/DarwinAwardWinner/ido-ubiquitous/issues
- Note that certain functions, such as `read-file-name', must
- always have ido-ubiquitous disabled, and cannot be added
- here. (They are effectively a permanent part of this list
- already.)"
- :group 'ido-ubiquitous
- :type '(repeat :tag "Functions"
- (symbol :tag "Function"))
- :set 'ido-ubiquitous-set-function-exceptions)
- (defcustom ido-ubiquitous-enable-compatibility t
- "Emulate a quirk of `completing-read'.
- In the past, the `completing-read' function had no way of
- specifying a default item, so instead the convention was to
- request the default by returning an empty string. This occurrs in
- standard emacs completion system when you press \"RET\" without
- typing anything first. This is a problem for ido completion
- because when ido is used this way, it does not know which item is
- the default, so it cannot put the default at the head of the
- list. Hence, simply pressing \"RET\" will not properly select the
- advertised default. Setting this variable to non-nil will force
- ido to emulate this quirk of the standard emacs completion system
- in order to maintain compatibility with old functions that still
- use the empty-string-as-default convention.
- Specifically, when this variable is non-nil, ido will return an
- empty string (thereby requesting the default) if you press \"RET\"
- without entering any text or cycling through the offered choices.
- This replaces the standard ido behavior of returning the first
- item on the list. Enabling this option improves compatibility
- with many older functions that use `completing-read' in this way,
- but may also break compatibility with others, since it changes
- what ido returns.
- If you want this enabled most of the time but once in a while you
- really want to select the first item on the list, you can do so
- by prefixing \"RET\" with \"C-u\".
- This has no effect when ido is completing buffers or files."
- :type 'boolean
- :group 'ido-ubiquitous)
- (defvar ido-ubiquitous-initial-item nil
- "The first item selected when ido starts.")
- (defadvice ido-read-internal (before clear-initial-item activate)
- (setq ido-ubiquitous-initial-item nil))
- (defadvice ido-make-choice-list (after set-initial-item activate)
- (when (and ad-return-value (listp ad-return-value))
- (setq ido-ubiquitous-initial-item (car ad-return-value))))
- (defadvice ido-next-match (after clear-initial-item activate)
- (setq ido-ubiquitous-initial-item nil))
- (defadvice ido-prev-match (after clear-initial-item activate)
- (setq ido-ubiquitous-initial-item nil))
- (defadvice ido-exit-minibuffer (around required-allow-empty-string activate)
- "Emulate a quirk of `completing-read'.
- Apparently, in the past `completing-read' used to request the
- default item by returning an empty string when RET was pressed
- with an empty input. This forces `ido-completing-read' to do the
- same (instead of returning the first choice in the list),
- allowing the default to be properly selected.
- This has no effect when ido is completing buffers or files.
- This behavior is disabled by setting
- `ido-ubiquitous-enable-compatibility' to nil."
- (if (and ido-ubiquitous-enable-compatibility
- (eq ido-cur-item 'list)
- ido-require-match
- (null ido-default-item)
- (not current-prefix-arg)
- (string= ido-text "")
- (string= (car ido-cur-list)
- ido-ubiquitous-initial-item))
- (ido-select-text)
- ad-do-it))
- (defadvice bookmark-completing-read (around disable-ido-compatibility activate)
- "`bookmark-completing-read' uses `completing-read' in an odd
- way that conflicts with the compatibilty mode of
- ido-ubiquitous."
- (let (ido-ubiquitous-enable-compatibility)
- ad-do-it))
- (provide 'ido-ubiquitous) ;;; ido-ubiquitous.el ends here
|