summaryrefslogtreecommitdiff
path: root/lisp/minibuffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/minibuffer.el')
-rw-r--r--lisp/minibuffer.el324
1 files changed, 235 insertions, 89 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 006e873ac57..78580c86e45 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3,6 +3,7 @@
;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Package: emacs
;; This file is part of GNU Emacs.
@@ -76,6 +77,9 @@
;; the provided string (as is the case in filecache.el), in which
;; case partial-completion (for example) doesn't make any sense
;; and neither does the completions-first-difference highlight.
+;; - indicate how to display the completions in *Completions* (turn
+;; \n into something else, add special boundaries between
+;; completions). E.g. when completing from the kill-ring.
;; - make partial-completion-mode obsolete:
;; - (?) <foo.h> style completion for file names.
@@ -407,6 +411,12 @@ Furthermore, for completions that are done step by step in subfields,
the method is applied to all the preceding fields that do not yet match.
E.g. C-x C-f /u/mo/s TAB could complete to /usr/monnier/src.
Additionally the user can use the char \"*\" as a glob pattern.")
+ (substring
+ completion-substring-try-completion completion-substring-all-completions
+ "Completion of the string taken as a substring.
+I.e. when completing \"foo_bar\" (where _ is the position of point),
+it will consider all completions candidates matching the glob
+pattern \"*foo*bar*\".")
(initials
completion-initials-try-completion completion-initials-all-completions
"Completion of acronyms and initialisms.
@@ -504,6 +514,25 @@ Moves point to the end of the new text."
(delete-region (point) (+ (point) (- end beg)))
(forward-char suffix-len)))
+(defcustom completion-cycle-threshold nil
+ "Number of completion candidates below which cycling is used.
+Depending on this setting `minibuffer-complete' may use cycling,
+like `minibuffer-force-complete'.
+If nil, cycling is never used.
+If t, cycling is always used.
+If an integer, cycling is used as soon as there are fewer completion
+candidates than this number."
+ :type '(choice (const :tag "No cycling" nil)
+ (const :tag "Always cycle" t)
+ (integer :tag "Threshold")))
+
+(defvar completion-all-sorted-completions nil)
+(make-variable-buffer-local 'completion-all-sorted-completions)
+(defvar completion-cycling nil)
+
+(defvar completion-fail-discreetly nil
+ "If non-nil, stay quiet when there is no match.")
+
(defun completion--do-completion (&optional try-completion-function)
"Do the completion and return a summary of what happened.
M = completion was performed, the text was Modified.
@@ -532,11 +561,13 @@ E = after completion we now have an Exact match.
(cond
((null comp)
(minibuffer-hide-completions)
- (ding) (minibuffer-message "No match") (minibuffer--bitset nil nil nil))
+ (unless completion-fail-discreetly
+ (ding) (minibuffer-message "No match"))
+ (minibuffer--bitset nil nil nil))
((eq t comp)
(minibuffer-hide-completions)
(goto-char (field-end))
- (minibuffer--bitset nil nil t)) ;Exact and unique match.
+ (minibuffer--bitset nil nil t)) ;Exact and unique match.
(t
;; `completed' should be t if some completion was done, which doesn't
;; include simply changing the case of the entered string. However,
@@ -556,34 +587,62 @@ E = after completion we now have an Exact match.
(forward-char (- comp-pos (length completion)))
(if (not (or unchanged completed))
- ;; The case of the string changed, but that's all. We're not sure
- ;; whether this is a unique completion or not, so try again using
- ;; the real case (this shouldn't recurse again, because the next
- ;; time try-completion will return either t or the exact string).
- (completion--do-completion try-completion-function)
+ ;; The case of the string changed, but that's all. We're not sure
+ ;; whether this is a unique completion or not, so try again using
+ ;; the real case (this shouldn't recurse again, because the next
+ ;; time try-completion will return either t or the exact string).
+ (completion--do-completion try-completion-function)
;; It did find a match. Do we match some possibility exactly now?
(let ((exact (test-completion completion
minibuffer-completion-table
- minibuffer-completion-predicate)))
- (if completed
- ;; We could also decide to refresh the completions,
- ;; if they're displayed (and assuming there are
- ;; completions left).
- (minibuffer-hide-completions)
- ;; Show the completion table, if requested.
- (cond
- ((not exact)
- (if (case completion-auto-help
- (lazy (eq this-command last-command))
- (t completion-auto-help))
- (minibuffer-completion-help)
- (minibuffer-message "Next char not unique")))
- ;; If the last exact completion and this one were the same, it
- ;; means we've already given a "Next char not unique" message
- ;; and the user's hit TAB again, so now we give him help.
- ((eq this-command last-command)
- (if completion-auto-help (minibuffer-completion-help)))))
+ minibuffer-completion-predicate))
+ (comps
+ ;; Check to see if we want to do cycling. We do it
+ ;; here, after having performed the normal completion,
+ ;; so as to take advantage of the difference between
+ ;; try-completion and all-completions, for things
+ ;; like completion-ignored-extensions.
+ (when (and completion-cycle-threshold
+ ;; Check that the completion didn't make
+ ;; us jump to a different boundary.
+ (or (not completed)
+ (< (car (completion-boundaries
+ (substring completion 0 comp-pos)
+ minibuffer-completion-table
+ minibuffer-completion-predicate
+ ""))
+ comp-pos)))
+ (completion-all-sorted-completions))))
+ (completion--flush-all-sorted-completions)
+ (cond
+ ((and (consp (cdr comps)) ;; There's something to cycle.
+ (not (ignore-errors
+ ;; This signal an (intended) error if comps is too
+ ;; short or if completion-cycle-threshold is t.
+ (consp (nthcdr completion-cycle-threshold comps)))))
+ ;; Fewer than completion-cycle-threshold remaining
+ ;; completions: let's cycle.
+ (setq completed t exact t)
+ (setq completion-all-sorted-completions comps)
+ (minibuffer-force-complete))
+ (completed
+ ;; We could also decide to refresh the completions,
+ ;; if they're displayed (and assuming there are
+ ;; completions left).
+ (minibuffer-hide-completions))
+ ;; Show the completion table, if requested.
+ ((not exact)
+ (if (case completion-auto-help
+ (lazy (eq this-command last-command))
+ (t completion-auto-help))
+ (minibuffer-completion-help)
+ (minibuffer-message "Next char not unique")))
+ ;; If the last exact completion and this one were the same, it
+ ;; means we've already given a "Next char not unique" message
+ ;; and the user's hit TAB again, so now we give him help.
+ ((eq this-command last-command)
+ (if completion-auto-help (minibuffer-completion-help))))
(minibuffer--bitset completed t exact))))))))
@@ -597,21 +656,26 @@ scroll the window of possible completions."
;; If the previous command was not this,
;; mark the completion buffer obsolete.
(unless (eq this-command last-command)
+ (completion--flush-all-sorted-completions)
(setq minibuffer-scroll-window nil))
- (let ((window minibuffer-scroll-window))
+ (cond
;; If there's a fresh completion window with a live buffer,
;; and this command is repeated, scroll that window.
- (if (window-live-p window)
+ ((window-live-p minibuffer-scroll-window)
+ (let ((window minibuffer-scroll-window))
(with-current-buffer (window-buffer window)
(if (pos-visible-in-window-p (point-max) window)
;; If end is in view, scroll up to the beginning.
(set-window-start window (point-min) nil)
;; Else scroll down one screen.
(scroll-other-window))
- nil)
-
- (case (completion--do-completion)
+ nil)))
+ ;; If we're cycling, keep on cycling.
+ ((and completion-cycling completion-all-sorted-completions)
+ (minibuffer-force-complete)
+ t)
+ (t (case (completion--do-completion)
(#b000 nil)
(#b001 (minibuffer-message "Sole completion")
t)
@@ -619,10 +683,8 @@ scroll the window of possible completions."
t)
(t t)))))
-(defvar completion-all-sorted-completions nil)
-(make-variable-buffer-local 'completion-all-sorted-completions)
-
(defun completion--flush-all-sorted-completions (&rest ignore)
+ (setq completion-cycling nil)
(setq completion-all-sorted-completions nil))
(defun completion-all-sorted-completions ()
@@ -664,6 +726,7 @@ Repeated uses step through the possible completions."
(all (completion-all-sorted-completions)))
(if (not (consp all))
(minibuffer-message (if all "No more completions" "No completions"))
+ (setq completion-cycling t)
(goto-char end)
(insert (car all))
(delete-region (+ start (cdr (last all))) end)
@@ -859,13 +922,13 @@ Return nil if there is no valid completion, else t."
(defface completions-annotations '((t :inherit italic))
"Face to use for annotations in the *Completions* buffer.")
-(defcustom completions-format nil
+(defcustom completions-format 'horizontal
"Define the appearance and sorting of completions.
If the value is `vertical', display completions sorted vertically
in columns in the *Completions* buffer.
-If the value is `horizontal' or nil, display completions sorted
+If the value is `horizontal', display completions sorted
horizontally in alphabetical order, rather than down the screen."
- :type '(choice (const nil) (const horizontal) (const vertical))
+ :type '(choice (const horizontal) (const vertical))
:group 'minibuffer
:version "23.2")
@@ -1176,7 +1239,7 @@ Point needs to be somewhere between START and END."
(call-interactively 'minibuffer-complete)
(delete-overlay ol)))))
-(defvar completion-at-point-functions nil
+(defvar completion-at-point-functions '(tags-completion-at-point-function)
"Special hook to find the completion table for the thing at point.
It is called without any argument and should return either nil,
or a function of no argument to perform completion (discouraged),
@@ -1188,24 +1251,31 @@ Currently supported properties are:
`:predicate' a predicate that completion candidates need to satisfy.
`:annotation-function' the value to use for `completion-annotate-function'.")
-(defun completion-at-point ()
- "Complete the thing at point according to local mode.
-This runs the hook `completion-at-point-functions' until a member returns
-non-nil."
- (interactive)
- (let ((res (run-hook-with-args-until-success
- 'completion-at-point-functions)))
- (cond
- ((functionp res) (funcall res))
- (res
- (let* ((plist (nthcdr 3 res))
- (start (nth 0 res))
- (end (nth 1 res))
- (completion-annotate-function
- (or (plist-get plist :annotation-function)
- completion-annotate-function)))
- (completion-in-region start end (nth 2 res)
- (plist-get plist :predicate)))))))
+(defun completion-at-point (&optional arg)
+ "Perform completion on the text around point.
+The completion method is determined by `completion-at-point-functions'.
+
+With a prefix argument, this command does completion within
+the collection of symbols listed in the index of the manual for the
+language you are using."
+ (interactive "P")
+ (if arg
+ (info-complete-symbol)
+ (let ((res (run-hook-with-args-until-success
+ 'completion-at-point-functions)))
+ (cond
+ ((functionp res) (funcall res))
+ (res
+ (let* ((plist (nthcdr 3 res))
+ (start (nth 0 res))
+ (end (nth 1 res))
+ (completion-annotate-function
+ (or (plist-get plist :annotation-function)
+ completion-annotate-function)))
+ (completion-in-region start end (nth 2 res)
+ (plist-get plist :predicate))))))))
+
+(define-obsolete-function-alias 'complete-symbol 'completion-at-point "24.1")
;;; Key bindings.
@@ -1305,12 +1375,19 @@ same as `substitute-in-file-name'."
((eq (car-safe action) 'boundaries)
(let ((start (length (file-name-directory string)))
(end (string-match-p "/" (cdr action))))
- (list* 'boundaries start end)))
-
- ((eq action 'lambda)
- (if (zerop (length string))
- nil ;Not sure why it's here, but it probably doesn't harm.
- (funcall (or pred 'file-exists-p) string)))
+ (list* 'boundaries
+ ;; if `string' is "C:" in w32, (file-name-directory string)
+ ;; returns "C:/", so `start' is 3 rather than 2.
+ ;; Not quite sure what is The Right Fix, but clipping it
+ ;; back to 2 will work for this particular case. We'll
+ ;; see if we can come up with a better fix when we bump
+ ;; into more such problematic cases.
+ (min start (length string)) end)))
+
+ ((eq action 'lambda)
+ (if (zerop (length string))
+ nil ;Not sure why it's here, but it probably doesn't harm.
+ (funcall (or pred 'file-exists-p) string)))
(t
(let* ((name (file-name-nondirectory string))
@@ -1358,19 +1435,20 @@ except that it passes the file name through `substitute-in-file-name'."
(cond
((eq (car-safe action) 'boundaries)
;; For the boundaries, we can't really delegate to
- ;; completion-file-name-table and then fix them up, because it
- ;; would require us to track the relationship between `str' and
+ ;; substitute-in-file-name+completion-file-name-table and then fix
+ ;; them up (as we do for the other actions), because it would
+ ;; require us to track the relationship between `str' and
;; `string', which is difficult. And in any case, if
- ;; substitute-in-file-name turns "fo-$TO-ba" into "fo-o/b-ba", there's
- ;; no way for us to return proper boundaries info, because the
- ;; boundary is not (yet) in `string'.
- ;; FIXME: Actually there is a way to return correct boundaries info,
- ;; at the condition of modifying the all-completions return accordingly.
- (let ((start (length (file-name-directory string)))
- (end (string-match-p "/" (cdr action))))
- (list* 'boundaries start end)))
+ ;; substitute-in-file-name turns "fo-$TO-ba" into "fo-o/b-ba",
+ ;; there's no way for us to return proper boundaries info, because
+ ;; the boundary is not (yet) in `string'.
+ ;;
+ ;; FIXME: Actually there is a way to return correct boundaries
+ ;; info, at the condition of modifying the all-completions
+ ;; return accordingly. But for now, let's not bother.
+ (completion-file-name-table string pred action))
- (t
+ (t
(let* ((default-directory
(if (stringp pred)
;; It used to be that `pred' was abused to pass `dir'
@@ -1382,7 +1460,9 @@ except that it passes the file name through `substitute-in-file-name'."
(substitute-in-file-name string)
(error string)))
(comp (completion-file-name-table
- str (or pred read-file-name-predicate) action)))
+ str
+ (with-no-warnings (or pred read-file-name-predicate))
+ action)))
(cond
((stringp comp)
@@ -1712,6 +1792,12 @@ Return the new suffix."
;; Nothing to merge.
suffix))
+(defun completion-basic--pattern (beforepoint afterpoint bounds)
+ (delete
+ "" (list (substring beforepoint (car bounds))
+ 'point
+ (substring afterpoint 0 (cdr bounds)))))
+
(defun completion-basic-try-completion (string table pred point)
(lexical-let*
((beforepoint (substring string 0 point))
@@ -1782,6 +1868,14 @@ expression (not containing character ranges like `a-z')."
:group 'minibuffer
:type 'string)
+(defcustom completion-pcm-complete-word-inserts-delimiters nil
+ "Treat the SPC or - inserted by `minibuffer-complete-word' as delimiters.
+Those chars are treated as delimiters iff this variable is non-nil.
+I.e. if non-nil, M-x SPC will just insert a \"-\" in the minibuffer, whereas
+if nil, it will list all possible commands in *Completions* because none of
+the commands start with a \"-\" or a SPC."
+ :type 'boolean)
+
(defun completion-pcm--pattern-trivial-p (pattern)
(and (stringp (car pattern))
;; It can be followed by `point' and "" and still be trivial.
@@ -1794,7 +1888,7 @@ expression (not containing character ranges like `a-z')."
(defun completion-pcm--string->pattern (string &optional point)
"Split STRING into a pattern.
A pattern is a list where each element is either a string
-or a symbol chosen among `any', `star', `point'."
+or a symbol chosen among `any', `star', `point', `prefix'."
(if (and point (< point (length string)))
(let ((prefix (substring string 0 point))
(suffix (substring string point)))
@@ -1807,11 +1901,12 @@ or a symbol chosen among `any', `star', `point'."
(while (and (setq p (string-match completion-pcm--delim-wild-regex
string p))
- ;; If the char was added by minibuffer-complete-word, then
- ;; don't treat it as a delimiter, otherwise "M-x SPC"
- ;; ends up inserting a "-" rather than listing
- ;; all completions.
- (not (get-text-property p 'completion-try-word string)))
+ (or completion-pcm-complete-word-inserts-delimiters
+ ;; If the char was added by minibuffer-complete-word,
+ ;; then don't treat it as a delimiter, otherwise
+ ;; "M-x SPC" ends up inserting a "-" rather than listing
+ ;; all completions.
+ (not (get-text-property p 'completion-try-word string))))
;; Usually, completion-pcm--delim-wild-regex matches a delimiter,
;; meaning that something can be added *before* it, but it can also
;; match a prefix and postfix, in which case something can be added
@@ -1837,11 +1932,10 @@ or a symbol chosen among `any', `star', `point'."
(concat "\\`"
(mapconcat
(lambda (x)
- (case x
- ((star any point)
- (if (if (consp group) (memq x group) group)
- "\\(.*?\\)" ".*?"))
- (t (regexp-quote x))))
+ (cond
+ ((stringp x) (regexp-quote x))
+ ((if (consp group) (memq x group) group) "\\(.*?\\)")
+ (t ".*?")))
pattern
""))))
;; Avoid pathological backtracking.
@@ -1997,6 +2091,17 @@ filter out additional entries (because TABLE migth not obey PRED)."
(nconc (completion-pcm--hilit-commonality pattern all)
(length prefix)))))
+(defun completion--sreverse (str)
+ "Like `reverse' but for a string STR rather than a list."
+ (apply 'string (nreverse (mapcar 'identity str))))
+
+(defun completion--common-suffix (strs)
+ "Return the common suffix of the strings STRS."
+ (completion--sreverse
+ (try-completion
+ ""
+ (mapcar 'completion--sreverse strs))))
+
(defun completion-pcm--merge-completions (strs pattern)
"Extract the commonality in STRS, with the help of PATTERN."
;; When completing while ignoring case, we want to try and avoid
@@ -2058,7 +2163,17 @@ filter out additional entries (because TABLE migth not obey PRED)."
;; `any' into a `star' because the surrounding context has
;; changed such that string->pattern wouldn't add an `any'
;; here any more.
- (unless unique (push elem res))
+ (unless unique
+ (push elem res)
+ (when (memq elem '(star point prefix))
+ ;; Extract common suffix additionally to common prefix.
+ ;; Only do it for `point', `star', and `prefix' since for
+ ;; `any' it could lead to a merged completion that
+ ;; doesn't itself match the candidates.
+ (let ((suffix (completion--common-suffix comps)))
+ (assert (stringp suffix))
+ (unless (equal suffix "")
+ (push suffix res)))))
(setq fixed "")))))
;; We return it in reverse order.
res)))))
@@ -2067,8 +2182,7 @@ filter out additional entries (because TABLE migth not obey PRED)."
(mapconcat (lambda (x) (cond
((stringp x) x)
((eq x 'star) "*")
- ((eq x 'any) "")
- ((eq x 'point) "")))
+ (t ""))) ;any, point, prefix.
pattern
""))
@@ -2110,6 +2224,7 @@ filter out additional entries (because TABLE migth not obey PRED)."
(pointpat (or (memq 'point mergedpat)
(memq 'any mergedpat)
(memq 'star mergedpat)
+ ;; Not `prefix'.
mergedpat))
;; New pos from the start.
(newpos (length (completion-pcm--pattern->string pointpat)))
@@ -2127,7 +2242,38 @@ filter out additional entries (because TABLE migth not obey PRED)."
'completion-pcm--filename-try-filter))
(completion-pcm--merge-try pattern all prefix suffix)))
-;;; Initials completion
+;;; Substring completion
+;; Mostly derived from the code of `basic' completion.
+
+(defun completion-substring--all-completions (string table pred point)
+ (let* ((beforepoint (substring string 0 point))
+ (afterpoint (substring string point))
+ (bounds (completion-boundaries beforepoint table pred afterpoint))
+ (suffix (substring afterpoint (cdr bounds)))
+ (prefix (substring beforepoint 0 (car bounds)))
+ (basic-pattern (completion-basic--pattern
+ beforepoint afterpoint bounds))
+ (pattern (if (not (stringp (car basic-pattern)))
+ basic-pattern
+ (cons 'prefix basic-pattern)))
+ (all (completion-pcm--all-completions prefix pattern table pred)))
+ (list all pattern prefix suffix (car bounds))))
+
+(defun completion-substring-try-completion (string table pred point)
+ (destructuring-bind (all pattern prefix suffix carbounds)
+ (completion-substring--all-completions string table pred point)
+ (if minibuffer-completing-file-name
+ (setq all (completion-pcm--filename-try-filter all)))
+ (completion-pcm--merge-try pattern all prefix suffix)))
+
+(defun completion-substring-all-completions (string table pred point)
+ (destructuring-bind (all pattern prefix suffix carbounds)
+ (completion-substring--all-completions string table pred point)
+ (when all
+ (nconc (completion-pcm--hilit-commonality pattern all)
+ (length prefix)))))
+
+;; Initials completion
;; Complete /ums to /usr/monnier/src or lch to list-command-history.
(defun completion-initials-expand (str table pred)