Fix default-directory for vc-root-diff.
[bpt/emacs.git] / lisp / minibuffer.el
index df2ff51..154cc37 100644 (file)
@@ -59,6 +59,8 @@
 
 ;; - 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).
@@ -391,6 +393,9 @@ the second failed attempt to complete."
      "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.
@@ -444,6 +449,17 @@ in the last `cdr'."
           (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.
@@ -486,14 +502,12 @@ E = after completion we now have an Exact match.
                                                    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
@@ -1088,12 +1102,12 @@ variables.")
   (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.")
 
@@ -1647,6 +1661,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)
   (let* ((beforepoint (substring string 0 point))
          (afterpoint (substring string point))
@@ -1663,10 +1683,8 @@ Return the new suffix."
              (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)))
@@ -1676,12 +1694,8 @@ Return the new suffix."
   (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))))
 
@@ -1813,7 +1827,6 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
   (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.
@@ -2059,13 +2072,47 @@ 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 '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