summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJambunathan K <kjambunathan@gmail.com>2012-11-29 16:32:24 -0500
committerStefan Monnier <monnier@iro.umontreal.ca>2012-11-29 16:32:24 -0500
commitcc37e70f6699cbadb1a8f5467e8dc9fcea986aa1 (patch)
treed0bd2e2dc9ebf2f2a958c7acb9cff788f11788ca
parent83e12fe07c18a6190c6c5ef6e959697eb0ac9f19 (diff)
downloademacs-cc37e70f6699cbadb1a8f5467e8dc9fcea986aa1.tar.gz
* lisp/icomplete.el: Change separator; add ido-style commands.
(icomplete-show-key-bindings): Remove custom var. (icomplete-get-keys): Remove function. (icomplete-forward-completions, icomplete-backward-completions): New commands. (icomplete-minibuffer-map): New var. (icomplete-minibuffer-setup): Use it. (icomplete-exhibit): Don't delay if the list of completions is known. (icomplete-separator): New custom. (icomplete-completions): Use it. * lisp/minibuffer.el (completion-all-sorted-completions): Delete duplicates. (minibuffer-force-complete-and-exit): New command. (minibuffer--complete-and-exit): New function extracted from minibuffer-complete-and-exit. (minibuffer-complete-and-exit): Use it.
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/ChangeLog19
-rw-r--r--lisp/icomplete.el107
-rw-r--r--lisp/minibuffer.el42
4 files changed, 116 insertions, 56 deletions
diff --git a/etc/NEWS b/etc/NEWS
index f0f4e6fb84e..fb86920303a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -29,6 +29,10 @@ so we will look at it and add it to the manual.
* Changes in Specialized Modes and Packages in Emacs 24.4
+** Icomplete is a bit more like IDO.
+*** key bindings to navigate through and select the completions.
+*** The icomplete-separator is customizable, and its default has changed.
+*** Removed icomplete-show-key-bindings.
** Calc
*** Calc by default now uses the Gregorian calendar for all dates, and
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 20de699a5ed..73a58600ba2 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,4 +1,21 @@
-2012-11-29 Stefan Monnier <monnier@iro.umontreal.ca>
+2012-11-29 Jambunathan K <kjambunathan@gmail.com>
+ Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * icomplete.el: Change separator; add ido-style commands.
+ (icomplete-show-key-bindings): Remove custom var.
+ (icomplete-get-keys): Remove function.
+ (icomplete-forward-completions, icomplete-backward-completions):
+ New commands.
+ (icomplete-minibuffer-map): New var.
+ (icomplete-minibuffer-setup): Use it.
+ (icomplete-exhibit): Don't delay if the list of completions is known.
+ (icomplete-separator): New custom.
+ (icomplete-completions): Use it.
+ * minibuffer.el (completion-all-sorted-completions): Delete duplicates.
+ (minibuffer-force-complete-and-exit): New command.
+ (minibuffer--complete-and-exit): New function extracted from
+ minibuffer-complete-and-exit.
+ (minibuffer-complete-and-exit): Use it.
* progmodes/etags.el (visit-tags-table-buffer): Give a more precise
error message when the file doesn't exist (bug#12974).
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index a4e3e339470..768692281f8 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -71,6 +71,11 @@
(make-obsolete-variable
'icomplete-prospects-length 'icomplete-prospects-height "23.1")
+(defcustom icomplete-separator " | "
+ "String used by icomplete to separate alternatives in the minibuffer."
+ :type 'string
+ :version "24.3")
+
;;;_* User Customization variables
(defcustom icomplete-prospects-height
;; 20 is an estimated common size for the prompt + minibuffer content, to
@@ -97,11 +102,6 @@ See `icomplete-delay-completions-threshold'."
:type 'integer
:group 'icomplete)
-(defcustom icomplete-show-key-bindings t
- "If non-nil, show key bindings as well as completion for sole matches."
- :type 'boolean
- :group 'icomplete)
-
(defcustom icomplete-minibuffer-setup-hook nil
"Icomplete-specific customization of minibuffer setup.
@@ -145,23 +145,6 @@ Use `icomplete-mode' function to set it up properly for incremental
minibuffer completion.")
(add-hook 'icomplete-post-command-hook 'icomplete-exhibit)
-(defun icomplete-get-keys (func-name)
- "Return strings naming keys bound to FUNC-NAME, or nil if none.
-Examines the prior, not current, buffer, presuming that current buffer
-is minibuffer."
- (when (commandp func-name)
- (save-excursion
- (let* ((sym (intern func-name))
- (buf (other-buffer nil t))
- (keys (with-current-buffer buf (where-is-internal sym))))
- (when keys
- (concat "<"
- (mapconcat 'key-description
- (sort keys
- #'(lambda (x y)
- (< (length x) (length y))))
- ", ")
- ">"))))))
;;;_ = icomplete-with-completion-tables
(defvar icomplete-with-completion-tables '(internal-complete-buffer)
"Specialized completion tables with which icomplete should operate.
@@ -169,6 +152,37 @@ is minibuffer."
Icomplete does not operate with any specialized completion tables
except those on this list.")
+(defvar icomplete-minibuffer-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\M-\t] 'minibuffer-force-complete)
+ (define-key map [?\C-j] 'minibuffer-force-complete-and-exit)
+ (define-key map [?\C-s] 'icomplete-forward-completions)
+ (define-key map [?\C-r] 'icomplete-backward-completions)
+ map))
+
+(defun icomplete-forward-completions ()
+ "Step forward completions by one entry.
+Second entry becomes the first and can be selected with
+`minibuffer-force-complete-and-exit'."
+ (interactive)
+ (let* ((comps (completion-all-sorted-completions))
+ (last (last comps)))
+ (setcdr last (cons (car comps) (cdr last)))
+ (completion--cache-all-sorted-completions (cdr comps))))
+
+(defun icomplete-backward-completions ()
+ "Step backward completions by one entry.
+Last entry becomes the first and can be selected with
+`minibuffer-force-complete-and-exit'."
+ (interactive)
+ (let* ((comps (completion-all-sorted-completions))
+ (last-but-one (last comps 2))
+ (last (cdr last-but-one)))
+ (when last
+ (setcdr last-but-one (cdr last))
+ (push (car last) comps)
+ (completion--cache-all-sorted-completions comps))))
+
;;;_ > icomplete-mode (&optional prefix)
;;;###autoload
(define-minor-mode icomplete-mode
@@ -208,6 +222,8 @@ Conditions are:
Usually run by inclusion in `minibuffer-setup-hook'."
(when (and icomplete-mode (icomplete-simple-completing-p))
(set (make-local-variable 'completion-show-inline-help) nil)
+ (use-local-map (make-composed-keymap icomplete-minibuffer-map
+ (current-local-map)))
(add-hook 'pre-command-hook
(lambda () (let ((non-essential t))
(run-hooks 'icomplete-pre-command-hook)))
@@ -239,27 +255,29 @@ and `minibuffer-setup-hook'."
(goto-char (point-max))
; Insert the match-status information:
(if (and (> (point-max) (minibuffer-prompt-end))
- buffer-undo-list ; Wait for some user input.
- (or
- ;; Don't bother with delay after certain number of chars:
- (> (- (point) (field-beginning)) icomplete-max-delay-chars)
- ;; Don't delay if alternatives number is small enough:
- (and (sequencep minibuffer-completion-table)
- (< (length minibuffer-completion-table)
- icomplete-delay-completions-threshold))
- ;; Delay - give some grace time for next keystroke, before
+ buffer-undo-list ; Wait for some user input.
+ (or
+ ;; Don't bother with delay after certain number of chars:
+ (> (- (point) (field-beginning)) icomplete-max-delay-chars)
+ ;; Don't delay if the completions are known.
+ completion-all-sorted-completions
+ ;; Don't delay if alternatives number is small enough:
+ (and (sequencep minibuffer-completion-table)
+ (< (length minibuffer-completion-table)
+ icomplete-delay-completions-threshold))
+ ;; Delay - give some grace time for next keystroke, before
;; embarking on computing completions:
(sit-for icomplete-compute-delay)))
(let ((text (while-no-input
- (icomplete-completions
- (field-string)
- minibuffer-completion-table
- minibuffer-completion-predicate
+ (icomplete-completions
+ (field-string)
+ minibuffer-completion-table
+ minibuffer-completion-predicate
(not minibuffer-completion-confirm))))
(buffer-undo-list t)
deactivate-mark)
;; Do nothing if while-no-input was aborted.
- (when (stringp text)
+ (when (stringp text)
(move-overlay icomplete-overlay (point) (point) (current-buffer))
;; The current C cursor code doesn't know to use the overlay's
;; marker's stickiness to figure out whether to place the cursor
@@ -365,17 +383,14 @@ are exhibited within the square braces.)"
(if prospects
(concat determ
"{"
- (and most-is-exact ",")
- (mapconcat 'identity (nreverse prospects) ",")
- (and limit ",...")
+ (and most-is-exact
+ (substring icomplete-separator
+ (string-match "[^ ]" icomplete-separator)))
+ (mapconcat 'identity (nreverse prospects)
+ icomplete-separator)
+ (and limit (concat icomplete-separator "…"))
"}")
- (concat determ
- " [Matched"
- (let ((keys (and icomplete-show-key-bindings
- (commandp (intern-soft most))
- (icomplete-get-keys most))))
- (if keys (concat "; " keys) ""))
- "]"))))))
+ (concat determ " [Matched]"))))))
;;_* Local emacs vars.
;;Local variables:
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 6e704fad807..7fe50e930ce 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1106,6 +1106,13 @@ scroll the window of possible completions."
(sort-fun (completion-metadata-get all-md 'cycle-sort-function)))
(when last
(setcdr last nil)
+
+ ;; Delete duplicates: do it after setting last's cdr to nil (so
+ ;; it's a proper list), and be careful to reset `last' since it
+ ;; may be a different cons-cell.
+ (setq all (delete-dups all))
+ (setq last (last all))
+
(setq all (if sort-fun (funcall sort-fun all)
;; Prefer shorter completions, by default.
(sort all (lambda (c1 c2) (< (length c1) (length c2))))))
@@ -1120,6 +1127,15 @@ scroll the window of possible completions."
;; all possibilities.
(completion--cache-all-sorted-completions (nconc all base-size))))))
+(defun minibuffer-force-complete-and-exit ()
+ "Complete the minibuffer with first of the matches and exit."
+ (interactive)
+ (minibuffer-force-complete)
+ (minibuffer--complete-and-exit
+ ;; If the previous completion completed to an element which fails
+ ;; test-completion, then we shouldn't exit, but that should be rare.
+ (lambda () (minibuffer-message "Incomplete"))))
+
(defun minibuffer-force-complete ()
"Complete the minibuffer to an exact match.
Repeated uses step through the possible completions."
@@ -1192,6 +1208,22 @@ If `minibuffer-completion-confirm' is `confirm-after-completion',
`minibuffer-confirm-exit-commands', and accept the input
otherwise."
(interactive)
+ (minibuffer--complete-and-exit
+ (lambda ()
+ (pcase (condition-case nil
+ (completion--do-completion nil 'expect-exact)
+ (error 1))
+ ((or #b001 #b011) (exit-minibuffer))
+ (#b111 (if (not minibuffer-completion-confirm)
+ (exit-minibuffer)
+ (minibuffer-message "Confirm")
+ nil))
+ (_ nil)))))
+
+(defun minibuffer--complete-and-exit (completion-function)
+ "Exit from `require-match' minibuffer.
+COMPLETION-FUNCTION is called if the current buffer's content does not
+appear to be a match."
(let ((beg (field-beginning))
(end (field-end)))
(cond
@@ -1239,15 +1271,7 @@ If `minibuffer-completion-confirm' is `confirm-after-completion',
(t
;; Call do-completion, but ignore errors.
- (pcase (condition-case nil
- (completion--do-completion nil 'expect-exact)
- (error 1))
- ((or #b001 #b011) (exit-minibuffer))
- (#b111 (if (not minibuffer-completion-confirm)
- (exit-minibuffer)
- (minibuffer-message "Confirm")
- nil))
- (_ nil))))))
+ (funcall completion-function)))))
(defun completion--try-word-completion (string table predicate point md)
(let ((comp (completion-try-completion string table predicate point md)))