ido-ubiquitous.el 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. ;;; ido-ubiquitous.el --- Use ido (nearly) everywhere.
  2. ;; Author: Ryan C. Thompson
  3. ;; URL: https://github.com/DarwinAwardWinner/ido-ubiquitous
  4. ;; Version: 1.1
  5. ;; Created: 2011-09-01
  6. ;; Keywords: convenience
  7. ;; EmacsWiki: InteractivelyDoThings
  8. ;; This file is NOT part of GNU Emacs.
  9. ;;; Commentary:
  10. ;; You may have seen the `ido-everywhere' variable in ido.el and got
  11. ;; excited that you could use ido completion for everything. Then you
  12. ;; were probably disappointed when you realized that it only applied
  13. ;; to *file names* and nothing else. Well, ido-ubiquitous is here to
  14. ;; fulfill the original promise and let you use ido completion for
  15. ;; (almost) any command that uses `completing-read' to offer you a
  16. ;; choice of several alternatives.
  17. ;; This even works in M-x, but for that, you might prefer the "smex"
  18. ;; package instead.
  19. ;; As of version 0.7, this package also makes a small modification to
  20. ;; ido's behavior so as to support a strange corner case of
  21. ;; `completing-read' that some functions rely on. Since the goal of
  22. ;; this package is to replace `completing-read' everywhere instead of
  23. ;; just selectively (as ido itself does), compatibility with all the
  24. ;; quriks of `completing-read' is important here.
  25. ;; If you find a case where enabling ido-ubiquitous causes a command
  26. ;; not to work correctly, please report it by creating an issue on
  27. ;; GitHub: https://github.com/DarwinAwardWinner/ido-ubiquitous/issues
  28. ;;; License:
  29. ;; This program is free software; you can redistribute it and/or modify
  30. ;; it under the terms of the GNU General Public License as published by
  31. ;; the Free Software Foundation; either version 3, or (at your option)
  32. ;; any later version.
  33. ;;
  34. ;; This program is distributed in the hope that it will be useful,
  35. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  36. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37. ;; GNU General Public License for more details.
  38. ;;
  39. ;; You should have received a copy of the GNU General Public License
  40. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  41. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  42. ;; Boston, MA 02110-1301, USA.
  43. ;;; Code:
  44. (require 'ido)
  45. ;;;###autoload
  46. (defgroup ido-ubiquitous nil
  47. "Use ido for (almost) all completion."
  48. :group 'ido)
  49. ;;;###autoload
  50. (define-minor-mode ido-ubiquitous-mode
  51. "Use `ido-completing-read' instead of `completing-read' almost everywhere.
  52. This mode has no effect unles `ido-mode' is also enabled.
  53. If this mode causes problems for a function, you can force the
  54. function to use the original completing read by using the macro
  55. `ido-ubiquitous-disable-in'. For example, if a
  56. function `foo' cannot work with ido-style completion, evaluate
  57. the following (for example by putting it in your .emacs file):
  58. (ido-ubiquitous-disable-in foo)"
  59. nil
  60. :global t
  61. :group 'ido-ubiquitous)
  62. ;;;###autoload
  63. (define-obsolete-variable-alias 'ido-ubiquitous
  64. 'ido-ubiquitous-mode "0.8")
  65. ;;;###autoload
  66. (define-obsolete-function-alias 'ido-ubiquitous
  67. 'ido-ubiquitous-mode "0.8")
  68. ;;;###autoload
  69. (defcustom ido-ubiquitous-command-exceptions '()
  70. "List of commands that should not be affected by `ido-ubiquitous'.
  71. Even when `ido-ubiquitous' mode is enabled, these commands will
  72. continue to use `completing-read' instead of
  73. `ido-completing-read'.
  74. Only *interactive* commands should go here. To disable
  75. ido-ubiquitous in non-interactive functions, customize
  76. `ido-ubiquitous-function-exceptions'."
  77. :type '(repeat (symbol :tag "Command"))
  78. :group 'ido-ubiquitous)
  79. ;;;###autoload
  80. (define-obsolete-variable-alias 'ido-ubiquitous-exceptions
  81. 'ido-ubiquitous-command-exceptions "0.4")
  82. (defadvice completing-read (around ido-ubiquitous activate)
  83. (if (or (not ido-mode)
  84. (not ido-ubiquitous-mode)
  85. (memq this-command ido-ubiquitous-command-exceptions)
  86. ;; Avoid infinite recursion from ido calling completing-read
  87. (boundp 'ido-cur-item))
  88. ad-do-it
  89. (let ((allcomp (all-completions "" collection predicate)))
  90. ;; Only use ido completion if there are actually any completions
  91. ;; to offer.
  92. (if allcomp
  93. (setq ad-return-value
  94. (ido-completing-read prompt allcomp
  95. nil require-match initial-input hist def))
  96. ad-do-it))))
  97. (defmacro ido-ubiquitous-disable-in (func)
  98. "Disable ido-ubiquitous in FUNC."
  99. (let ((docstring
  100. (format "Disable ido-ubiquitous in %s" func)))
  101. `(defadvice ,func (around disable-ido-ubiquitous activate)
  102. ,docstring
  103. (let (ido-ubiquitous-mode) ad-do-it))))
  104. (define-obsolete-function-alias
  105. 'disable-ido-ubiquitous-in
  106. 'ido-ubiquitous-disable-in
  107. "0.4")
  108. (defmacro ido-ubiquitous-enable-in (func)
  109. "Re-enable ido-ubiquitous in FUNC.
  110. This reverses the effect of `ido-ubiquitous-disable-in'."
  111. ;; In my experience, simply using `ad-remove-advice' or
  112. ;; `ad-disable-advice' doesn't work correctly (in Emacs 23).
  113. ;; Instead, I've found that one must redefine the advice under the
  114. ;; same name ("disable-ido-ubiquitous") to simply call the original
  115. ;; function with no modifications. This has the same effect
  116. ;; (disables the advice), but is presumably less efficient.
  117. (let ((docstring
  118. (format "DO NOT disable ido-ubiquitous in %s" func)))
  119. `(defadvice ,func (around disable-ido-ubiquitous activate)
  120. ,docstring
  121. ad-do-it)))
  122. (define-obsolete-function-alias
  123. 'enable-ido-ubiquitous-in
  124. 'ido-ubiquitous-enable-in
  125. "0.4")
  126. ;; Always disable ido-ubiquitous in `find-file' and similar functions,
  127. ;; because they are not supposed to use ido.
  128. (defvar ido-ubiquitous-permanent-function-exceptions
  129. '(read-file-name
  130. gnus-emacs-completing-read
  131. gnus-iswitchb-completing-read
  132. man)
  133. "Functions in which ido-ubiquitous should always be disabled.
  134. If you want to disable ido in a specific function or command, do
  135. not modify this variable. Instead, try `M-x customize-group
  136. ido-ubiquitous.")
  137. (dolist (func ido-ubiquitous-permanent-function-exceptions)
  138. (eval `(ido-ubiquitous-disable-in ,func)))
  139. (defun ido-ubiquitous--set-difference (list1 list2)
  140. "Replacement for `set-difference' from `cl'."
  141. (apply #'nconc
  142. (mapcar (lambda (elt) (unless (memq elt list2) (list elt)))
  143. list1)))
  144. (defun ido-ubiquitous-set-function-exceptions (sym newval)
  145. (let* ((oldval (when (boundp sym) (eval sym))))
  146. ;; Filter out permanent fixtures
  147. (setq oldval (ido-ubiquitous--set-difference oldval ido-ubiquitous-permanent-function-exceptions))
  148. (setq newval (ido-ubiquitous--set-difference newval ido-ubiquitous-permanent-function-exceptions))
  149. ;; Re-enable ido-ubiquitous on all old functions, in case they
  150. ;; were removed from the list.
  151. (dolist (oldfun oldval)
  152. (eval `(ido-ubiquitous-enable-in ,oldfun)))
  153. ;; Set the new value
  154. (set-default sym newval)
  155. ;; Disable ido-ubiquitous on all new functions
  156. (dolist (newfun newval)
  157. (eval `(ido-ubiquitous-disable-in ,newfun)))))
  158. ;;;###autoload
  159. (defcustom ido-ubiquitous-function-exceptions
  160. '(grep-read-files)
  161. "List of functions in which to disable ido-ubiquitous.
  162. If you need to add a function to this list, please also file a
  163. bug report at
  164. https://github.com/DarwinAwardWinner/ido-ubiquitous/issues
  165. Note that certain functions, such as `read-file-name', must
  166. always have ido-ubiquitous disabled, and cannot be added
  167. here. (They are effectively a permanent part of this list
  168. already.)"
  169. :group 'ido-ubiquitous
  170. :type '(repeat :tag "Functions"
  171. (symbol :tag "Function"))
  172. :set 'ido-ubiquitous-set-function-exceptions)
  173. (defcustom ido-ubiquitous-enable-compatibility t
  174. "Emulate a quirk of `completing-read'.
  175. Apparently, long ago `completing-read' did not have a \"default\"
  176. argument, so functions that used it requested the default item by
  177. returning an empty string when RET was pressed with an empty
  178. input. When t, this option forces `ido-completing-read' to mimic
  179. this behavior by returning an empty string if the user has
  180. neither entered any text nor cycled choices (instead of ido's
  181. normal behavior of returning the first choice in the list). This
  182. improves compatibility with many older functions that use
  183. `completing-read' in this way, but may also break compatibility
  184. with others.
  185. You can also disable this behavior just once by pressing \"C-u\"
  186. right before pressing \"RET\".
  187. This has no effect when ido is completing buffers or files.")
  188. (defvar ido-ubiquitous-initial-item nil
  189. "The first item selected when ido starts.")
  190. (defadvice ido-read-internal (before clear-initial-item activate)
  191. (setq ido-ubiquitous-initial-item nil))
  192. (defadvice ido-make-choice-list (after set-initial-item activate)
  193. (when (and ad-return-value (listp ad-return-value))
  194. (setq ido-ubiquitous-initial-item (car ad-return-value))))
  195. (defadvice ido-next-match (after clear-initial-item activate)
  196. (setq ido-ubiquitous-initial-item nil))
  197. (defadvice ido-prev-match (after clear-initial-item activate)
  198. (setq ido-ubiquitous-initial-item nil))
  199. (defadvice ido-exit-minibuffer (around required-allow-empty-string activate)
  200. "Emulate a quirk of `completing-read'.
  201. Apparently, `completing-read' used to request the default item by
  202. returning an empty string when RET was pressed with an empty input.
  203. This forces `ido-completing-read' to do the same (instead of returning
  204. the first choice in the list).
  205. This has no effect when ido is completing buffers or files."
  206. (if (and ido-ubiquitous-enable-compatibility
  207. (eq ido-cur-item 'list)
  208. ido-require-match
  209. (null ido-default-item)
  210. (not current-prefix-arg)
  211. (string= ido-text "")
  212. (string= (car ido-cur-list)
  213. ido-ubiquitous-initial-item))
  214. (ido-select-text)
  215. ad-do-it))
  216. (defadvice bookmark-completing-read (around disable-ido-compatibility activate)
  217. "`bookmark-completing-read' uses `completing-read' in an odd
  218. way that conflicts with the compatibilty mode of
  219. ido-ubiquitous."
  220. (let (ido-ubiquitous-enable-compatibility)
  221. ad-do-it))
  222. (provide 'ido-ubiquitous) ;;; ido-ubiquitous.el ends here