changeset 44469:f9a82a50692e

(read_minibuf): Use empty_string. (Ftry_completion): Allow lambda forms and lists of strings for `alist'. Short-circuit the search as soon as it "failed". (Fall_completions): Allow lambda forms and lists of strings for alist. (Fcompleting_read): Set Qminibuffer_completion_confirm to nil when require_match is nil. (Ftest_completion): Rename from `test_completion' and export to elisp. Call the predicate also when alist is a list. Obey Vcompletion_regexp_list. (do_completion, Fminibuffer_complete_and_exit): Use it. (Fassoc_string): Rename from `assoc_for_completion'. Allow list of strings as well and export to elisp.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Tue, 09 Apr 2002 19:28:42 +0000
parents 539150b68126
children 7f801508c4d0
files src/minibuf.c
diffstat 1 files changed, 88 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/minibuf.c	Tue Apr 09 18:56:34 2002 +0000
+++ b/src/minibuf.c	Tue Apr 09 19:28:42 2002 +0000
@@ -427,7 +427,7 @@
   GCPRO5 (map, initial, val, ambient_dir, input_method);
 
   if (!STRINGP (prompt))
-    prompt = build_string ("");
+    prompt = empty_string;
 
   if (!enable_recursive_minibuffers
       && minibuf_level > 0)
@@ -1103,7 +1103,9 @@
   int bestmatchsize = 0;
   /* These are in bytes, too.  */
   int compare, matchsize;
-  int list = CONSP (alist) || NILP (alist);
+  int list = NILP (alist) || (CONSP (alist)
+			      && (!SYMBOLP (XCAR (alist))
+				  || NILP (XCAR (alist))));
   int index = 0, obsize = 0;
   int matchcount = 0;
   Lisp_Object bucket, zero, end, tem;
@@ -1133,11 +1135,11 @@
 
       if (list)
 	{
-	  if (NILP (tail))
+	  if (!CONSP (tail))
 	    break;
-	  elt = Fcar (tail);
-	  eltstring = Fcar (elt);
-	  tail = Fcdr (tail);
+	  elt = XCAR (tail);
+	  eltstring = CONSP (elt) ? XCAR (elt) : elt;
+	  tail = XCDR (tail);
 	}
       else
 	{
@@ -1225,6 +1227,7 @@
 		matchsize = XINT (tem) - 1;
 
 	      if (matchsize < 0)
+		/* When can this happen ?  -stef  */
 		matchsize = compare;
 	      if (completion_ignore_case)
 		{
@@ -1259,6 +1262,10 @@
 		    bestmatch = eltstring;
 		}
 	      bestmatchsize = matchsize;
+	      if (matchsize <= XSTRING (string)->size
+		  && matchcount > 1)
+		/* No need to look any further.  */
+		break;
 	    }
 	}
     }
@@ -1316,7 +1323,9 @@
 {
   Lisp_Object tail, elt, eltstring;
   Lisp_Object allmatches;
-  int list = CONSP (alist) || NILP (alist);
+  int list = NILP (alist) || (CONSP (alist)
+			      && (!SYMBOLP (XCAR (alist))
+				  || NILP (XCAR (alist))));
   int index = 0, obsize = 0;
   Lisp_Object bucket, tem;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
@@ -1346,11 +1355,11 @@
 
       if (list)
 	{
-	  if (NILP (tail))
+	  if (!CONSP (tail))
 	    break;
-	  elt = Fcar (tail);
-	  eltstring = Fcar (elt);
-	  tail = Fcdr (tail);
+	  elt = XCAR (tail);
+	  eltstring = CONSP (elt) ? XCAR (elt) : elt;
+	  tail = XCDR (tail);
 	}
       else
 	{
@@ -1486,7 +1495,7 @@
   specbind (Qminibuffer_completion_table, table);
   specbind (Qminibuffer_completion_predicate, predicate);
   specbind (Qminibuffer_completion_confirm,
-	    EQ (require_match, Qt) ? Qnil : Qt);
+	    EQ (require_match, Qt) ? Qnil : require_match);
   last_exact_completion = Qnil;
 
   position = Qnil;
@@ -1535,47 +1544,70 @@
 }
 
 Lisp_Object Fminibuffer_completion_help ();
-Lisp_Object assoc_for_completion ();
+Lisp_Object Fassoc_string ();
 
 /* Test whether TXT is an exact completion.  */
-Lisp_Object
-test_completion (txt)
-     Lisp_Object txt;
+DEFUN ("test-completion", Ftest_completion, Stest_completion, 2, 3, 0,
+       doc: /* Return non-nil if STRING is a valid completion.
+Takes the same arguments as `all-completions' and `try-completion'.
+If ALIST is a function, it is called with three arguments:
+the values STRING, PREDICATE and `lambda'.  */)
+       (string, alist, predicate)
+     Lisp_Object string, alist, predicate;
 {
-  Lisp_Object tem;
+  Lisp_Object regexps, tem = Qnil;
+
+  CHECK_STRING (string);
 
-  if (CONSP (Vminibuffer_completion_table)
-      || NILP (Vminibuffer_completion_table))
-    return assoc_for_completion (txt, Vminibuffer_completion_table);
-  else if (VECTORP (Vminibuffer_completion_table))
+  if ((CONSP (alist) && (!SYMBOLP (XCAR (alist)) || NILP (XCAR (alist))))
+      || NILP (alist))
     {
-      /* Bypass intern-soft as that loses for nil */
-      tem = oblookup (Vminibuffer_completion_table,
-		      XSTRING (txt)->data,
-		      XSTRING (txt)->size,
-		      STRING_BYTES (XSTRING (txt)));
+      tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil);
+      if (CONSP (tem))
+	tem = XCAR (tem);
+      else
+	return Qnil;
+    }
+  else if (VECTORP (alist))
+    {
+      /* Bypass intern-soft as that loses for nil.  */
+      tem = oblookup (alist,
+		      XSTRING (string)->data,
+		      XSTRING (string)->size,
+		      STRING_BYTES (XSTRING (string)));
       if (!SYMBOLP (tem))
 	{
-	  if (STRING_MULTIBYTE (txt))
-	    txt = Fstring_make_unibyte (txt);
+	  if (STRING_MULTIBYTE (string))
+	    string = Fstring_make_unibyte (string);
 	  else
-	    txt = Fstring_make_multibyte (txt);
+	    string = Fstring_make_multibyte (string);
 
 	  tem = oblookup (Vminibuffer_completion_table,
-			  XSTRING (txt)->data,
-			  XSTRING (txt)->size,
-			  STRING_BYTES (XSTRING (txt)));
+			  XSTRING (string)->data,
+			  XSTRING (string)->size,
+			  STRING_BYTES (XSTRING (string)));
 	  if (!SYMBOLP (tem))
 	    return Qnil;
 	}
-      if (!NILP (Vminibuffer_completion_predicate))
-	return call1 (Vminibuffer_completion_predicate, tem);
-      else
-	return Qt;
     }
   else
-    return call3 (Vminibuffer_completion_table, txt,
-		  Vminibuffer_completion_predicate, Qlambda);
+    return call3 (alist, string, predicate, Qlambda);
+
+  /* Reject this element if it fails to match all the regexps.  */
+  for (regexps = Vcompletion_regexp_list; CONSP (regexps);
+       regexps = XCDR (regexps))
+    {
+      if (NILP (Fstring_match (XCAR (regexps),
+			       SYMBOLP (tem) ? string : tem,
+			       Qnil)))
+	return Qnil;
+    }
+
+  /* Finally, check the predicate.  */
+  if (!NILP (predicate))
+    return call1 (predicate, tem);
+  else
+    return Qt;
 }
 
 /* returns:
@@ -1645,7 +1677,9 @@
     }
 
   /* It did find a match.  Do we match some possibility exactly now? */
-  tem = test_completion (Fminibuffer_contents ());
+  tem = Ftest_completion (Fminibuffer_contents (),
+			  Vminibuffer_completion_table,
+			  Vminibuffer_completion_predicate);
   if (NILP (tem))
     {
       /* not an exact match */
@@ -1679,10 +1713,15 @@
 
 /* Like assoc but assumes KEY is a string, and ignores case if appropriate.  */
 
-Lisp_Object
-assoc_for_completion (key, list)
+DEFUN ("assoc-string", Fassoc_string, Sassoc_string, 2, 3, 0,
+       doc: /* Like `assoc' but specifically for strings.
+Unibyte strings are converted to multibyte for comparison.
+And case is ignored if CASE-FOLD is non-nil.
+As opposed to `assoc', it will also match an entry consisting of a single
+string rather than a cons cell whose car is a string.  */)
+       (key, list, case_fold)
      register Lisp_Object key;
-     Lisp_Object list;
+     Lisp_Object list, case_fold;
 {
   register Lisp_Object tail;
 
@@ -1690,13 +1729,12 @@
     {
       register Lisp_Object elt, tem, thiscar;
       elt = Fcar (tail);
-      if (!CONSP (elt)) continue;
-      thiscar = Fcar (elt);
+      thiscar = CONSP (elt) ? XCAR (elt) : elt;
       if (!STRINGP (thiscar))
 	continue;
       tem = Fcompare_strings (thiscar, make_number (0), Qnil,
 			      key, make_number (0), Qnil,
-			      completion_ignore_case ? Qt : Qnil);
+			      case_fold);
       if (EQ (tem, Qt))
 	return elt;
       QUIT;
@@ -1797,7 +1835,9 @@
   if (XINT (Fminibuffer_prompt_end ()) == ZV)
     goto exit;
 
-  if (!NILP (test_completion (Fminibuffer_contents ())))
+  if (!NILP (Ftest_completion (Fminibuffer_contents (),
+			       Vminibuffer_completion_table,
+			       Vminibuffer_completion_predicate)))
     goto exit;
 
   /* Call do_completion, but ignore errors.  */
@@ -2476,6 +2516,8 @@
 
   defsubr (&Stry_completion);
   defsubr (&Sall_completions);
+  defsubr (&Stest_completion);
+  defsubr (&Sassoc_string);
   defsubr (&Scompleting_read);
   defsubr (&Sminibuffer_complete);
   defsubr (&Sminibuffer_complete_word);