;;; 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>
;;; Todo:
-;; - make partial-complete-mode obsolete:
+;; - 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).
+;; - indicate how to turn all-completion's output into
+;; try-completion's output: e.g. completion-ignored-extensions.
+;; maybe that could be merged with the "quote" operation above.
+;; - completion hook to run when the completion is
+;; selected/inserted (maybe this should be provided some other
+;; way, e.g. as text-property, so `try-completion can also return it?)
+;; both for when it's inserted via TAB or via choose-completion.
+;; - indicate that `all-completions' doesn't do prefix-completion
+;; but just returns some list that relates in some other way to
+;; 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.
+
+;; - make partial-completion-mode obsolete:
;; - (?) <foo.h> style completion for file names.
;; This can't be done identically just by tweaking completion,
;; because partial-completion-mode's behavior is to expand <string.h>
"Apply FUN to each element of XS in turn.
Return the first non-nil returned value.
Like CL's `some'."
- (let ((firsterror nil)
- res)
+ (lexical-let ((firsterror nil)
+ res)
(while (and (not res) xs)
(condition-case err
(setq res (funcall fun (pop xs)))
(defconst completion-styles-alist
'((emacs21
completion-emacs21-try-completion completion-emacs21-all-completions
- "Simple prefix-based completion.")
+ "Simple prefix-based completion.
+I.e. when completing \"foo_bar\" (where _ is the position of point),
+it will consider all completions candidates matching the glob
+pattern \"foobar*\".")
(emacs22
completion-emacs22-try-completion completion-emacs22-all-completions
- "Prefix completion that only operates on the text before point.")
+ "Prefix completion that only operates on the text before point.
+I.e. when completing \"foo_bar\" (where _ is the position of point),
+it will consider all completions candidates matching the glob
+pattern \"foo*\" and will add back \"bar\" to the end of it.")
(basic
completion-basic-try-completion completion-basic-all-completions
- "Completion of the prefix before point and the suffix after point.")
+ "Completion of the prefix before point and the suffix after point.
+I.e. when completing \"foo_bar\" (where _ is the position of point),
+it will consider all completions candidates matching the glob
+pattern \"foo*bar*\".")
(partial-completion
completion-pcm-try-completion completion-pcm-all-completions
"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.")
+I.e. when completing \"l-co_h\" (where _ is the position of point),
+it will consider all completions candidates matching the glob
+pattern \"l*-co*h*\".
+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.")
(initials
completion-initials-try-completion completion-initials-all-completions
"Completion of acronyms and initialisms.
follow the calling convention of `completion-all-completions'),
and DOC describes the way this style of completion works.")
-(defcustom completion-styles '(basic partial-completion emacs22)
+(defcustom completion-styles
+ ;; First, use `basic' because prefix completion has been the standard
+ ;; for "ever" and works well in most cases, so using it first
+ ;; ensures that we obey previous behavior in most cases.
+ '(basic
+ ;; Then use `partial-completion' because it has proven to
+ ;; be a very convenient extension.
+ partial-completion
+ ;; Finally use `emacs22' so as to maintain (in many/most cases)
+ ;; the previous behavior that when completing "foobar" with point
+ ;; between "foo" and "bar" the completion try to complete "foo"
+ ;; and simply add "bar" to the end of the result.
+ emacs22)
"List of completion styles to use.
The available styles are listed in `completion-styles-alist'."
:type `(repeat (choice ,@(mapcar (lambda (x) (list 'const (car x)))
POINT is the position of point within STRING.
The return value is a list of completions and may contain the base-size
in the last `cdr'."
- ;; FIXME: We need to additionally return completion-extra-size (similar
- ;; to completion-base-size but for the text after point).
+ ;; FIXME: We need to additionally return the info needed for the
+ ;; second part of completion-base-position.
(completion--some (lambda (style)
(funcall (nth 2 (assq style completion-styles-alist))
string table pred point))
(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."
+ ;; Maybe 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.
+ (let ((prefix-len 0))
+ ;; Don't touch markers in the shared prefix (if any).
+ (while (and (< prefix-len (length newtext))
+ (< (+ beg prefix-len) end)
+ (eq (char-after (+ beg prefix-len))
+ (aref newtext prefix-len)))
+ (setq prefix-len (1+ prefix-len)))
+ (unless (zerop prefix-len)
+ (setq beg (+ beg prefix-len))
+ (setq newtext (substring newtext prefix-len))))
+ (let ((suffix-len 0))
+ ;; Don't touch markers in the shared suffix (if any).
+ (while (and (< suffix-len (length newtext))
+ (< beg (- end suffix-len))
+ (eq (char-before (- end suffix-len))
+ (aref newtext (- (length newtext) suffix-len 1))))
+ (setq suffix-len (1+ suffix-len)))
+ (unless (zerop suffix-len)
+ (setq end (- end suffix-len))
+ (setq newtext (substring newtext 0 (- suffix-len)))))
+ (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.
101 5 ??? impossible
110 6 some completion happened
111 7 completed to an exact completion"
- (let* ((beg (field-beginning))
- (end (field-end))
- (string (buffer-substring beg end))
- (comp (funcall (or try-completion-function
- 'completion-try-completion)
- string
- minibuffer-completion-table
- minibuffer-completion-predicate
- (- (point) beg))))
+ (lexical-let*
+ ((beg (field-beginning))
+ (end (field-end))
+ (string (buffer-substring beg end))
+ (comp (funcall (or try-completion-function
+ 'completion-try-completion)
+ string
+ minibuffer-completion-table
+ minibuffer-completion-predicate
+ (- (point) beg))))
(cond
((null comp)
(minibuffer-hide-completions)
;; `completed' should be t if some completion was done, which doesn't
;; include simply changing the case of the entered string. However,
;; for appearance, the string is rewritten if the case changes.
- (let* ((comp-pos (cdr comp))
- (completion (car comp))
- (completed (not (eq t (compare-strings completion nil nil
- string nil nil t))))
- (unchanged (eq t (compare-strings completion nil nil
- string nil nil nil))))
- (unless unchanged
-
+ (lexical-let*
+ ((comp-pos (cdr comp))
+ (completion (car comp))
+ (completed (not (eq t (compare-strings completion nil nil
+ string nil nil t))))
+ (unchanged (eq t (compare-strings completion nil nil
+ string nil nil nil))))
+ (if unchanged
+ (goto-char end)
;; Insert in minibuffer the chars we got.
- (goto-char end)
- (insert completion)
- (delete-region beg end))
- ;; Move point.
- (goto-char (+ beg comp-pos))
+ (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
`minibuffer-confirm-exit-commands', and accept the input
otherwise."
(interactive)
- (let ((beg (field-beginning))
- (end (field-end)))
+ (lexical-let ((beg (field-beginning))
+ (end (field-end)))
(cond
;; Allow user to specify null string
((= beg end) (exit-minibuffer))
((test-completion (buffer-substring beg end)
minibuffer-completion-table
minibuffer-completion-predicate)
+ ;; FIXME: completion-ignore-case has various slightly
+ ;; incompatible meanings. E.g. it can reflect whether the user
+ ;; wants completion to pay attention to case, or whether the
+ ;; string will be used in a context where case is significant.
+ ;; E.g. usually try-completion should obey the first, whereas
+ ;; test-completion should obey the second.
(when completion-ignore-case
;; Fixup case of the field, if necessary.
(let* ((string (buffer-substring beg end))
string
minibuffer-completion-table
minibuffer-completion-predicate)))
- (when (and (stringp compl)
+ (when (and (stringp compl) (not (equal string compl))
;; If it weren't for this piece of paranoia, I'd replace
;; the whole thing with a call to do-completion.
;; This is important, e.g. when the current minibuffer's
(delete-region beg end))))
(exit-minibuffer))
- ((eq minibuffer-completion-confirm 'confirm)
+ ((memq minibuffer-completion-confirm '(confirm confirm-after-completion))
;; The user is permitted to exit with an input that's rejected
;; by test-completion, after confirming her choice.
- (if (eq last-command this-command)
+ (if (or (eq last-command this-command)
+ ;; For `confirm-after-completion' we only ask for confirmation
+ ;; if trying to exit immediately after typing TAB (this
+ ;; catches most minibuffer typos).
+ (and (eq minibuffer-completion-confirm 'confirm-after-completion)
+ (not (memq last-command minibuffer-confirm-exit-commands))))
(exit-minibuffer)
(minibuffer-message "Confirm")
nil))
- ((eq minibuffer-completion-confirm 'confirm-after-completion)
- ;; Similar to the above, but only if trying to exit immediately
- ;; after typing TAB (this catches most minibuffer typos).
- (if (memq last-command minibuffer-confirm-exit-commands)
- (progn (minibuffer-message "Confirm")
- nil)
- (exit-minibuffer)))
-
(t
;; Call do-completion, but ignore errors.
(case (condition-case nil
(defface completions-annotations '((t :inherit italic))
"Face to use for annotations in the *Completions* buffer.")
+(defcustom completions-format nil
+ "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
+horizontally in alphabetical order, rather than down the screen."
+ :type '(choice (const nil) (const horizontal) (const vertical))
+ :group 'minibuffer
+ :version "23.2")
+
(defun completion--insert-strings (strings)
"Insert a list of STRINGS into the current buffer.
Uses columns to keep the listing readable but compact.
(max 1 (/ (length strings) 2))))
(colwidth (/ wwidth columns))
(column 0)
+ (rows (/ (length strings) columns))
+ (row 0)
(laststring nil))
;; The insertion should be "sensible" no matter what choices were made
;; for the parameters above.
(+ (string-width (car str))
(string-width (cadr str)))
(string-width str))))
- (unless (bolp)
- (if (< wwidth (+ (max colwidth length) column))
- ;; No space for `str' at point, move to next line.
- (progn (insert "\n") (setq column 0))
- (insert " \t")
- ;; Leave the space unpropertized so that in the case we're
- ;; already past the goal column, there is still
- ;; a space displayed.
- (set-text-properties (- (point) 1) (point)
- ;; We can't just set tab-width, because
- ;; completion-setup-function will kill all
- ;; local variables :-(
- `(display (space :align-to ,column)))
- nil))
+ (cond
+ ((eq completions-format 'vertical)
+ ;; Vertical format
+ (when (> row rows)
+ (forward-line (- -1 rows))
+ (setq row 0 column (+ column colwidth)))
+ (when (> column 0)
+ (end-of-line)
+ (while (> (current-column) column)
+ (if (eobp)
+ (insert "\n")
+ (forward-line 1)
+ (end-of-line)))
+ (insert " \t")
+ (set-text-properties (- (point) 1) (point)
+ `(display (space :align-to ,column)))))
+ (t
+ ;; Horizontal format
+ (unless (bolp)
+ (if (< wwidth (+ (max colwidth length) column))
+ ;; No space for `str' at point, move to next line.
+ (progn (insert "\n") (setq column 0))
+ (insert " \t")
+ ;; Leave the space unpropertized so that in the case we're
+ ;; already past the goal column, there is still
+ ;; a space displayed.
+ (set-text-properties (- (point) 1) (point)
+ ;; We can't just set tab-width, because
+ ;; completion-setup-function will kill all
+ ;; local variables :-(
+ `(display (space :align-to ,column)))
+ nil))))
(if (not (consp str))
(put-text-property (point) (progn (insert str) (point))
'mouse-face 'highlight)
'mouse-face 'highlight)
(add-text-properties (point) (progn (insert (cadr str)) (point))
'(mouse-face nil
- face completions-annotations)))
- ;; Next column to align to.
- (setq column (+ column
- ;; Round up to a whole number of columns.
- (* colwidth (ceiling length colwidth))))))))))
+ face completions-annotations)))
+ (cond
+ ((eq completions-format 'vertical)
+ ;; Vertical format
+ (if (> column 0)
+ (forward-line)
+ (insert "\n"))
+ (setq row (1+ row)))
+ (t
+ ;; Horizontal format
+ ;; Next column to align to.
+ (setq column (+ column
+ ;; Round up to a whole number of columns.
+ (* colwidth (ceiling length colwidth))))))))))))
(defvar completion-common-substring nil)
(make-obsolete-variable 'completion-common-substring nil "23.1")
"Display a list of possible completions of the current minibuffer contents."
(interactive)
(message "Making completion list...")
- (let* ((start (field-beginning))
- (string (field-string))
- (completions (completion-all-completions
- string
- minibuffer-completion-table
- minibuffer-completion-predicate
- (- (point) (field-beginning)))))
+ (lexical-let* ((start (field-beginning))
+ (string (field-string))
+ (completions (completion-all-completions
+ string
+ minibuffer-completion-table
+ minibuffer-completion-predicate
+ (- (point) (field-beginning)))))
(message nil)
(if (and completions
(or (consp (cdr completions))
(not (equal (car completions) string))))
- (with-output-to-temp-buffer "*Completions*"
- (let* ((last (last completions))
- (base-size (cdr last)))
+ (let* ((last (last completions))
+ (base-size (cdr last))
+ ;; If the *Completions* buffer is shown in a new
+ ;; window, mark it as softly-dedicated, so bury-buffer in
+ ;; minibuffer-hide-completions will know whether to
+ ;; delete the window or not.
+ (display-buffer-mark-dedicated 'soft))
+ (with-output-to-temp-buffer "*Completions*"
;; Remove the base-size tail because `sort' requires a properly
;; nil-terminated list.
(when last (setcdr last nil))
(if ann (list s ann) s)))
completions)))
(with-current-buffer standard-output
- (set (make-local-variable 'completion-base-position)
- ;; FIXME: We should provide the END part as well, but
- ;; currently completion-all-completions does not give
- ;; us the necessary information.
- (list (+ start base-size) nil)))
+ (set (make-local-variable 'completion-base-position)
+ ;; FIXME: We should provide the END part as well, but
+ ;; currently completion-all-completions does not give
+ ;; us the necessary information.
+ (list (+ start base-size) nil)))
(display-completion-list completions)))
;; If there are no completions, or if the current input is already the
(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.")
(defun completion-in-region (start end collection &optional predicate)
"Complete the text between START and END using COLLECTION.
+Return nil if there is no valid completion, else t.
Point needs to be somewhere between START and END."
- ;; FIXME: some callers need to setup completion-ignore-case,
- ;; completion-ignored-extensions. The latter can be embedded in the
- ;; completion tables, but the first cannot (actually, maybe it should).
(assert (<= start (point)) (<= (point) end))
;; FIXME: undisplay the *Completions* buffer once the completion is done.
(with-wrapper-hook
(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.
+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)))))))
+
+;;; 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)
;; 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)))
(declare-function x-file-dialog "xfns.c"
(prompt dir &optional default-filename mustmatch only-dir-p))
+(defun read-file-name-defaults (&optional dir initial)
+ (let ((default
+ (cond
+ ;; With non-nil `initial', use `dir' as the first default.
+ ;; Essentially, this mean reversing the normal order of the
+ ;; current directory name and the current file name, i.e.
+ ;; 1. with normal file reading:
+ ;; 1.1. initial input is the current directory
+ ;; 1.2. the first default is the current file name
+ ;; 2. with non-nil `initial' (e.g. for `find-alternate-file'):
+ ;; 2.2. initial input is the current file name
+ ;; 2.1. the first default is the current directory
+ (initial (abbreviate-file-name dir))
+ ;; In file buffers, try to get the current file name
+ (buffer-file-name
+ (abbreviate-file-name buffer-file-name))))
+ (file-name-at-point
+ (run-hook-with-args-until-success 'file-name-at-point-functions)))
+ (when file-name-at-point
+ (setq default (delete-dups
+ (delete "" (delq nil (list file-name-at-point default))))))
+ ;; Append new defaults to the end of existing `minibuffer-default'.
+ (append
+ (if (listp minibuffer-default) minibuffer-default (list minibuffer-default))
+ (if (listp default) default (list default)))))
+
(defun read-file-name (prompt &optional dir default-filename mustmatch initial predicate)
"Read file name, prompting with PROMPT and completing in directory DIR.
Value is not expanded---you must call `expand-file-name' yourself.
(lexical-let ((dir (file-name-as-directory
(expand-file-name dir))))
(minibuffer-with-setup-hook
- (lambda () (setq default-directory dir))
+ (lambda ()
+ (setq default-directory dir)
+ ;; When the first default in `minibuffer-default'
+ ;; duplicates initial input `insdef',
+ ;; reset `minibuffer-default' to nil.
+ (when (equal (or (car-safe insdef) insdef)
+ (or (car-safe minibuffer-default)
+ minibuffer-default))
+ (setq minibuffer-default
+ (cdr-safe minibuffer-default)))
+ ;; On the first request on `M-n' fill
+ ;; `minibuffer-default' with a list of defaults
+ ;; relevant for file-name reading.
+ (set (make-local-variable 'minibuffer-default-add-function)
+ (lambda ()
+ (with-current-buffer
+ (window-buffer (minibuffer-selected-window))
+ (read-file-name-defaults dir initial)))))
(completing-read prompt 'read-file-name-internal
pred mustmatch insdef
'file-name-history default-filename)))
suffix))
(defun completion-basic-try-completion (string table pred point)
- (let* ((beforepoint (substring string 0 point))
- (afterpoint (substring string point))
- (bounds (completion-boundaries beforepoint table pred afterpoint)))
+ (lexical-let*
+ ((beforepoint (substring string 0 point))
+ (afterpoint (substring string point))
+ (bounds (completion-boundaries beforepoint table pred afterpoint)))
(if (zerop (cdr bounds))
;; `try-completion' may return a subtly different result
;; than `all+merge', so try to use it whenever possible.
(concat completion
(completion--merge-suffix completion point afterpoint))
(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)))))
- (all (completion-pcm--all-completions prefix pattern table pred)))
+ (lexical-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)))))
+ (all (completion-pcm--all-completions prefix pattern table pred)))
(if minibuffer-completing-file-name
(setq all (completion-pcm--filename-try-filter all)))
(completion-pcm--merge-try pattern all prefix suffix)))))
(defun completion-basic-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)))
- (pattern (delete
- "" (list (substring beforepoint (car bounds))
- 'point
- (substring afterpoint 0 (cdr bounds)))))
- (all (completion-pcm--all-completions prefix pattern table pred)))
+ (lexical-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)))))
+ (all (completion-pcm--all-completions prefix pattern table pred)))
(completion-hilit-commonality all point (car bounds))))
;;; Partial-completion-mode style completion.
(defun completion-pcm--prepare-delim-re (delims)
(setq completion-pcm--delim-wild-regex (concat "[" delims "*]")))
-(defcustom completion-pcm-word-delimiters "-_. "
+(defcustom completion-pcm-word-delimiters "-_./: "
"A string of characters treated as word delimiters for completion.
Some arcane rules:
If `]' is in this string, it must come first.
(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.
FILTER is a function applied to the return value, that can be used, e.g. to
filter out additional entries (because TABLE migth not obey PRED)."
(unless filter (setq filter 'identity))
- (let* ((beforepoint (substring string 0 point))
- (afterpoint (substring string point))
- (bounds (completion-boundaries beforepoint table pred afterpoint))
- (prefix (substring beforepoint 0 (car bounds)))
- (suffix (substring afterpoint (cdr bounds)))
- firsterror)
+ (lexical-let*
+ ((beforepoint (substring string 0 point))
+ (afterpoint (substring string point))
+ (bounds (completion-boundaries beforepoint table pred afterpoint))
+ (prefix (substring beforepoint 0 (car bounds)))
+ (suffix (substring afterpoint (cdr bounds)))
+ firsterror)
(setq string (substring string (car bounds) (+ point (cdr bounds))))
(let* ((relpoint (- point (car bounds)))
(pattern (completion-pcm--string->pattern string relpoint))
;; order of preference) either at the old point, or at
;; the last place where there's something to choose, or
;; at the very end.
- (pointpat (or (memq 'point mergedpat) (memq 'any mergedpat)
+ (pointpat (or (memq 'point mergedpat)
+ (memq 'any mergedpat)
+ (memq 'star mergedpat)
mergedpat))
;; New pos from the start.
(newpos (length (completion-pcm--pattern->string pointpat)))
;; 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
(when newstr
(completion-pcm-try-completion newstr table pred (length newstr)))))
+\f
+;; Miscellaneous
+
+(defun minibuffer-insert-file-name-at-point ()
+ "Get a file name at point in original buffer and insert it to minibuffer."
+ (interactive)
+ (let ((file-name-at-point
+ (with-current-buffer (window-buffer (minibuffer-selected-window))
+ (run-hook-with-args-until-success 'file-name-at-point-functions))))
+ (when file-name-at-point
+ (insert file-name-at-point))))
(provide 'minibuffer)