;;; minibuffer.el --- Minibuffer completion functions
-;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
;; - extend `boundaries' to provide various other meta-data about the
;; output of `all-completions':
+;; - preferred sorting order when displayed in *Completions*.
+;; - annotations/text-properties to add when displayed in *Completions*.
;; - quoting/unquoting (so we can complete files names with envvars
;; and backslashes, and all-completion can list names without
;; quoting backslashes and dollars).
"Completion of multiple words, each one taken as a prefix.
E.g. M-x l-c-h can complete to list-command-history
and C-x C-f /u/m/s to /usr/monnier/src.")
+ (substring
+ completion-substring-try-completion completion-substring-all-completions
+ "Completion of the string taken as a substring.")
(initials
completion-initials-try-completion completion-initials-all-completions
"Completion of acronyms and initialisms.
(if completions 2 0)
(if exact 1 0)))
+(defun completion--replace (beg end newtext)
+ "Replace the buffer text between BEG and END with NEWTEXT.
+Moves point to the end of the new text."
+ ;; This should be in subr.el.
+ ;; You'd think this is trivial to do, but details matter if you want
+ ;; to keep markers "at the right place" and be robust in the face of
+ ;; after-change-functions that may themselves modify the buffer.
+ (goto-char beg)
+ (insert newtext)
+ (delete-region (point) (+ (point) (- end beg))))
+
(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.
string nil nil t))))
(unchanged (eq t (compare-strings completion nil nil
string nil nil nil))))
- (unless unchanged
-
- ;; Insert in minibuffer the chars we got.
+ (if unchanged
(goto-char end)
- (insert completion)
- (delete-region beg end))
- ;; Move point.
- (goto-char (+ beg comp-pos))
+ ;; Insert in minibuffer the chars we got.
+ (completion--replace beg end completion))
+ ;; Move point to its completion-mandated destination.
+ (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
(exit-minibuffer))
(defvar completion-in-region-functions nil
- "Wrapper hook around `complete-in-region'.
+ "Wrapper hook around `completion-in-region'.
The functions on this special hook are called with 5 arguments:
NEXT-FUN START END COLLECTION PREDICATE.
NEXT-FUN is a function of four arguments (START END COLLECTION PREDICATE)
-that performs the default operation. The other four argument are like
-the ones passed to `complete-in-region'. The functions on this hook
+that performs the default operation. The other four arguments are like
+the ones passed to `completion-in-region'. The functions on this hook
are expected to perform completion on START..END using COLLECTION
and PREDICATE, either by calling NEXT-FUN or by doing it themselves.")
(call-interactively 'minibuffer-complete)
(delete-overlay ol)))))
+(defvar completion-at-point-functions nil
+ "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),
+or a list of the form (START END COLLECTION &rest PROPS) where
+ START and END delimit the entity to complete and should include point,
+ COLLECTION is the completion table to use to complete it, and
+ PROPS is a property list for additional information.
+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."
+ (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)))))))
+
+;;; Key bindings.
+
+(define-obsolete-variable-alias 'minibuffer-local-must-match-filename-map
+ 'minibuffer-local-filename-must-match-map "23.1")
+
(let ((map minibuffer-local-map))
(define-key map "\C-g" 'abort-recursive-edit)
(define-key map "\r" 'exit-minibuffer)
;; 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)
(let* ((beforepoint (substring string 0 point))
(afterpoint (substring string point))
(length completion))))
(let* ((suffix (substring afterpoint (cdr bounds)))
(prefix (substring beforepoint 0 (car bounds)))
- (pattern (delete
- "" (list (substring beforepoint (car bounds))
- 'point
- (substring afterpoint 0 (cdr bounds)))))
+ (pattern (completion-basic--pattern
+ beforepoint afterpoint bounds))
(all (completion-pcm--all-completions prefix pattern table pred)))
(if minibuffer-completing-file-name
(setq all (completion-pcm--filename-try-filter all)))
(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)))
- (pattern (delete
- "" (list (substring beforepoint (car bounds))
- 'point
- (substring afterpoint 0 (cdr bounds)))))
+ (pattern (completion-basic--pattern beforepoint afterpoint bounds))
(all (completion-pcm--all-completions prefix pattern table pred)))
(completion-hilit-commonality all point (car bounds))))
(when completions
(let* ((re (completion-pcm--pattern->regex pattern '(point)))
(case-fold-search completion-ignore-case))
- ;; Remove base-size during mapcar, and add it back later.
(mapcar
(lambda (str)
;; Don't modify the string itself.
'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 'any 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)
- (unless (or (zerop (length str))
- (string-match completion-pcm--delim-wild-regex str))
- (let ((bounds (completion-boundaries str table pred "")))
+ (let ((bounds (completion-boundaries str table pred "")))
+ (unless (or (zerop (length str))
+ ;; Only check within the boundaries, since the
+ ;; boundary char (e.g. /) might be in delim-regexp.
+ (string-match completion-pcm--delim-wild-regex str
+ (car bounds)))
(if (zerop (car bounds))
(mapconcat 'string str "-")
;; If there's a boundary, it's trickier. The main use-case