Skip to content

Commit

Permalink
Overhaul compatibility mode
Browse files Browse the repository at this point in the history
Now compatibilty is only activated if the current call to
"ido-completing-read" was done through the ido-ubiquitous wrapper
"completing-read-ido". The new implementation now also works with
recursive minibuffers.

This *should* fix both #16 and #17, which I previously thought might
be mutually exclusive.
  • Loading branch information
DarwinAwardWinner committed Sep 3, 2012
1 parent 6a86f22 commit 49de8ee
Showing 1 changed file with 59 additions and 47 deletions.
106 changes: 59 additions & 47 deletions ido-ubiquitous.el
Expand Up @@ -121,6 +121,9 @@ ido-ubiquitous in non-interactive functions, customize
(define-obsolete-variable-alias 'ido-ubiquitous-exceptions
'ido-ubiquitous-command-exceptions "0.4")

(defvar ido-next-call-replaces-completing-read nil)
(defvar ido-this-call-replaces-completing-read nil)

(defun completing-read-ido (prompt collection &optional predicate
require-match initial-input
hist def inherit-input-method)
Expand All @@ -141,13 +144,22 @@ be used as the value of `completing-read-function'."
;; Only use ido completion if there are actually any completions
;; to offer.
(if allcomp
(ido-completing-read prompt allcomp
nil require-match initial-input hist def)
(let ((ido-next-call-replaces-completing-read t))
(ido-completing-read prompt allcomp
nil require-match initial-input hist def))
(funcall ido-ubiquitous-orig-completing-read-function
prompt collection predicate
require-match initial-input
hist def inherit-input-method)))))

(defadvice ido-completing-read (around detect-replacing-cr activate)
(if ido-next-call-replaces-completing-read
(let ((ido-next-call-replaces-completing-read nil)
(ido-this-call-replaces-completing-read t))
ad-do-it)
(let ((ido-this-call-replaces-completing-read nil))
ad-do-it)))

(defmacro ido-ubiquitous-disable-in (func)
"Disable ido-ubiquitous in FUNC."
(let ((docstring
Expand Down Expand Up @@ -232,35 +244,34 @@ already.)"
: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."
"Allow ido to emulate a 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'.
When this mode is enabled, you can still select the first item on
the list by prefixing \"RET\" with \"C-u\"."
:type 'boolean
:group 'ido-ubiquitous)

Expand All @@ -280,29 +291,30 @@ This has no effect when ido is completing buffers or files."
(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)
(defadvice ido-exit-minibuffer (around compatibility 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
> 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-compatibility', which controls whether
this advice has any effect."
(if (and (eq ido-cur-item 'list)
ido-ubiquitous-enable-compatibility
;; Only enable if we are replacing `completing-read'
ido-this-call-replaces-completing-read
;; Input is empty
(string= ido-text "")
;; Default is nil
(null ido-default-item)
;; Prefix disables compatibility
(not current-prefix-arg)
(string= ido-text "")
(string= (car ido-cur-list)
ido-ubiquitous-initial-item))
(ido-select-text)
ad-do-it))
ad-do-it)
(setq ido-ubiquitous-initial-item nil))

(defadvice bookmark-completing-read (around disable-ido-compatibility activate)
"`bookmark-completing-read' uses `completing-read' in an odd
Expand Down

0 comments on commit 49de8ee

Please sign in to comment.