]> code.delx.au - gnu-emacs/blobdiff - lisp/minibuffer.el
* hl-line.el (hl-line-unload-function): New function.
[gnu-emacs] / lisp / minibuffer.el
index 510fe4b17215ebddaf70aa2a1412c164934df24c..b64a8d08ae5bc7a490608dc50933c63ce1f31e0f 100644 (file)
 
 ;;; Bugs:
 
-;; - completion-ignored-extensions is ignored by partial-completion because
-;;   pcm merges the `all' output to synthesize a `try' output and
-;;   read-file-name-internal's `all' output doesn't obey
-;;   completion-ignored-extensions.
+;; - 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
 
 ;;; Todo:
 
+;; - make lisp-complete-symbol and sym-comp use it.
 ;; - add support for ** to pcm.
 ;; - Make read-file-name-predicate obsolete.
 ;; - 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:
@@ -72,7 +73,6 @@ 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."
@@ -130,7 +130,7 @@ This alist may be a full list of possible completions so that FUN can ignore
 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
+The result of the `completion-table-dynamic' form is a function
 that can be used as the COLLECTION argument to `try-completion' and
 `all-completions'.  See Info node `(elisp)Programmed Completion'."
   (lexical-let ((fun fun))
@@ -281,7 +281,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))
@@ -567,6 +574,10 @@ input if confirmed."
           (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)
@@ -604,14 +615,9 @@ input if confirmed."
         (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))
+             ;; Disable partial-completion for this.
+             (completion-styles
+              (remove 'partial-completion completion-styles))
              tem)
          (while (and exts (not (consp tem)))
             (setq tem (completion-try-completion
@@ -814,11 +820,11 @@ The actual completion alternatives, as inserted, are given `mouse-face'
 properties of `highlight'.
 At the end, this runs the normal hook `completion-setup-hook'.
 It can find the completion buffer in `standard-output'.
-The obsolete optional second arg COMMON-SUBSTRING is a string.
-It is used to put faces, `completions-first-difference' and
-`completions-common-part' on the completion buffer.  The
-`completions-common-part' face is put on the common substring
-specified by COMMON-SUBSTRING."
+
+The obsolete optional arg COMMON-SUBSTRING, if non-nil, should be a string
+specifying a common substring for adding the faces
+`completions-first-difference' and `completions-common-part' to
+the completions buffer."
   (if common-substring
       (setq completions (completion-hilit-commonality
                          completions (length common-substring))))
@@ -827,25 +833,28 @@ specified by COMMON-SUBSTRING."
       (with-temp-buffer
        (let ((standard-output (current-buffer))
              (completion-setup-hook nil))
-         (display-completion-list completions))
+         (display-completion-list completions common-substring))
        (princ (buffer-string)))
 
-    (with-current-buffer standard-output
-      (goto-char (point-max))
-      (if (null completions)
-         (insert "There are no possible completions of what you have typed.")
-
-       (insert "Possible completions are:\n")
-        (let ((last (last completions)))
-          ;; Get the base-size from the tail of the list.
-          (set (make-local-variable 'completion-base-size) (or (cdr last) 0))
-          (setcdr last nil)) ;Make completions a properly nil-terminated list.
-       (completion--insert-strings completions))))
+    (let ((mainbuf (current-buffer)))
+      (with-current-buffer standard-output
+       (goto-char (point-max))
+       (if (null completions)
+           (insert "There are no possible completions of what you have typed.")
+         (insert "Possible completions are:\n")
+         (let ((last (last completions)))
+           ;; Set base-size from the tail of the list.
+           (set (make-local-variable 'completion-base-size)
+                (or (cdr last)
+                    (and (minibufferp mainbuf) 0)))
+           (setcdr last nil)) ; Make completions a properly nil-terminated list.
+         (completion--insert-strings completions)))))
 
   ;; The hilit used to be applied via completion-setup-hook, so there
   ;; may still be some code that uses completion-common-substring.
-  (let ((completion-common-substring common-substring))
-    (run-hooks 'completion-setup-hook))
+  (with-no-warnings
+    (let ((completion-common-substring common-substring))
+      (run-hooks 'completion-setup-hook)))
   nil)
 
 (defun minibuffer-completion-help ()
@@ -906,6 +915,9 @@ specified by COMMON-SUBSTRING."
 
 ;;; 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)
@@ -925,7 +937,7 @@ specified by COMMON-SUBSTRING."
 
 (let ((map minibuffer-local-filename-completion-map))
   (define-key map " " nil))
-(let ((map minibuffer-local-must-match-filename-map))
+(let ((map minibuffer-local-filename-must-match-map))
   (define-key map " " nil))
 
 (let ((map minibuffer-local-ns-map))
@@ -1053,7 +1065,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 cygwin))
       t nil)
   "Non-nil means when reading a file name completion ignores case."
   :group 'minibuffer
@@ -1214,7 +1226,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)))
@@ -1224,11 +1236,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)))
@@ -1251,36 +1261,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)))))
-
-      (cons (concat completion suffix) (length completion)))))
+;;; 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))
 
-(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)
@@ -1366,7 +1408,8 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
     ;; since all-completions is written in C!
     (let* (;; Convert search pattern to a standard regular expression.
           (regex (completion-pcm--pattern->regex pattern))
-          (completion-regexp-list (cons regex completion-regexp-list))
+           (case-fold-search completion-ignore-case)
+           (completion-regexp-list (cons regex completion-regexp-list))
           (compl (all-completions
                    (concat prefix (if (stringp (car pattern)) (car pattern) ""))
                   table pred))
@@ -1379,8 +1422,7 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
       (if (not (functionp table))
          ;; The internal functions already obeyed completion-regexp-list.
          compl
-       (let ((case-fold-search completion-ignore-case)
-              (poss ()))
+       (let ((poss ()))
          (dolist (c compl)
            (when (string-match regex c) (push c poss)))
          poss)))))
@@ -1388,6 +1430,7 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
 (defun completion-pcm--hilit-commonality (pattern completions)
   (when completions
     (let* ((re (completion-pcm--pattern->regex pattern '(point)))
+           (case-fold-search completion-ignore-case)
            (last (last completions))
            (base-size (cdr last)))
       ;; Remove base-size during mapcar, and add it back later.
@@ -1411,7 +1454,13 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
         completions)
        base-size))))
 
-(defun completion-pcm--find-all-completions (string table pred point)
+(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))
@@ -1422,7 +1471,9 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
     (let* ((relpoint (- point (car bounds)))
            (pattern (completion-pcm--string->pattern string relpoint))
            (all (condition-case err
-                    (completion-pcm--all-completions prefix pattern table pred)
+                    (funcall filter
+                             (completion-pcm--all-completions
+                              prefix pattern table pred))
                   (error (unless firsterror (setq firsterror err)) nil))))
       (when (and (null all)
                  (> (car bounds) 0)
@@ -1432,7 +1483,7 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
         (let ((substring (substring prefix 0 -1)))
           (destructuring-bind (subpat suball subprefix subsuffix)
               (completion-pcm--find-all-completions
-               substring table pred (length substring))
+               substring table pred (length substring) filter)
             (let ((sep (aref prefix (1- (length prefix))))
                   ;; Text that goes between the new submatches and the
                   ;; completion substring.
@@ -1472,9 +1523,10 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
                   (dolist (submatch suball)
                     (setq all (nconc (mapcar
                                       (lambda (s) (concat submatch between s))
-                                      (completion-pcm--all-completions
-                                       (concat subprefix submatch between)
-                                       pattern table pred))
+                                      (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
@@ -1558,10 +1610,36 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
              pattern
              ""))
 
-(defun completion-pcm-try-completion (string table pred point)
-  (destructuring-bind (pattern all prefix suffix)
-      (completion-pcm--find-all-completions string table pred point)
+;; 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
@@ -1573,11 +1651,18 @@ 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))))
-        (if (and (> (length merged) 0) (> (length suffix) 0)
-                 (eq (aref merged (1- (length merged))) (aref suffix 0)))
-            (setq suffix (substring suffix 1)))
+
+      (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)