changeset 93937:dfe13eac745b

* minibuffer.el (minibuffer): Move group from cus-edit.el. (completion-auto-help): Move from C code. (minibuffer--maybe-completion-help): Remove. (minibuffer--bitset): New function. (minibuffer--do-completion): Rename from minibuffer-do-completion. Renumber a bit. Really complete on string *before* point. Add argument used for word-completion. Join trailing / in completion with following text, as done in minibuffer-complete-word. Handle new value `lazy' for completion-auto-help. (minibuffer-try-word-completion): New function extracted from minibuffer-complete-word. (minibuffer-complete-word): Use minibuffer--do-completion. (minibuffer--insert-strings): Rename from minibuffer-complete-insert-strings. (exit-minibuffer): Fix typo. * cus-edit.el (minibuffer): Move group to minibuffer.el. * cus-start.el: Remove completion-auto-help. * minibuf.c (Vcompletion_auto_help): Move to minibuffer.el. (syms_of_minibuf): Remove its initialization.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Wed, 09 Apr 2008 19:33:56 +0000
parents 3bc9b0eef232
children 3c06445e714c
files etc/NEWS lisp/ChangeLog lisp/cus-edit.el lisp/cus-start.el lisp/minibuffer.el src/ChangeLog src/minibuf.c
diffstat 7 files changed, 156 insertions(+), 126 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Wed Apr 09 19:08:22 2008 +0000
+++ b/etc/NEWS	Wed Apr 09 19:33:56 2008 +0000
@@ -65,6 +65,10 @@
 
 * Changes in Emacs 23.1
 
+** `completion-auto-help' can be set to `lazy' to list the completions only
+if you repeat the completion.  This was already supported in
+`partial-completion-mode'.
+
 ** Emacs now supports using both X displays and ttys in one session.
 Start the server (M-x server-start).  Then `emacsclient -t' creates a
 tty frame connected to the running emacs server.  You can also use any
--- a/lisp/ChangeLog	Wed Apr 09 19:08:22 2008 +0000
+++ b/lisp/ChangeLog	Wed Apr 09 19:33:56 2008 +0000
@@ -1,9 +1,30 @@
+2008-04-09  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* minibuffer.el (minibuffer): Move group from cus-edit.el.
+	(completion-auto-help): Move from C code.
+	(minibuffer--maybe-completion-help): Remove.
+	(minibuffer--bitset): New function.
+	(minibuffer--do-completion): Rename from minibuffer-do-completion.
+	Renumber a bit.  Really complete on string *before* point.
+	Add argument used for word-completion.
+	Join trailing / in completion with following text, as done in
+	minibuffer-complete-word.
+	Handle new value `lazy' for completion-auto-help.
+	(minibuffer-try-word-completion): New function extracted from
+	minibuffer-complete-word.
+	(minibuffer-complete-word): Use minibuffer--do-completion.
+	(minibuffer--insert-strings): Rename from
+	minibuffer-complete-insert-strings.
+	(exit-minibuffer): Fix typo.
+	* cus-edit.el (minibuffer): Move group to minibuffer.el.
+	* cus-start.el: Remove completion-auto-help.
+
 2008-04-09  Alexandre Julliard  <julliard@winehq.org>
 
 	* vc.el (vc-status-add-entries): New function.
-	(vc-status-add-entry): Removed.
-	(vc-update-vc-status-buffer, vc-status-mark-buffer-changed): Use
-	vc-status-add-entries.
+	(vc-status-add-entry): Remove.
+	(vc-update-vc-status-buffer, vc-status-mark-buffer-changed):
+	Use vc-status-add-entries.
 
 	* emacs-lisp/ewoc.el (ewoc-collect): Return results in the correct
 	order.
@@ -18,8 +39,8 @@
 
 2008-04-09  Chong Yidong  <cyd@stupidchicken.com>
 
-	* emacs-lisp/regexp-opt.el (regexp-opt): Reduce
-	max-lisp-eval-depth and max-specpdl-size to 10000.
+	* emacs-lisp/regexp-opt.el (regexp-opt):
+	Reduce max-lisp-eval-depth and max-specpdl-size to 10000.
 
 2008-04-09  Lennart Borgman  <lennart.borgman@gmail.com>
 
--- a/lisp/cus-edit.el	Wed Apr 09 19:08:22 2008 +0000
+++ b/lisp/cus-edit.el	Wed Apr 09 19:33:56 2008 +0000
@@ -416,11 +416,6 @@
   "Debugging Emacs itself."
   :group 'development)
 
-(defgroup minibuffer nil
-  "Controlling the behavior of the minibuffer."
-  :link '(custom-manual "(emacs)Minibuffer")
-  :group 'environment)
-
 (defgroup keyboard nil
   "Input from the keyboard."
   :group 'environment)
--- a/lisp/cus-start.el	Wed Apr 09 19:08:22 2008 +0000
+++ b/lisp/cus-start.el	Wed Apr 09 19:33:56 2008 +0000
@@ -248,7 +248,6 @@
 ;;; 					(const :tag " current dir" nil)
 ;;;					(directory :format "%v"))))
 	     ;; minibuf.c
-	     (completion-auto-help minibuffer boolean)
 	     (enable-recursive-minibuffers minibuffer boolean)
 	     (history-length minibuffer
 			     (choice (const :tag "Infinite" t) integer)
--- a/lisp/minibuffer.el	Wed Apr 09 19:08:22 2008 +0000
+++ b/lisp/minibuffer.el	Wed Apr 09 19:33:56 2008 +0000
@@ -21,6 +21,9 @@
 
 ;;; Commentary:
 
+;; Names starting with "minibuffer--" are for functions and variables that
+;; are meant to be for internal use only.
+
 ;; TODO:
 ;; - merge do-completion and complete-word
 ;; - move all I/O out of do-completion
@@ -29,6 +32,11 @@
 
 (eval-when-compile (require 'cl))
 
+(defgroup minibuffer nil
+  "Controlling the behavior of the minibuffer."
+  :link '(custom-manual "(emacs)Minibuffer")
+  :group 'environment)
+
 (defun minibuffer-message (message &rest args)
   "Temporarily display MESSAGE at the end of the minibuffer.
 The text is displayed for `minibuffer-message-timeout' seconds,
@@ -37,7 +45,7 @@
 If ARGS are provided, then pass MESSAGE through `format'."
   ;; Clear out any old echo-area message to make way for our new thing.
   (message nil)
-  (unless (string-match "\\[.+\\]" message)
+  (unless (and (null args) (string-match "\\[.+\\]" message))
     (setq message (concat " [" message "]")))
   (when args (setq message (apply 'format message args)))
   (let ((ol (make-overlay (point-max) (point-max) nil t t)))
@@ -57,33 +65,45 @@
 If the current buffer is not a minibuffer, erase its entire contents."
   (delete-field))
 
-(defun minibuffer--maybe-completion-help ()
-  (if completion-auto-help
-      (minibuffer-completion-help)
-    (minibuffer-message "Next char not unique")))
+(defcustom completion-auto-help t
+  "Non-nil means automatically provide help for invalid completion input.
+If the value is t the *Completion* buffer is displayed whenever completion
+is requested but cannot be done.
+If the value is `lazy', the *Completions* buffer is only displayed after
+the second failed attempt to complete."
+  :type (choice (const nil) (const t) (const lazy))
+  :group 'minibuffer)
 
-(defun minibuffer-do-completion ()
-  "Do the completion and return a summary of what happened.
-C = There were available completions.
-E = After completion we now have an exact match.
-M = Completion was performed, the text was Modified.
+(defun minibuffer--bitset (modified completions exact)
+  (logior (if modified    4 0)
+          (if completions 2 0)
+          (if exact       1 0)))
 
- CEM
- 000 0 no possible completion
- 010 1 was already an exact and unique completion
- 110 3 was already an exact completion
- 111 4 completed to an exact completion
- 101 5 some completion happened
- 100 6 no completion happened"
-  (let* ((string (minibuffer-completion-contents))
-         (completion (try-completion (field-string)
-                                    minibuffer-completion-table
-                                    minibuffer-completion-predicate)))
-    (setq last-exact-completion nil)
+(defun minibuffer--do-completion (&optional try-completion-function)
+  "Do the completion and return a summary of what happened.
+M = completion was performed, the text was Modified.
+C = there were available Completions.
+E = after completion we now have an Exact match.
+
+ MCE
+ 000  0 no possible completion
+ 001  1 was already an exact and unique completion
+ 010  2 no completion happened
+ 011  3 was already an exact completion
+ 100  4 ??? impossible
+ 101  5 ??? impossible
+ 110  6 some completion happened
+ 111  7 completed to an exact completion"
+  (let* ((beg (field-beginning))
+         (string (buffer-substring beg (point)))
+         (completion (funcall (or try-completion-function 'try-completion)
+                              string
+                              minibuffer-completion-table
+                              minibuffer-completion-predicate)))
     (cond
      ((null completion)
-      (ding) (minibuffer-message "No match") 0)
-     ((eq t completion) 1)              ;Exact and unique match.
+      (ding) (minibuffer-message "No match") (minibuffer--bitset nil nil nil))
+     ((eq t completion) (minibuffer--bitset nil nil t)) ;Exact and unique match.
      (t
       ;; `completed' should be t if some completion was done, which doesn't
       ;; include simply changing the case of the entered string.  However,
@@ -93,34 +113,46 @@
             (unchanged (eq t (compare-strings completion nil nil
                                               string nil nil nil))))
         (unless unchanged
-          (let ((beg (field-beginning))
-                (end (point)))
+          ;; Merge a trailing / in completion with a / after point.
+          ;; We used to only do it for word completion, but it seems to make
+          ;; sense for all completions.
+          (if (and (eq ?/ (aref completion (1- (length completion))))
+                   (< (point) (field-end))
+                   (eq ?/ (char-after)))
+              (setq completion (substring completion 0 -1)))
+
+          ;; Insert in minibuffer the chars we got.
+          (let ((end (point)))
             (insert completion)
             (delete-region beg end)))
+
         (if (not (or unchanged completed))
 	   ;; The case of the string changed, but that's all.  We're not sure
 	   ;; whether this is a unique completion or not, so try again using
 	   ;; the real case (this shouldn't recurse again, because the next
 	   ;; time try-completion will return either t or the exact string).
-           (minibuffer-do-completion)
+           (minibuffer--do-completion)
 
           ;; It did find a match.  Do we match some possibility exactly now?
           (let ((exact (test-completion (field-string)
 					minibuffer-completion-table
 					minibuffer-completion-predicate)))
-            (cond
-             ((not exact)
-              (if completed 5
-                (minibuffer--maybe-completion-help)
-                6))
-             (completed 4)
-             (t
-              ;; If the last exact completion and this one were the same,
-              ;; it means we've already given a "Complete but not unique"
-              ;; message and the user's hit TAB again, so now we give him help.
-              (if (eq this-command last-command)
-                  (minibuffer-completion-help))
-              3)))))))))
+            (unless completed
+              ;; Show the completion table, if requested.
+              (cond
+               ((not exact)
+                (if (case completion-auto-help
+                      (lazy (eq this-command last-command))
+                      (t completion-auto-help))
+                    (minibuffer-completion-help)
+                  (minibuffer-message "Next char not unique")))
+               ;; If the last exact completion and this one were the same,
+               ;; it means we've already given a "Complete but not unique"
+               ;; message and the user's hit TAB again, so now we give him help.
+               ((eq this-command last-command)
+                (if completion-auto-help (minibuffer-completion-help)))))
+
+            (minibuffer--bitset completed t exact))))))))
 
 (defun minibuffer-complete ()
   "Complete the minibuffer contents as far as possible.
@@ -146,16 +178,15 @@
 	    (scroll-other-window))
 	  nil)
 
-      (let ((i (minibuffer-do-completion)))
-        (case i
-          (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))))))
+      (case (minibuffer--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)))))
 
 (defun minibuffer-complete-and-exit ()
   "If the minibuffer contents is a valid completion then exit.
@@ -195,33 +226,21 @@
 
    (t
     ;; Call do-completion, but ignore errors.
-    (let ((i (condition-case nil
-                 (minibuffer-do-completion)
-               (error 1))))
-      (case i
-        ((1 3) (exit-minibuffer))
-        (4 (if (not minibuffer-completion-confirm)
-               (exit-minibuffer)
-             (minibuffer-message "Confirm")
-             nil))
-        (t nil))))))
+    (case (condition-case nil
+              (minibuffer--do-completion)
+            (error 1))
+      ((1 3) (exit-minibuffer))
+      (7 (if (not minibuffer-completion-confirm)
+             (exit-minibuffer)
+           (minibuffer-message "Confirm")
+           nil))
+      (t nil)))))
 
-(defun minibuffer-complete-word ()
-  "Complete the minibuffer contents at most a single word.
-After one word is completed as much as possible, a space or hyphen
-is added, provided that matches some possible completion.
-Return nil if there is no valid completion, else t."
-  (interactive)
-  (let* ((beg (field-beginning))
-         (string (buffer-substring beg (point)))
-         (completion (try-completion string
-                                     minibuffer-completion-table
-                                     minibuffer-completion-predicate)))
-    (cond
-     ((null completion)
-      (ding) (minibuffer-message "No match") nil)
-     ((eq t completion) nil)              ;Exact and unique match.
-     (t
+(defun minibuffer-try-word-completion (string table predicate)
+  (let ((completion (try-completion string table predicate)))
+    (if (not (stringp completion))
+        completion
+
       ;; Completing a single word is actually more difficult than completing
       ;; as much as possible, because we first have to find the "current
       ;; position" in `completion' in order to find the end of the word
@@ -239,10 +258,7 @@
 			       (substitute-in-file-name string)
 			     (error string))))
 	  (unless (eq string substituted)
-	    (setq string substituted)
-	    (let ((end (point)))
-              (insert substituted)
-              (delete-region beg end)))))
+	    (setq string substituted))))
 
       ;; Make buffer (before point) contain the longest match
       ;; of `string's tail and `completion's head.
@@ -255,8 +271,7 @@
           (setq startpos (1+ startpos))
           (setq length (1- length)))
 
-        (setq string (substring string startpos))
-        (delete-region beg (+ beg startpos)))
+        (setq string (substring string startpos)))
 
       ;; Now `string' is a prefix of `completion'.
 
@@ -267,31 +282,34 @@
               tem)
           (while (and exts (not (stringp tem)))
             (setq tem (try-completion (concat string (pop exts))
-                                      minibuffer-completion-table
-                                      minibuffer-completion-predicate)))
+                                      table predicate)))
           (if (stringp tem) (setq completion tem))))
 
-      (if (= (length string) (length completion))
-          ;; If got no characters, print help for user.
-          (progn
-            (if completion-auto-help (minibuffer-completion-help))
-            nil)
-        ;; Otherwise insert in minibuffer the chars we got.
-        (if (string-match "\\W" completion (length string))
-            ;; First find first word-break in the stuff found by completion.
-            ;; i gets index in string of where to stop completing.
-            (setq completion (substring completion 0 (match-end 0))))
+      ;; Otherwise cut after the first word.
+      (if (string-match "\\W" completion (length string))
+          ;; First find first word-break in the stuff found by completion.
+          ;; i gets index in string of where to stop completing.
+          (substring completion 0 (match-end 0))
+        completion))))
+
 
-        (if (and (eq ?/ (aref completion (1- (length completion))))
-                 (eq ?/ (char-after)))
-            (setq completion (substring completion 0 (1- (length completion)))))
+(defun minibuffer-complete-word ()
+  "Complete the minibuffer contents at most a single word.
+After one word is completed as much as possible, a space or hyphen
+is added, provided that matches some possible completion.
+Return nil if there is no valid completion, else t."
+  (interactive)
+  (case (minibuffer--do-completion 'minibuffer-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)))
 
-        (let ((pos (point)))
-          (insert completion)
-          (delete-region beg pos)
-          t))))))
-
-(defun minibuffer-complete-insert-strings (strings)
+(defun minibuffer--insert-strings (strings)
   "Insert a list of STRINGS into the current buffer.
 Uses columns to keep the listing readable but compact.
 It also eliminates runs of equal strings."
@@ -378,7 +396,7 @@
 	  (insert "There are no possible completions of what you have typed.")
 	
 	(insert "Possible completions are:\n")
-	(minibuffer-complete-insert-strings completions))))
+	(minibuffer--insert-strings completions))))
   (let ((completion-common-substring common-substring))
     (run-hooks 'completion-setup-hook))
   nil)
@@ -421,7 +439,7 @@
   ;; A better solution would be to make deactivate-mark buffer-local
   ;; (or to turn it into a list of buffers, ...), but in the mean time,
   ;; this should do the trick in most cases.
-  (setq deactivate_mark nil)
+  (setq deactivate-mark nil)
   (throw 'exit nil))
 
 (defun self-insert-and-exit ()
--- a/src/ChangeLog	Wed Apr 09 19:08:22 2008 +0000
+++ b/src/ChangeLog	Wed Apr 09 19:33:56 2008 +0000
@@ -1,5 +1,8 @@
 2008-04-09  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+	* minibuf.c (Vcompletion_auto_help): Move to minibuffer.el.
+	(syms_of_minibuf): Remove its initialization.
+
 	* minibuf.c (temp_echo_area_glyphs): Remove unused function.
 
 2008-04-09  Juanma Barranquero  <lekktu@gmail.com>
--- a/src/minibuf.c	Wed Apr 09 19:08:22 2008 +0000
+++ b/src/minibuf.c	Wed Apr 09 19:33:56 2008 +0000
@@ -55,10 +55,6 @@
 
 int minibuf_level;
 
-/* Nonzero means display completion help for invalid input.  */
-
-Lisp_Object Vcompletion_auto_help;
-
 /* The maximum length of a minibuffer history.  */
 
 Lisp_Object Qhistory_length, Vhistory_length;
@@ -2126,12 +2122,6 @@
 `add-to-history' explicitly.  */);
   Vhistory_add_new_input = Qt;
 
-  DEFVAR_LISP ("completion-auto-help", &Vcompletion_auto_help,
-	       doc: /* *Non-nil means automatically provide help for invalid completion input.
-Under Partial Completion mode, a non-nil, non-t value has a special meaning;
-see the doc string of `partial-completion-mode' for more details.  */);
-  Vcompletion_auto_help = Qt;
-
   DEFVAR_BOOL ("completion-ignore-case", &completion_ignore_case,
 	       doc: /* Non-nil means don't consider case significant in completion.