ソースを参照

Rewrite ido-ubiquitous on top of ido-cr+

Ryan C. Thompson 10 年 前
コミット
f0ddb5f2f9
1 ファイル変更201 行追加270 行削除
  1. 201 270
      ido-ubiquitous.el

+ 201 - 270
ido-ubiquitous.el

@@ -76,15 +76,12 @@ be updated until you restart Emacs.")
 (require 'ido)
 (require 'advice)
 (require 'cl-lib)
+(require 'ido-completing-read+)
 ;; Only exists in emacs 24.4 and up; we don't use this library
 ;; directly, but we load it here so we can test if it's available,
 ;; because if it isn't we need enable a workaround.
 (require 'nadvice nil 'noerror)
 
-;; Declare this ahead of time to quiet the compiler; it is actually
-;; defined later.
-(defvar ido-ubiquitous-fallback-completing-read-function)
-
 ;;; Internal utility functions
 
 (defun ido-ubiquitous--as-string (sym-or-str)
@@ -169,119 +166,109 @@ be updated until you restart Emacs.")
 
 (defgroup ido-ubiquitous nil
   "Use ido for (almost) all completion."
-  :group 'ido)
+  :group 'ido
+  :group 'ido-completing-read-plus)
 
 ;;;###autoload
 (define-obsolete-variable-alias 'ido-ubiquitous
-  'ido-ubiquitous-mode "0.8")
+  'ido-ubiquitous-mode "ido-ubiquitous 0.8")
 ;;;###autoload
 (define-obsolete-function-alias 'ido-ubiquitous
-  'ido-ubiquitous-mode "0.8")
+  'ido-ubiquitous-mode "ido-ubiquitous 0.8")
 
 ;;;###autoload
 (define-minor-mode ido-ubiquitous-mode
   "Use `ido-completing-read' instead of `completing-read' almost everywhere.
 
-  If this mode causes problems for a function, you can customize
-  when ido completion is or is not used by customizing
-  `ido-ubiquitous-command-overrides' or
-  `ido-ubiquitous-function-overrides'."
-
+If this mode causes problems for a function, you can customize
+when ido completion is or is not used by customizing
+`ido-ubiquitous-command-overrides' or
+`ido-ubiquitous-function-overrides'."
   nil
   :global t
   :group 'ido-ubiquitous
-  ;; Ensure emacs 23 code disabled (in case user upgraded in this session)
-  (ignore-errors
-    (ad-disable-advice 'completing-read 'around 'ido-ubiquitous-legacy)
-    (ad-activate 'completing-read))
-  ;; Actually enable/disable the mode
+  ;; Actually enable/disable the mode by setting
+  ;; `completing-read-function'.
   (setq completing-read-function
         (if ido-ubiquitous-mode
-            'completing-read-ido
-          (or ido-ubiquitous-fallback-completing-read-function
-              'completing-read-default))))
-
-(defcustom ido-ubiquitous-max-items 30000
-  "Max collection size to use ido-ubiquitous on.
-
-If `ido-ubiquitous-mode' is active and `completing-read' is
-called on a COLLECTION with greater than this number of items in
-it, the fallback completion method will be used instead. To
-disable fallback based on collection size, set this to nil."
-  :type '(choice (const :tag "No limit" nil)
-                 (integer
-                  :tag "Limit" :value 30000
-                  :validate
-                  (lambda (widget)
-                    (let ((v (widget-value widget)))
-                      (if (and (integerp v)
-                               (> v 0))
-                          nil
-                        (widget-put widget :error "This field should contain a positive integer")
-                        widget)))))
-  :group 'ido-ubiquitous)
+            #'completing-read-ido-ubiquitous
+          ido-cr+-fallback-function)))
 
-(defcustom ido-ubiquitous-fallback-completing-read-function
-  ;; Initialize to the current value of `completing-read-function',
-  ;; unless that is already set to the ido completer, in which case
-  ;; use `completing-read-default'.
-  (if (eq completing-read-function 'completing-read-ido)
-      'completing-read-default
-    completing-read-function)
-  "Alternate completing-read function to use when ido is not wanted.
-
-This will be used for functions that are incompatibile with ido
-or if ido cannot handle the completion arguments.
-
-If you turn off ido-ubiquitous mode, `completing-read-function'
-will be set back to this."
-  :type '(choice (const :tag "Standard emacs completion"
-                        completing-read-default)
-                 (function :tag "Other function"))
-  :group 'ido-ubiquitous)
+;; Variables for functionality that has moved to ido-completing-read+
+(define-obsolete-variable-alias
+  'ido-ubiquitous-max-items
+  'ido-cr+-max-items
+  "ido-ubiquitous 2.17")
+(define-obsolete-variable-alias
+  'ido-ubiquitous-fallback-completing-read-function
+  'ido-cr+-fallback-function
+  "ido-ubiquitous 2.17")
 
 (define-obsolete-variable-alias
   'ido-ubiquitous-enable-compatibility-globally
   'ido-ubiquitous-enable-old-style-default
-  "2.0")
+  "ido-ubiquitous 2.0")
+
+(defcustom ido-ubiquitous-default-state 'enable
+  "Default ido-ubiquitous mode of operation for commands with no override.
 
-(defcustom ido-ubiquitous-enable-old-style-default t
-  "Allow ido to emulate a quirk of `completing-read'.
+This can be set to one of three options:
 
-From the `completing-read' docstring:
+  * `enable': use normal ido completion;
+  * `enable-old': use ido completion, but with emulation of the
+    old-style default selection of `completing-read';
+  * `disable': use non-ido completion.
+
+Command-specific and function-specific overrides are available to
+override this default for specific commands/functions. See
+`ido-ubiquitous-command-overrides' and
+`ido-ubiquitous-function-overrides'.
+
+The `enable-old' option swaps the behavior of RET and C-j but
+only for the first keypress after beginning completion.
+Specifically, on the first keypress, RET will return an empty
+string and C-j will return the first item on the list. The
+purpose of this is to emulate a legacy compatibility quirk of
+`completing-read'. From the `completing-read' docstring:
 
 > If the input is null, `completing-read' returns DEF, or the
 > first element of the list of default values, or an empty string
 > if DEF is nil, regardless of the value of REQUIRE-MATCH.
 
-If this variable is non-nil, then ido-ubiquitous will attempt to
-emulate this behavior. Specifically, if RET is pressed
-immediately upon entering completion, an empty string will be
-returned instead of the first element in the list. This behavior
-is only enabled when ido is being used as a substitute for
-`completing-read', and not when it is used directly.
-
 This odd behavior is required for compatibility with an old-style
 usage pattern whereby the default was requested by returning an
 empty string. In this mode, the caller receives the empty string
 and handles the default case manually, while `completing-read'
 never has any knowledge of the default. This is a problem for
-ido, which always returns the first element in the list when the
-input is empty. Without knowledge of the default, it cannot
-ensure that the default is first on the list, so returning the
-first item is not the correct behavior. Instead, it must return
-an empty string like `completing-read'.
-
-You can termporarily invert this behavior by prefixing \"RET\"
-with \"C-u\".
-
-If you want to enable old-style default selection selectively for
-specific commands or functions, set appropriate overrides in
-`ido-ubiquitous-command-overrides' or
-`ido-ubiquitous-function-overrides'."
-  :type 'boolean
+ido, which normally returns the first element in the list, not an
+empty string, when the input is empty and you press RET. Without
+knowledge of the default, it cannot ensure that the default is
+first on the list, so returning the first item is not the correct
+behavior. Instead, it must return an empty string like
+`completing-read'.
+
+The `disable' mode is available as a default, which seems
+counterintuitive. But this allows you, if you so desire, to
+enable ido-ubiquitous selectively for only a few specifc commands
+using overrides and disable it for everything else."
+  :type '(choice :tag "Default mode"
+                 (const :menu-tag "Disable"
+                        :tag "Disable ido-ubiquitous"
+                        disable)
+                 (const :menu-tag "Enable"
+                        :tag "Enable ido-ubiquitous in normal default mode"
+                        enable)
+                 (const :menu-tag "Enable old-style default"
+                        :tag "Enable ido-ubiquitous in old-style default mode"
+                        enable-old))
   :group 'ido-ubiquitous)
 
+(make-obsolete-variable
+ 'ido-ubiquitous-enable-old-style-default
+ "This variable no longer has any effect. Set
+`ido-ubiquitous-default-state' to `enable-old' instead."
+ "ido-ubiquitous 2.17")
+
 (defconst ido-ubiquitous-default-command-overrides
   '(;; If you want ido for M-x, install smex
     (disable exact "execute-extended-command")
@@ -391,11 +378,10 @@ The OVERRIDE argument is evaluated normally, so if it is a
 literal symbol, it must be quoted.
 
 See `ido-ubiquitous-command-overrides' for valid override types."
+  (declare (indent 1))
   ;; Eval override
   `(let ((ido-ubiquitous-next-override ,override))
      ,@body))
-(put 'ido-ubiquitous-with-override 'lisp-indent-function
-     (get 'prog1 'lisp-indent-function))
 
 (defun ido-ubiquitous-apply-function-override (func override)
   "Set the override property on FUNC to OVERRIDE and set up advice to apply the override."
@@ -462,7 +448,7 @@ in incorrect behavior if used with ido. Since there is no way to
 tell the difference, this preference defaults to nil, which means
 that ido-ubiquitous will not work when COLLECTION is a function
 unless there is a specific override in effect. To disable this
-safeguard and guarantee breakage on some functions, you may set
+safeguard and GUARANTEE ERRORS on some functions, you may set
 this to non-nil, but this is not recommended."
   :type 'boolean
   :group 'ido-ubiquitous)
@@ -472,89 +458,53 @@ this to non-nil, but this is not recommended."
 ;; These variable are used to make ido-ubiquitous work properly in the
 ;; case that `completing-read' is called recursively (which is
 ;; possible when `enable-recursive-minibuffers' is non-nil.)
-(defvar ido-ubiquitous-next-call-replaces-completing-read nil
+(defvar ido-ubiquitous-enable-next-call nil
   "If non-nil, then the next call to `ido-completing-read' is by ido-ubiquitous.")
-(defvar ido-ubiquitous-this-call-replaces-completing-read nil
+(defvar ido-ubiquitous-enable-this-call nil
   "If non-nil, then the current call to `ido-completing-read' is by ido-ubiquitous.")
 (defvar ido-ubiquitous-next-override nil
   "This holds the override to be applied on the next call to `completing-read'.
 
-It's value can be nil or one of the symbols `disable', `enable', or `enable-old'.
+It's value can be nil or one of the symbols `disable', `enable', or
+`enable-old'.
 
-You should not modify this variable directly. Instead use the macro `ido-ubiquitous-with-override'.")
+You should not modify this variable directly. Instead use the
+macro `ido-ubiquitous-with-override'.")
 (defvar ido-ubiquitous-active-override nil
   "This holds the override being applied to the current call to `completing-read'.
 
-It's value can be nil or one of the symbols `disable', `enable', or `enable-old'.
-
-You should not modify this variable directly. Instead use the macro `ido-ubiquitous-with-override'.")
-
-(defun ido-ubiquitous-completing-read (&rest args)
-  "Wrapper for `ido-completing-read' that enables ido-ubiquitous features.
-
-Unlike `ido-completing-read', this function can return with
-`ido-exit' set to `fallback', and any function that calls this
-should check the value of `ido-exit' and handle this case
-appropriately. For example, see `completing-read-ido'."
-  (let ((ido-ubiquitous-next-call-replaces-completing-read t))
-    (apply 'ido-completing-read args)))
-
-(defadvice ido-completing-read (around detect-replacing-cr activate)
-  "Enable workarounds if this call was done through ido-ubiquitous.
-
-This advice implements the logic required for
-`ido-completing-read' to handle a number of special cases that
-`completing-read' can handle. It only has an effect if
-`ido-completing-read' is called through
-`ido-ubiquitous-completing-read', so other packages that use
-`ido-completing-read', such as `smex', will not be affected."
-  (let* ((orig-args (ad-get-args 0))
-         (ido-ubiquitous-this-call-replaces-completing-read
-          ido-ubiquitous-next-call-replaces-completing-read)
-         (ido-ubiquitous-next-call-replaces-completing-read nil)
-         (error-during-setup nil))
-    (when ido-ubiquitous-this-call-replaces-completing-read
-      (condition-case nil
-          (progn
-            ;; ido doesn't natively handle DEF being a list. If DEF is
-            ;; a list, prepend it to CHOICES and set DEF to just the
-            ;; car of the default list.
-            (when (and def (listp def))
-              (setq choices
-                    (append def
-                            (nreverse (cl-set-difference choices def)))
-                    def (car def)))
-            ;; Work around a bug in ido when both INITIAL-INPUT and
-            ;; DEF are provided More info:
-            ;; https://github.com/technomancy/ido-ubiquitous/issues/18
-            (let ((initial (cond ((null initial-input) "")
-                                 ((stringp initial-input) initial-input)
-                                 ((consp initial-input) (car initial-input))
-                                 (t initial-input))))
-              (when (and def initial
-                         (stringp initial)
-                         (not (string= initial "")))
-                ;; Both default and initial input were provided. So
-                ;; keep the initial input and preprocess the choices
-                ;; list to put the default at the head, then proceed
-                ;; with default = nil.
-                (setq choices (cons def (remove def choices))
-                      def nil))))
-        (error
-         (progn
-           (warn "ido-ubiquitous: failed during setup. Falling back to standard completion")
-           (setq error-during-setup t)))))
-    ;; For ido-ubiquitous, only attempt ido completion if setup
-    ;; completed without error
-    (if (not error-during-setup)
-        ad-do-it
-      (setq ad-return-value
-            (apply ido-ubiquitous-fallback-completing-read-function
-                   orig-args)))))
-
-(defun completing-read-ido (prompt collection &optional predicate
-                                   require-match initial-input
-                                   hist def inherit-input-method)
+It's value can be nil or one of the symbols `disable', `enable', or
+`enable-old'.
+
+You should not modify this variable directly. Instead use the
+macro `ido-ubiquitous-with-override'.")
+(defvar ido-ubiquitous-active-state nil
+  "This holds the ido-ubiquitous mode of operation for the current call to `completing-read'.
+
+It's value can be nil or one of the symbols `disable', `enable', or
+`enable-old'.
+
+You should not modify this variable directly.")
+
+(defadvice ido-completing-read (around ido-ubiquitous activate)
+  "Enable ido-ubiquitous features if this call was done through ido-ubiquitous.
+
+This advice ensures that `ido-ubiquitous-enable-this-call' is set
+properly while `ido-completing-read' is executing. This variable
+is used to determine whether to enable certain behaviors only for
+ido-ubiquitous, not for ordinary ido completion."
+  ;; Set "this" and clear "next" so it doesn't apply to nested calls.
+  (let* ((ido-ubiquitous-enable-this-call ido-ubiquitous-enable-next-call)
+         (ido-ubiquitous-enable-next-call nil))
+    ad-do-it))
+
+;; Signal used to trigger fallback
+(define-error 'ido-ubiquitous-fallback "ido-ubiquitous-fallback")
+
+(defun completing-read-ido-ubiquitous
+    (prompt collection &optional predicate
+            require-match initial-input
+            hist def inherit-input-method)
   "ido-based method for reading from the minibuffer with completion.
 
 See `completing-read' for the meaning of the arguments.
@@ -563,87 +513,48 @@ This function is a wrapper for `ido-completing-read' designed to
 be used as the value of `completing-read-function'. Importantly,
 it detects edge cases that ido cannot handle and uses normal
 completion for them."
-  (let* (;; Save the original arguments in case we need to do the
-         ;; fallback
-         (orig-args
-          (list prompt collection predicate require-match
-                initial-input hist def inherit-input-method))
-         ;; Set the active override and clear the "next" one so it
-         ;; doesn't apply to nested calls.
-         (ido-ubiquitous-active-override ido-ubiquitous-next-override)
-         (ido-ubiquitous-next-override nil)
-         ;; Check for conditions that ido can't or shouldn't handle
-         (ido-allowed
-          (and ido-ubiquitous-mode
-               ;; Check for disable override
-               (not (eq ido-ubiquitous-active-override 'disable))
-               ;; Can't handle this arg
-               (not inherit-input-method)
-               ;; Can't handle this being set
-               (not (bound-and-true-p completion-extra-properties))))
-         ;; Check if ido can handle this collection. If collection is
-         ;; a function, require an override to be ok. Also,
-         ;; collection-ok should never be true when ido-allowed is
-         ;; false.
-         (collection-ok
-          (and ido-allowed
-               (or ido-ubiquitous-allow-on-functional-collection
-                   (not (functionp collection))
-                   (memq ido-ubiquitous-active-override '(enable enable-old)))))
-         ;; Pre-expand list of possible completions, but only if we
-         ;; have a chance of using ido. This is executed after the
-         ;; ido-allowed check to avoid unnecessary work if ido isn't
-         ;; going to used.
-         (_ignore ;; (Return value doesn't matter).
-          (when (and ido-allowed collection-ok)
-            (setq collection (all-completions "" collection predicate)
-                  ;; Don't need this any more
-                  predicate nil)))
-         (collection-ok
-          ;; Don't use ido if the collection is empty or too large.
-          (and collection-ok
-               collection
-               (or (null ido-ubiquitous-max-items)
-                   (<= (length collection) ido-ubiquitous-max-items))))
-         ;; Final check for everything
-         (ido-allowed (and ido-allowed collection-ok))
-         (result
-          (if ido-allowed
-              (ido-ubiquitous-completing-read
-               prompt collection
-               predicate require-match initial-input hist def
-               inherit-input-method)
-            (setq ido-exit 'fallback))))
-    ;; (message "Result: %S" result)
-    ;; (message "ido-exit: %S" ido-exit)
-    ;; Do the fallback if necessary. This could either be because ido
-    ;; can't handle the arguments, or the user indicated during
-    ;; completion that they wanted to fall back to non-ido completion.
-    (if (memq 'fallback (list ido-exit result))
-        (apply ido-ubiquitous-fallback-completing-read-function
-               orig-args)
-      result)))
-
-;; Fallback on magic C-f and C-b
-(defadvice ido-magic-forward-char (before ido-ubiquitous-fallback activate)
-  "Allow falling back in ido-ubiquitous."
-  (when ido-ubiquitous-this-call-replaces-completing-read
-    ;; `ido-context-switch-command' is already let-bound at this
-    ;; point.
-    (setq ido-context-switch-command #'ido-fallback-command)))
-
-(defadvice ido-magic-backward-char (before ido-ubiquitous-fallback activate)
-  "Allow falling back in ido-ubiquitous."
-  (when ido-ubiquitous-this-call-replaces-completing-read
-    ;; `ido-context-switch-command' is already let-bound at this
-    ;; point.
-    (setq ido-context-switch-command #'ido-fallback-command)))
+  (let (;; Save the original arguments in case we need to do the
+        ;; fallback
+        (orig-args
+         (list prompt collection predicate require-match
+               initial-input hist def inherit-input-method)))
+    (condition-case nil
+        (let* (;; Set the active override and clear the "next" one so it
+               ;; doesn't apply to nested calls.
+               (ido-ubiquitous-active-override ido-ubiquitous-next-override)
+               (ido-ubiquitous-next-override nil)
+               ;; Apply the active override, if any
+               (ido-ubiquitous-active-state
+                (or ido-ubiquitous-active-override
+                    ido-ubiquitous-default-state
+                    'enable)))
+          ;; If ido-ubiquitous is disabled this time, fall back
+          (when (eq ido-ubiquitous-active-state 'disable)
+            (signal 'ido-ubiquitous-fallback nil))
+          ;; Handle a collection that is a function: either expand
+          ;; completion list now or fall back
+          (when (functionp collection)
+            (if (or ido-ubiquitous-allow-on-functional-collection
+                    (memq ido-ubiquitous-active-override
+                          '(enable enable-old)))
+                (setq collection (all-completions "" collection predicate))
+              (signal 'ido-ubiquitous-fallback nil)))
+          (let ((ido-ubiquitous-enable-next-call t))
+            (ido-completing-read+
+             prompt collection predicate require-match
+             initial-input hist def inherit-input-method)))
+      ;; Handler for ido-ubiquitous-fallback signal
+      (ido-ubiquitous-fallback
+       (message "Ido-ubiquitous falling back")
+       (apply ido-cr+-fallback-function orig-args)))))
 
 ;;; Old-style default support
 
 (defvar ido-ubiquitous-initial-item nil
   "The first item selected when ido starts.
 
+TODO Rewrite this
+
 This is initialized to the first item in the list of completions
 when ido starts, and is cleared when any character is entered
 into the prompt or the list is cycled. If it is non-nil and still
@@ -656,8 +567,9 @@ the list.")
   (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))))
+  (setq ido-ubiquitous-initial-item
+        (when (and ad-return-value (listp ad-return-value))
+          (car ad-return-value))))
 
 (defadvice ido-next-match (after clear-initial-item activate)
   (setq ido-ubiquitous-initial-item nil))
@@ -665,40 +577,58 @@ the list.")
 (defadvice ido-prev-match (after clear-initial-item activate)
   (setq ido-ubiquitous-initial-item nil))
 
-(defadvice ido-exit-minibuffer (around compatibility activate)
+(defun ido-ubiquitous-should-use-old-style-default ()
+  "Returns non nil if ido-ubiquitous should emulate old-style default.
+
+This function simply encapsulates all the checks that need to be
+done in order to decide whether to swap RET and C-j. See
+`ido-ubiquitous-default-state' for more information."
+  (and
+   ;; Only if completing a list, not a buffer or file
+   (eq ido-cur-item 'list)
+   ;; Only if this call was done through ido-ubiquitous
+   ido-ubiquitous-enable-this-call
+   ;; Only if default is nil
+   (null ido-default-item)
+   ;; Only if input is empty
+   (string= ido-text "")
+   ;; Only if old-style default enabled
+   (eq ido-ubiquitous-active-state 'enable-old)
+   ;; Only if `ido-ubiquitous-initial-item' hasn't been cleared
+   ido-ubiquitous-initial-item
+   ;; Only if initial item hasn't changed
+   (string= (car ido-cur-list)
+            ido-ubiquitous-initial-item)))
+
+(defadvice ido-exit-minibuffer (around old-style-default-compat activate)
   "Emulate a quirk of `completing-read'.
 
 > If the input is null, `completing-read' returns DEF, or the
 > first element of the list of default values, or an empty string
 > if DEF is nil, regardless of the value of REQUIRE-MATCH.
 
-See `ido-ubiquitous-enable-old-style-default', which
-controls whether this advice has any effect."
+See `ido-ubiquitous-default-state', which controls whether this
+advice has any effect."
   (condition-case nil
-      (let* ((enable-oldstyle
-              (and
-               ;; Completing a list, not a buffer or file
-               (eq ido-cur-item 'list)
-               ;; Only enable if we are replacing `completing-read'
-               ido-ubiquitous-this-call-replaces-completing-read
-               ;; Default is nil
-               (null ido-default-item)
-               ;; Input is empty
-               (string= ido-text "")
-               ;; Old-style default enabled
-               (if ido-ubiquitous-active-override
-                   (eq ido-ubiquitous-active-override 'enable-old)
-                 ido-ubiquitous-enable-old-style-default)
-               ;; First item on the list hasn't changed
-               (string= (car ido-cur-list)
-                        ido-ubiquitous-initial-item)))
-             ;; Prefix inverts oldstyle behavior
-             (should-invert current-prefix-arg)
-             (actually-enable-oldstyle
-              (if should-invert (not enable-oldstyle) enable-oldstyle)))
-        (if actually-enable-oldstyle
-            (ido-select-text)
-          ad-do-it))
+      (if (ido-ubiquitous-should-use-old-style-default)
+          (ido-select-text)
+        ad-do-it)
+    (error ad-do-it))
+  (setq ido-ubiquitous-initial-item nil))
+
+(defadvice ido-select-text (around old-style-default-compat activate)
+  "Emulate a quirk of `completing-read'.
+
+> If the input is null, `completing-read' returns DEF, or the
+> first element of the list of default values, or an empty string
+> if DEF is nil, regardless of the value of REQUIRE-MATCH.
+
+See `ido-ubiquitous-default-state', which controls whether this
+advice has any effect."
+  (condition-case nil
+      (if (ido-ubiquitous-should-use-old-style-default)
+          (ido-exit-minibuffer)
+        ad-do-it)
     (error ad-do-it))
   (setq ido-ubiquitous-initial-item nil))
 
@@ -906,12 +836,13 @@ This advice completely overrides the original definition."
   "Do initial setup for ido-ubiquitous.
 
 This only needs to be called once when the file is first loaded."
-  ;; Clean up old versions of ido-ubiquitous that defined advice on
-  ;; `completing-read' instead of modifying
-  ;; `completing-read-function'.
-  (when (ad-find-advice 'completing-read 'around 'ido-ubiquitous)
-    (ad-remove-advice 'completing-read 'around 'ido-ubiquitous)
-    (ad-activate 'completing-read))
+  ;; Clean up old versions of ido-ubiquitous advice if they exist
+  (ignore-errors (ad-remove-advice 'completing-read 'around 'ido-ubiquitous))
+  (ignore-errors (ad-remove-advice 'ido-completing-read 'around 'detect-replacing-cr))
+  (ignore-errors (ad-remove-advice 'ido-magic-forward-char 'before 'ido-ubiquitous-fallback))
+  (ignore-errors (ad-remove-advice 'ido-magic-backward-char 'before 'ido-ubiquitous-fallback))
+  (ignore-errors (ad-remove-advice 'ido-exit-minibuffer 'around 'compatibility))
+  (ad-activate-all)
   ;; Make sure the mode is turned on/off as specified by the value of
   ;; the mode variable
   (ido-ubiquitous-mode (if ido-ubiquitous-mode 1 0)))