* bitmaps/README:
[bpt/emacs.git] / lisp / minibuffer.el
index de69f53..87318f8 100644 (file)
 
 ;;; Commentary:
 
-;; Names starting with "minibuffer--" are for functions and variables that
-;; are meant to be for internal use only.
+;; Names with "--" are for functions and variables that are meant to be for
+;; internal use only.
+
+;; Functional completion tables have an extended calling conventions:
+;; - If completion-all-completions-with-base-size is set, then all-completions
+;;   should return the base-size in the last cdr.
+;; - The `action' can be (additionally to nil, t, and lambda) of the form
+;;   (boundaries . SUFFIX) in which case it should return
+;;   (boundaries START . END).  See `completion-boundaries'.
+;;   Any other return value should be ignored (so we ignore values returned
+;;   from completion tables that don't know about this new `action' form).
+;;   See `completion-boundaries'.
+
+;;; Bugs:
+
+;; - completion-all-sorted-completions list all the completions, whereas
+;;   it should only lists the ones that `try-completion' would consider.
+;;   E.g.  it should honor completion-ignored-extensions.
+;; - choose-completion can't automatically figure out the boundaries
+;;   corresponding to the displayed completions.  `base-size' gives the left
+;;   boundary, but not the righthand one.  So we need to add
+;;   completion-extra-size (and also completion-no-auto-exit).
 
 ;;; Todo:
 
+;; - make lisp-complete-symbol and sym-comp use it.
+;; - add support for ** to pcm.
 ;; - Make read-file-name-predicate obsolete.
-;; - New command minibuffer-force-complete that chooses one of all-completions.
 ;; - Add vc-file-name-completion-table to read-file-name-internal.
 ;; - A feature like completing-help.el.
+;; - make lisp/complete.el obsolete.
 ;; - Make the `hide-spaces' arg of all-completions obsolete?
 
 ;;; Code:
@@ -43,14 +65,37 @@ element in the returned list of completions.  See `completion-base-size'.")
 
 ;;; Completion table manipulation
 
+;; New completion-table operation.
+(defun completion-boundaries (string table pred suffix)
+  "Return the boundaries of the completions returned by TABLE for STRING.
+STRING is the string on which completion will be performed.
+SUFFIX is the string after point.
+The result is of the form (START . END) where START is the position
+in STRING of the beginning of the completion field and END is the position
+in SUFFIX of the end of the completion field.
+I.e. START is the same as the `completion-base-size'.
+E.g. for simple completion tables, the result is always (0 . (length SUFFIX))
+and for file names the result is the positions delimited by
+the closest directory separators."
+  (let ((boundaries (if (functionp table)
+                        (funcall table string pred (cons 'boundaries suffix)))))
+    (if (not (eq (car-safe boundaries) 'boundaries))
+        (setq boundaries nil))
+    (cons (or (cadr boundaries) 0)
+          (or (cddr boundaries) (length suffix)))))
+
 (defun completion--some (fun xs)
   "Apply FUN to each element of XS in turn.
 Return the first non-nil returned value.
 Like CL's `some'."
-  (let (res)
+  (let ((firsterror nil)
+        res)
     (while (and (not res) xs)
-      (setq res (funcall fun (pop xs))))
-    res))
+      (condition-case err
+          (setq res (funcall fun (pop xs)))
+        (error (unless firsterror (setq firsterror err)) nil)))
+    (or res
+        (if firsterror (signal (car firsterror) (cdr firsterror))))))
 
 (defun apply-partially (fun &rest args)
   "Do a \"curried\" partial application of FUN to ARGS.
@@ -66,13 +111,17 @@ STRING is the string to complete.
 TABLE is the completion table, which should not be a function.
 PRED is a completion predicate.
 ACTION can be one of nil, t or `lambda'."
-  ;; (assert (not (functionp table)))
-  (funcall
-   (cond
-    ((null action) 'try-completion)
-    ((eq action t) 'all-completions)
-    (t 'test-completion))
-   string table pred))
+  (cond
+   ((functionp table) (funcall table string pred action))
+   ((eq (car-safe action) 'boundaries)
+    (cons 'boundaries (completion-boundaries string table pred (cdr action))))
+   (t
+    (funcall
+     (cond
+      ((null action) 'try-completion)
+      ((eq action t) 'all-completions)
+      (t 'test-completion))
+     string table pred))))
 
 (defun completion-table-dynamic (fun)
   "Use function FUN as a dynamic completion table.
@@ -83,7 +132,7 @@ the value of its argument.  If completion is performed in the minibuffer,
 FUN will be called in the buffer from which the minibuffer was entered.
 
 The result of the `dynamic-completion-table' form is a function
-that can be used as the ALIST argument to `try-completion' and
+that can be used as the COLLECTION argument to `try-completion' and
 `all-completions'.  See Info node `(elisp)Programmed Completion'."
   (lexical-let ((fun fun))
     (lambda (string pred action)
@@ -112,8 +161,7 @@ You should give VAR a non-nil `risky-local-variable' property."
 
 (defun completion-table-with-context (prefix table string pred action)
   ;; TODO: add `suffix' maybe?
-  ;; Notice that `pred' is not a predicate when called from read-file-name
-  ;; or Info-read-node-name-2.
+  ;; Notice that `pred' may not be a function in some abusive cases.
   (when (functionp pred)
     (setq pred
           (lexical-let ((pred pred))
@@ -129,18 +177,22 @@ You should give VAR a non-nil `risky-local-variable' property."
              (t                         ;Lists and alists.
               (lambda (s)
                 (funcall pred (concat prefix (if (consp s) (car s) s)))))))))
-  (let ((comp (complete-with-action action table string pred)))
-    (cond
-     ;; In case of try-completion, add the prefix.
-     ((stringp comp) (concat prefix comp))
-     ;; In case of non-empty all-completions,
-     ;; add the prefix size to the base-size.
-     ((consp comp)
-      (let ((last (last comp)))
-        (when completion-all-completions-with-base-size
-          (setcdr last (+ (or (cdr last) 0) (length prefix))))
-        comp))
-     (t comp))))
+  (if (eq (car-safe action) 'boundaries)
+      (let* ((len (length prefix))
+             (bound (completion-boundaries string table pred (cdr action))))
+        (list* 'boundaries (+ (car bound) len) (cdr bound)))
+    (let ((comp (complete-with-action action table string pred)))
+      (cond
+       ;; In case of try-completion, add the prefix.
+       ((stringp comp) (concat prefix comp))
+       ;; In case of non-empty all-completions,
+       ;; add the prefix size to the base-size.
+       ((consp comp)
+        (let ((last (last comp)))
+          (when completion-all-completions-with-base-size
+            (setcdr last (+ (or (cdr last) 0) (length prefix))))
+          comp))
+       (t comp)))))
 
 (defun completion-table-with-terminator (terminator table string pred action)
   (cond
@@ -152,7 +204,18 @@ You should give VAR a non-nil `risky-local-variable' property."
                  (eq (try-completion comp table pred) t))
             (concat comp terminator)
           comp))))
-   ((eq action t) (all-completions string table pred))
+   ((eq action t)
+    ;; FIXME: We generally want the `try' and `all' behaviors to be
+    ;; consistent so pcm can merge the `all' output to get the `try' output,
+    ;; but that sometimes clashes with the need for `all' output to look
+    ;; good in *Completions*.
+    ;; (let* ((all (all-completions string table pred))
+    ;;        (last (last all))
+    ;;        (base-size (cdr last)))
+    ;;   (when all
+    ;;     (setcdr all nil)
+    ;;     (nconc (mapcar (lambda (s) (concat s terminator)) all) base-size)))
+    (all-completions string table pred))
    ;; completion-table-with-terminator is always used for
    ;; "sub-completions" so it's only called if the terminator is missing,
    ;; in which case `test-completion' should return nil.
@@ -219,7 +282,14 @@ If ARGS are provided, then pass MESSAGE through `format'."
                     (copy-sequence message)
                   (concat " [" message "]")))
   (when args (setq message (apply 'format message args)))
-  (let ((ol (make-overlay (point-max) (point-max) nil t t)))
+  (let ((ol (make-overlay (point-max) (point-max) nil t t))
+       ;; A quit during sit-for normally only interrupts the sit-for,
+        ;; but since minibuffer-message is used at the end of a command,
+        ;; at a time when the command has virtually finished already, a C-g
+        ;; should really cause an abort-recursive-edit instead (i.e. as if
+        ;; the C-g had been typed at top-level).  Binding inhibit-quit here
+        ;; is an attempt to get that behavior.
+       (inhibit-quit t))
     (unwind-protect
         (progn
           (unless (zerop (length message))
@@ -297,10 +367,10 @@ Only the elements of table that satisfy predicate PRED are considered.
 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'."
-  ;; The property `completion-styles' indicates that this functional
-  ;; completion-table claims to take care of completion styles itself.
-  ;; [I.e. It will most likely call us back at some point. ]
   (let ((completion-all-completions-with-base-size t))
+    ;; The property `completion-styles' indicates that this functional
+    ;; completion-table claims to take care of completion styles itself.
+    ;; [I.e. It will most likely call us back at some point. ]
     (if (and (symbolp table) (get table 'completion-styles))
         ;; Extended semantics for functional completion-tables:
         ;; They accept a 4th argument `point' and when called with action=t
@@ -417,19 +487,75 @@ scroll the window of possible completions."
          nil)
 
       (case (completion--do-completion)
-        (0 nil)
-        (1 (goto-char (field-end))
-           (minibuffer-message "Sole completion")
-           t)
-        (3 (goto-char (field-end))
-           (minibuffer-message "Complete, but not unique")
-           t)
-        (t t)))))
+        (#b000 nil)
+        (#b001 (goto-char (field-end))
+               (minibuffer-message "Sole completion")
+               t)
+        (#b011 (goto-char (field-end))
+               (minibuffer-message "Complete, but not unique")
+               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-all-sorted-completions nil))
+
+(defun completion-all-sorted-completions ()
+  (or completion-all-sorted-completions
+      (let* ((start (field-beginning))
+             (end (field-end))
+             (all (completion-all-completions (buffer-substring start end)
+                                              minibuffer-completion-table
+                                              minibuffer-completion-predicate
+                                              (- (point) start)))
+             (last (last all))
+             (base-size (or (cdr last) 0)))
+        (when last
+          (setcdr last nil)
+          ;; Prefer shorter completions.
+          (setq all (sort all (lambda (c1 c2) (< (length c1) (length c2)))))
+          ;; Prefer recently used completions.
+          (let ((hist (symbol-value minibuffer-history-variable)))
+            (setq all (sort all (lambda (c1 c2)
+                                  (> (length (member c1 hist))
+                                     (length (member c2 hist)))))))
+          ;; Cache the result.  This is not just for speed, but also so that
+          ;; repeated calls to minibuffer-force-complete can cycle through
+          ;; all possibilities.
+          (add-hook 'after-change-functions
+                    'completion--flush-all-sorted-completions nil t)
+          (setq completion-all-sorted-completions
+                (nconc all base-size))))))
+
+(defun minibuffer-force-complete ()
+  "Complete the minibuffer to an exact match.
+Repeated uses step through the possible completions."
+  (interactive)
+  ;; FIXME: Need to deal with the extra-size issue here as well.
+  (let* ((start (field-beginning))
+         (end (field-end))
+         (all (completion-all-sorted-completions)))
+    (if (not (consp all))
+        (minibuffer-message (if all "No more completions" "No completions"))
+      (goto-char end)
+      (insert (car all))
+      (delete-region (+ start (cdr (last all))) end)
+      ;; If completing file names, (car all) may be a directory, so we'd now
+      ;; have a new set of possible completions and might want to reset
+      ;; completion-all-sorted-completions to nil, but we prefer not to,
+      ;; so that repeated calls minibuffer-force-complete still cycle
+      ;; through the previous possible completions.
+      (setq completion-all-sorted-completions (cdr all)))))
 
 (defun minibuffer-complete-and-exit ()
   "If the minibuffer contents is a valid completion then exit.
 Otherwise try to complete it.  If completion leads to a valid completion,
-a repetition of this command will exit."
+a repetition of this command will exit.
+If `minibuffer-completion-confirm' is equal to `confirm', then do not
+try to complete, but simply ask for confirmation and accept any
+input if confirmed."
   (interactive)
   (let ((beg (field-beginning))
         (end (field-end)))
@@ -449,6 +575,10 @@ a repetition of this command will exit."
           (when (and (stringp 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
+                     ;; content is a directory which only contains a single
+                     ;; file, so `try-completion' actually completes to
+                     ;; that file.
                      (= (length string) (length compl)))
             (goto-char end)
             (insert compl)
@@ -468,11 +598,11 @@ a repetition of this command will exit."
       (case (condition-case nil
                 (completion--do-completion)
               (error 1))
-        ((1 3) (exit-minibuffer))
-        (7 (if (not minibuffer-completion-confirm)
-               (exit-minibuffer)
-             (minibuffer-message "Confirm")
-             nil))
+        ((#b001 #b011) (exit-minibuffer))
+        (#b111 (if (not minibuffer-completion-confirm)
+                   (exit-minibuffer)
+                 (minibuffer-message "Confirm")
+                 nil))
         (t nil))))))
 
 (defun completion--try-word-completion (string table predicate point)
@@ -486,6 +616,14 @@ a repetition of this command will exit."
         (let ((exts '(" " "-"))
               (before (substring string 0 point))
               (after (substring string point))
+              ;; If the user hasn't entered any text yet, then she
+              ;; presumably hits SPC to see the *completions*, but
+              ;; partial-completion will often find a " " or a "-" to match.
+              ;; So disable partial-completion in that situation.
+              (completion-styles
+               (or (and (equal string "")
+                        (remove 'partial-completion completion-styles))
+                   completion-styles))
              tem)
          (while (and exts (not (consp tem)))
             (setq tem (completion-try-completion
@@ -561,14 +699,14 @@ is added, provided that matches some possible completion.
 Return nil if there is no valid completion, else t."
   (interactive)
   (case (completion--do-completion 'completion--try-word-completion)
-    (0 nil)
-    (1 (goto-char (field-end))
-       (minibuffer-message "Sole completion")
-       t)
-    (3 (goto-char (field-end))
-       (minibuffer-message "Complete, but not unique")
-       t)
-    (t t)))
+    (#b000 nil)
+    (#b001 (goto-char (field-end))
+           (minibuffer-message "Sole completion")
+           t)
+    (#b011 (goto-char (field-end))
+           (minibuffer-message "Complete, but not unique")
+           t)
+    (t     t)))
 
 (defun completion--insert-strings (strings)
   "Insert a list of STRINGS into the current buffer.
@@ -778,6 +916,40 @@ specified by COMMON-SUBSTRING."
     (ding))
   (exit-minibuffer))
 
+;;; 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)
+  (define-key map "\n" 'exit-minibuffer))
+
+(let ((map minibuffer-local-completion-map))
+  (define-key map "\t" 'minibuffer-complete)
+  ;; M-TAB is already abused for many other purposes, so we should find
+  ;; another binding for it.
+  ;; (define-key map "\e\t" 'minibuffer-force-complete)
+  (define-key map " " 'minibuffer-complete-word)
+  (define-key map "?" 'minibuffer-completion-help))
+
+(let ((map minibuffer-local-must-match-map))
+  (define-key map "\r" 'minibuffer-complete-and-exit)
+  (define-key map "\n" 'minibuffer-complete-and-exit))
+
+(let ((map minibuffer-local-filename-completion-map))
+  (define-key map " " nil))
+(let ((map minibuffer-local-filename-must-match-map))
+  (define-key map " " nil))
+
+(let ((map minibuffer-local-ns-map))
+  (define-key map " " 'exit-minibuffer)
+  (define-key map "\t" 'exit-minibuffer)
+  (define-key map "?" 'self-insert-and-exit))
+
+;;; Completion tables.
+
 (defun minibuffer--double-dollars (str)
   (replace-regexp-in-string "\\$" "$$" str))
 
@@ -786,24 +958,43 @@ specified by COMMON-SUBSTRING."
             (substring enventry 0 (string-match "=" enventry)))
           process-environment))
 
+(defconst completion--embedded-envvar-re
+  (concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)"
+          "$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'"))
+
 (defun completion--embedded-envvar-table (string pred action)
-  (when (string-match (concat "\\(?:^\\|[^$]\\(?:\\$\\$\\)*\\)"
-                              "$\\([[:alnum:]_]*\\|{\\([^}]*\\)\\)\\'")
-                      string)
-    (let* ((beg (or (match-beginning 2) (match-beginning 1)))
-           (table (completion--make-envvar-table))
-           (prefix (substring string 0 beg)))
-      (if (eq (aref string (1- beg)) ?{)
-          (setq table (apply-partially 'completion-table-with-terminator
-                                       "}" table)))
-      (completion-table-with-context prefix table
-                                     (substring string beg)
-                                     pred action))))
+  (if (eq (car-safe action) 'boundaries)
+      ;; Compute the boundaries of the subfield to which this
+      ;; completion applies.
+      (let ((suffix (cdr action)))
+        (if (string-match completion--embedded-envvar-re string)
+            (list* 'boundaries
+                   (or (match-beginning 2) (match-beginning 1))
+                   (when (string-match "[^[:alnum:]_]" suffix)
+                     (match-beginning 0)))))
+    (when (string-match completion--embedded-envvar-re string)
+      (let* ((beg (or (match-beginning 2) (match-beginning 1)))
+             (table (completion--make-envvar-table))
+             (prefix (substring string 0 beg)))
+        (if (eq (aref string (1- beg)) ?{)
+            (setq table (apply-partially 'completion-table-with-terminator
+                                         "}" table)))
+        (completion-table-with-context
+         prefix table (substring string beg) pred action)))))
 
 (defun completion--file-name-table (string pred action)
   "Internal subroutine for `read-file-name'.  Do not call this."
-  (if (and (zerop (length string)) (eq 'lambda action))
-      nil                               ; FIXME: why?
+  (cond
+   ((and (zerop (length string)) (eq 'lambda action))
+    nil)                                ; FIXME: why?
+   ((eq (car-safe action) 'boundaries)
+    ;; FIXME: Actually, this is not always right in the presence of
+    ;; envvars, but there's not much we can do, I think.
+    (let ((start (length (file-name-directory string)))
+          (end (string-match "/" (cdr action))))
+      (list* 'boundaries start end)))
+
+   (t
     (let* ((dir (if (stringp pred)
                     ;; It used to be that `pred' was abused to pass `dir'
                     ;; as an argument.
@@ -834,8 +1025,8 @@ specified by COMMON-SUBSTRING."
 
        ((eq action t)
         (let ((all (file-name-all-completions name realdir))
-              ;; Actually, this is not always right in the presence of
-              ;; envvars, but there's not much we can do, I think.
+              ;; FIXME: Actually, this is not always right in the presence
+              ;; of envvars, but there's not much we can do, I think.
               (base-size (length (file-name-directory string))))
 
           ;; Check the predicate, if necessary.
@@ -857,14 +1048,13 @@ specified by COMMON-SUBSTRING."
 
           (if (and completion-all-completions-with-base-size (consp all))
               ;; Add base-size, but only if the list is non-empty.
-              (nconc all base-size))
-
-          all))
+              (nconc all base-size)
+            all)))
 
        (t
         ;; Only other case actually used is ACTION = lambda.
         (let ((default-directory dir))
-          (funcall (or read-file-name-predicate 'file-exists-p) str)))))))
+          (funcall (or read-file-name-predicate 'file-exists-p) str))))))))
 
 (defalias 'read-file-name-internal
   (completion-table-in-turn 'completion--embedded-envvar-table
@@ -878,7 +1068,7 @@ specified by COMMON-SUBSTRING."
   "Current predicate used by `read-file-name-internal'.")
 
 (defcustom read-file-name-completion-ignore-case
-  (if (memq system-type '(ms-dos windows-nt darwin macos vax-vms axp-vms))
+  (if (memq system-type '(ms-dos windows-nt darwin))
       t nil)
   "Non-nil means when reading a file name completion ignores case."
   :group 'minibuffer
@@ -1039,7 +1229,7 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
                       (not (equal (if (consp name) (car name) name) except)))
                     nil)))
 
-;;; Old-style completion, used in Emacs-21.
+;;; Old-style completion, used in Emacs-21 and Emacs-22.
 
 (defun completion-emacs21-try-completion (string table pred point)
   (let ((completion (try-completion string table pred)))
@@ -1049,11 +1239,9 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
 
 (defun completion-emacs21-all-completions (string table pred point)
   (completion-hilit-commonality
-   (all-completions string table pred t)
+   (all-completions string table pred)
    (length string)))
 
-;;; Basic completion, used in Emacs-22.
-
 (defun completion-emacs22-try-completion (string table pred point)
   (let ((suffix (substring string point))
         (completion (try-completion (substring string 0 point) table pred)))
@@ -1076,36 +1264,68 @@ Like `internal-complete-buffer', but removes BUFFER from the completion list."
 
 (defun completion-emacs22-all-completions (string table pred point)
   (completion-hilit-commonality
-   (all-completions (substring string 0 point) table pred t)
+   (all-completions (substring string 0 point) table pred)
    point))
 
-(defun completion-basic-try-completion (string table pred point)
-  (let ((suffix (substring string point))
-        (completion (try-completion (substring string 0 point) table pred)))
-    (if (not (stringp completion))
-        completion
-      ;; Merge end of completion with beginning of suffix.
-      ;; Simple generalization of the "merge trailing /" done in Emacs-22.
-      (when (and (not (zerop (length suffix)))
-                 (string-match "\\(.+\\)\n\\1" (concat completion "\n" suffix)
-                               ;; Make sure we don't compress things to less
-                               ;; than we started with.
-                               point)
-                 ;; Just make sure we didn't match some other \n.
-                 (eq (match-end 1) (length completion)))
-        (setq suffix (substring suffix (- (match-end 1) (match-beginning 1)))))
+;;; Basic completion.
+
+(defun completion--merge-suffix (completion point suffix)
+  "Merge end of COMPLETION with beginning of SUFFIX.
+Simple generalization of the \"merge trailing /\" done in Emacs-22.
+Return the new suffix."
+  (if (and (not (zerop (length suffix)))
+           (string-match "\\(.+\\)\n\\1" (concat completion "\n" suffix)
+                         ;; Make sure we don't compress things to less
+                         ;; than we started with.
+                         point)
+           ;; Just make sure we didn't match some other \n.
+           (eq (match-end 1) (length completion)))
+      (substring suffix (- (match-end 1) (match-beginning 1)))
+    ;; Nothing to merge.
+    suffix))
 
-      (cons (concat completion suffix) (length completion)))))
-
-(defalias 'completion-basic-all-completions 'completion-emacs22-all-completions)
+(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)))
+    (if (zerop (cdr bounds))
+        ;; `try-completion' may return a subtly different result
+        ;; than `all+merge', so try to use it whenever possible.
+        (let ((completion (try-completion beforepoint table pred)))
+          (if (not (stringp completion))
+              completion
+            (cons
+             (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)))
+        (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)))
+    (completion-hilit-commonality
+     (if (consp all) (nconc all (car bounds)) all)
+     point)))
 
 ;;; Partial-completion-mode style completion.
 
-;; BUGS:
-
-;; - "minibuffer-s- TAB" with minibuffer-selected-window ends up with
-;;   "minibuffer--s-" which matches other options.
-
 (defvar completion-pcm--delim-wild-regex nil)
 
 (defun completion-pcm--prepare-delim-re (delims)
@@ -1130,13 +1350,13 @@ expression (not containing character ranges like `a-z')."
 (defun completion-pcm--pattern-trivial-p (pattern)
   (and (stringp (car pattern)) (null (cdr pattern))))
 
-(defun completion-pcm--string->pattern (basestr &optional point)
-  "Split BASESTR into a pattern.
+(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'."
-  (if (and point (< point (length basestr)))
-      (let ((prefix (substring basestr 0 point))
-            (suffix (substring basestr point)))
+  (if (and point (< point (length string)))
+      (let ((prefix (substring string 0 point))
+            (suffix (substring string point)))
         (append (completion-pcm--string->pattern prefix)
                 '(point)
                 (completion-pcm--string->pattern suffix)))
@@ -1144,9 +1364,9 @@ or a symbol chosen among `any', `star', `point'."
           (p 0)
           (p0 0))
 
-      (while (setq p (string-match completion-pcm--delim-wild-regex basestr p))
-        (push (substring basestr p0 p) pattern)
-        (if (eq (aref basestr p) ?*)
+      (while (setq p (string-match completion-pcm--delim-wild-regex string p))
+        (push (substring string p0 p) pattern)
+        (if (eq (aref string p) ?*)
             (progn
               (push 'star pattern)
               (setq p0 (1+ p)))
@@ -1156,27 +1376,36 @@ or a symbol chosen among `any', `star', `point'."
 
       ;; An empty string might be erroneously added at the beginning.
       ;; It should be avoided properly, but it's so easy to remove it here.
-      (delete "" (nreverse (cons (substring basestr p0) pattern))))))
+      (delete "" (nreverse (cons (substring string p0) pattern))))))
 
 (defun completion-pcm--pattern->regex (pattern &optional group)
+  (let ((re
   (concat "\\`"
           (mapconcat
            (lambda (x)
              (case x
-               ((star any point) (if (if (consp group) (memq x group) group)
+                      ((star any point)
+                       (if (if (consp group) (memq x group) group)
                                      "\\(.*?\\)" ".*?"))
                (t (regexp-quote x))))
            pattern
-           "")))
+                  ""))))
+    ;; Avoid pathological backtracking.
+    (while (string-match "\\.\\*\\?\\(?:\\\\[()]\\)*\\(\\.\\*\\?\\)" re)
+      (setq re (replace-match "" t t re 1)))
+    re))
 
-(defun completion-pcm--all-completions (pattern table pred)
+(defun completion-pcm--all-completions (prefix pattern table pred)
   "Find all completions for PATTERN in TABLE obeying PRED.
 PATTERN is as returned by `completion-pcm--string->pattern'."
   ;; Find an initial list of possible completions.
   (if (completion-pcm--pattern-trivial-p pattern)
 
       ;; Minibuffer contains no delimiters -- simple case!
-      (all-completions (car pattern) table pred)
+      (let* ((all (all-completions (concat prefix (car pattern)) table pred))
+             (last (last all)))
+        (if last (setcdr last nil))
+        all)
 
     ;; Use all-completions to do an initial cull.  This is a big win,
     ;; since all-completions is written in C!
@@ -1184,11 +1413,14 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
           (regex (completion-pcm--pattern->regex pattern))
           (completion-regexp-list (cons regex completion-regexp-list))
           (compl (all-completions
-                   (if (stringp (car pattern)) (car pattern) "")
+                   (concat prefix (if (stringp (car pattern)) (car pattern) ""))
                   table pred))
            (last (last compl)))
-      ;; FIXME: If `base-size' is not 0, we have a problem :-(
-      (if last (setcdr last nil))
+      (when last
+        (if (and (numberp (cdr last)) (/= (cdr last) (length prefix)))
+            (message "Inconsistent base-size returned by completion table %s"
+                     table))
+        (setcdr last nil))
       (if (not (functionp table))
          ;; The internal functions already obeyed completion-regexp-list.
          compl
@@ -1224,11 +1456,103 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
         completions)
        base-size))))
 
+(defun completion-pcm--find-all-completions (string table pred point
+                                                    &optional filter)
+  "Find all completions for STRING at POINT in TABLE, satisfying PRED.
+POINT is a position inside STRING.
+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)
+    (setq string (substring string (car bounds) (+ point (cdr bounds))))
+    (let* ((relpoint (- point (car bounds)))
+           (pattern (completion-pcm--string->pattern string relpoint))
+           (all (condition-case err
+                    (funcall filter
+                             (completion-pcm--all-completions
+                              prefix pattern table pred))
+                  (error (unless firsterror (setq firsterror err)) nil))))
+      (when (and (null all)
+                 (> (car bounds) 0)
+                 (null (ignore-errors (try-completion prefix table pred))))
+        ;; The prefix has no completions at all, so we should try and fix
+        ;; that first.
+        (let ((substring (substring prefix 0 -1)))
+          (destructuring-bind (subpat suball subprefix subsuffix)
+              (completion-pcm--find-all-completions
+               substring table pred (length substring) filter)
+            (let ((sep (aref prefix (1- (length prefix))))
+                  ;; Text that goes between the new submatches and the
+                  ;; completion substring.
+                  (between nil))
+              ;; Eliminate submatches that don't end with the separator.
+              (dolist (submatch (prog1 suball (setq suball ())))
+                (when (eq sep (aref submatch (1- (length submatch))))
+                  (push submatch suball)))
+              (when suball
+                ;; Update the boundaries and corresponding pattern.
+                ;; We assume that all submatches result in the same boundaries
+                ;; since we wouldn't know how to merge them otherwise anyway.
+                ;; FIXME: COMPLETE REWRITE!!!
+                (let* ((newbeforepoint
+                        (concat subprefix (car suball)
+                                (substring string 0 relpoint)))
+                       (leftbound (+ (length subprefix) (length (car suball))))
+                       (newbounds (completion-boundaries
+                                   newbeforepoint table pred afterpoint)))
+                  (unless (or (and (eq (cdr bounds) (cdr newbounds))
+                                   (eq (car newbounds) leftbound))
+                              ;; Refuse new boundaries if they step over
+                              ;; the submatch.
+                              (< (car newbounds) leftbound))
+                    ;; The new completed prefix does change the boundaries
+                    ;; of the completed substring.
+                    (setq suffix (substring afterpoint (cdr newbounds)))
+                    (setq string
+                          (concat (substring newbeforepoint (car newbounds))
+                                  (substring afterpoint 0 (cdr newbounds))))
+                    (setq between (substring newbeforepoint leftbound
+                                             (car newbounds)))
+                    (setq pattern (completion-pcm--string->pattern
+                                   string
+                                   (- (length newbeforepoint)
+                                      (car newbounds)))))
+                  (dolist (submatch suball)
+                    (setq all (nconc (mapcar
+                                      (lambda (s) (concat submatch between s))
+                                      (funcall filter
+                                               (completion-pcm--all-completions
+                                                (concat subprefix submatch between)
+                                                pattern table pred)))
+                                     all)))
+                  ;; FIXME: This can come in handy for try-completion,
+                  ;; but isn't right for all-completions, since it lists
+                  ;; invalid completions.
+                  ;; (unless all
+                  ;;   ;; Even though we found expansions in the prefix, none
+                  ;;   ;; leads to a valid completion.
+                  ;;   ;; Let's keep the expansions, tho.
+                  ;;   (dolist (submatch suball)
+                  ;;     (push (concat submatch between newsubstring) all)))
+                  ))
+              (setq pattern (append subpat (list 'any (string sep))
+                                    (if between (list between)) pattern))
+              (setq prefix subprefix)))))
+      (if (and (null all) firsterror)
+          (signal (car firsterror) (cdr firsterror))
+        (list pattern all prefix suffix)))))
+
 (defun completion-pcm-all-completions (string table pred point)
-  (let ((pattern (completion-pcm--string->pattern string point)))
-    (completion-pcm--hilit-commonality
-     pattern
-     (completion-pcm--all-completions pattern table pred))))
+  (destructuring-bind (pattern all &optional prefix suffix)
+      (completion-pcm--find-all-completions string table pred point)
+    (when all
+      (nconc (completion-pcm--hilit-commonality pattern all)
+             (length prefix)))))
 
 (defun completion-pcm--merge-completions (strs pattern)
   "Extract the commonality in STRS, with the help of PATTERN."
@@ -1288,10 +1612,36 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
              pattern
              ""))
 
-(defun completion-pcm-try-completion (string table pred point)
-  (let* ((pattern (completion-pcm--string->pattern string point))
-         (all (completion-pcm--all-completions pattern table pred)))
+;; We want to provide the functionality of `try', but we use `all'
+;; and then merge it.  In most cases, this works perfectly, but
+;; if the completion table doesn't consider the same completions in
+;; `try' as in `all', then we have a problem.  The most common such
+;; case is for filename completion where completion-ignored-extensions
+;; is only obeyed by the `try' code.  We paper over the difference
+;; here.  Note that it is not quite right either: if the completion
+;; table uses completion-table-in-turn, this filtering may take place
+;; too late to correctly fallback from the first to the
+;; second alternative.
+(defun completion-pcm--filename-try-filter (all)
+  "Filter to adjust `all' file completion to the behavior of `try'."
     (when all
+    (let ((try ())
+          (re (concat "\\(?:\\`\\.\\.?/\\|"
+                      (regexp-opt completion-ignored-extensions)
+                      "\\)\\'")))
+      (dolist (f all)
+        (unless (string-match re f) (push f try)))
+      (or try all))))
+      
+
+(defun completion-pcm--merge-try (pattern all prefix suffix)
+  (cond
+   ((not (consp all)) all)
+   ((and (not (consp (cdr all)))        ;Only one completion.
+         ;; Ignore completion-ignore-case here.
+         (equal (completion-pcm--pattern->string pattern) (car all)))
+    t)
+   (t
       (let* ((mergedpat (completion-pcm--merge-completions all pattern))
              ;; `mergedpat' is in reverse order.  Place new point (by
             ;; order of preference) either at the old point, or at
@@ -1303,7 +1653,17 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
              (newpos (length (completion-pcm--pattern->string pointpat)))
             ;; Do it afterwards because it changes `pointpat' by sideeffect.
              (merged (completion-pcm--pattern->string (nreverse mergedpat))))
-        (cons merged newpos)))))
+
+      (setq suffix (completion--merge-suffix merged newpos suffix))
+        (cons (concat prefix merged suffix) (+ newpos (length prefix)))))))
+
+(defun completion-pcm-try-completion (string table pred point)
+  (destructuring-bind (pattern all prefix suffix)
+      (completion-pcm--find-all-completions
+       string table pred point
+       (if minibuffer-completing-file-name
+           'completion-pcm--filename-try-filter))
+    (completion-pcm--merge-try pattern all prefix suffix)))
 
 
 (provide 'minibuffer)