* bitmaps/README:
[bpt/emacs.git] / lisp / minibuffer.el
index 59081b8..87318f8 100644 (file)
 ;; - 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 . POS) in which case it should return (boundaries START . END).
+;;   (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-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.
-;; - 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:
@@ -65,23 +66,23 @@ element in the returned list of completions.  See `completion-base-size'.")
 ;;; Completion table manipulation
 
 ;; New completion-table operation.
-(defun completion-boundaries (string table pred pos)
-  "Return the boundaries of the completions returned by TABLE at POS.
+(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.
-The result is of the form (START . END) and gives the start and end position
-corresponding to the substring of STRING that can be completed by one
-of the elements returned by
-\(all-completions (substring STRING 0 POS) TABLE PRED).
+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 STRING))
-and for file names the result is the substring around POS delimited by
+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 pos)))))
+                        (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 string)))))
+          (or (cddr boundaries) (length suffix)))))
 
 (defun completion--some (fun xs)
   "Apply FUN to each element of XS in turn.
@@ -131,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)
@@ -178,9 +179,8 @@ You should give VAR a non-nil `risky-local-variable' property."
                 (funcall pred (concat prefix (if (consp s) (car s) s)))))))))
   (if (eq (car-safe action) 'boundaries)
       (let* ((len (length prefix))
-             (bound (completion-boundaries string table pred
-                                           (- (cdr action) len))))
-        (list* 'boundaries (+ (car bound) len) (+ (cdr bound) len)))
+             (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.
@@ -282,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))
@@ -568,6 +575,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)
@@ -907,6 +918,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)
@@ -926,7 +940,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))
@@ -952,13 +966,12 @@ specified by COMMON-SUBSTRING."
   (if (eq (car-safe action) 'boundaries)
       ;; Compute the boundaries of the subfield to which this
       ;; completion applies.
-      (let* ((pos (cdr action))
-             (suffix (substring string pos)))
-        (if (string-match completion--embedded-envvar-re
-                          (substring string 0 pos))
-            (list* 'boundaries (or (match-beginning 2) (match-beginning 1))
+      (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)
-                     (+ pos (match-beginning 0))))))
+                     (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))
@@ -977,11 +990,10 @@ specified by COMMON-SUBSTRING."
    ((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
-                          (substring string 0 (cdr action)))))
-          (end (string-match "/" string (cdr action))))
+    (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'
@@ -1056,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
@@ -1217,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)))
@@ -1227,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)))
@@ -1254,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)))))
-
-      (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)
@@ -1414,17 +1456,26 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
         completions)
        base-size))))
 
-(defun completion-pcm--find-all-completions (string table pred point)
-  (let* ((bounds (completion-boundaries string table pred point))
-         (prefix (substring string 0 (car bounds)))
-         (suffix (substring string (cdr bounds)))
-         (origstring string)
+(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) (cdr bounds)))
-    (let* ((pattern (completion-pcm--string->pattern
-                     string (- point (car bounds))))
+    (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
-                    (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)
@@ -1434,7 +1485,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.
@@ -1447,41 +1498,48 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
                 ;; 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.
-                (let* ((newstring (concat subprefix (car suball) string suffix))
-                       (newpoint (+ point (- (length newstring)
-                                             (length origstring))))
+                ;; FIXME: COMPLETE REWRITE!!!
+                (let* ((newbeforepoint
+                        (concat subprefix (car suball)
+                                (substring string 0 relpoint)))
+                       (leftbound (+ (length subprefix) (length (car suball))))
                        (newbounds (completion-boundaries
-                                   newstring table pred newpoint))
-                       (newsubstring
-                        (substring newstring (car newbounds) (cdr newbounds))))
-                  (unless (or (equal newsubstring string)
+                                   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)
-                                 (+ (length subprefix) (length (car suball)))))
+                              (< (car newbounds) leftbound))
                     ;; The new completed prefix does change the boundaries
                     ;; of the completed substring.
-                    (setq suffix (substring newstring (cdr newbounds)))
-                    (setq string newsubstring)
-                    (setq between (substring newstring
-                                             (+ (length subprefix)
-                                                (length (car suball)))
+                    (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 (- newpoint (car bounds)))))
+                                   string
+                                   (- (length newbeforepoint)
+                                      (car newbounds)))))
                   (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)))
-                  (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)))))
+                  ;; 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)))))
@@ -1492,7 +1550,9 @@ PATTERN is as returned by `completion-pcm--string->pattern'."
 (defun completion-pcm-all-completions (string table pred point)
   (destructuring-bind (pattern all &optional prefix suffix)
       (completion-pcm--find-all-completions string table pred point)
-    (completion-pcm--hilit-commonality pattern all)))
+    (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."
@@ -1552,10 +1612,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
@@ -1567,11 +1653,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)