From: Stefan Monnier Date: Sun, 7 Jul 2002 21:09:14 +0000 (+0000) Subject: (Ftry_completion, Fall_completions, Ftest_completion): X-Git-Tag: ttn-vms-21-2-B4~14264 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=85cd4372bcaf22d8f12116bd01ed332bc867902b;p=emacs.git (Ftry_completion, Fall_completions, Ftest_completion): Add support for hash-tables. (Ftry_completion): Return t even if the string appears multiple times. --- diff --git a/src/minibuf.c b/src/minibuf.c index f4aeb0f8c38..87fc6f8ce4a 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1089,8 +1089,9 @@ common to all matches is returned as a string. If there is no match at all, nil is returned. For a unique match which is exact, t is returned. -ALIST can be an obarray instead of an alist. -Then the print names of all symbols in the obarray are the possible matches. +If ALIST is a hash-table, all the string keys are the possible matches. +If ALIST is an obarray, the names of all symbols in the obarray +are the possible matches. ALIST can also be a function to do the completion itself. It receives three arguments: the values STRING, PREDICATE and nil. @@ -1100,7 +1101,8 @@ If optional third argument PREDICATE is non-nil, it is used to test each possible match. The match is a candidate only if PREDICATE returns non-nil. The argument given to PREDICATE is the alist element -or the symbol from the obarray. +or the symbol from the obarray. If ALIST is a hash-table, +predicate is called with two arguments: the key and the value. Additionally to this predicate, `completion-regexp-list' is used to further constrain the set of candidates. */) (string, alist, predicate) @@ -1111,37 +1113,38 @@ is used to further constrain the set of candidates. */) int bestmatchsize = 0; /* These are in bytes, too. */ int compare, matchsize; - int list = NILP (alist) || (CONSP (alist) - && (!SYMBOLP (XCAR (alist)) - || NILP (XCAR (alist)))); + int type = HASH_TABLE_P (alist) ? 3 + : VECTORP (alist) ? 2 + : NILP (alist) || (CONSP (alist) + && (!SYMBOLP (XCAR (alist)) + || NILP (XCAR (alist)))); int index = 0, obsize = 0; int matchcount = 0; Lisp_Object bucket, zero, end, tem; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; CHECK_STRING (string); - if (!list && !VECTORP (alist)) + if (type == 0) return call3 (alist, string, predicate, Qnil); bestmatch = bucket = Qnil; /* If ALIST is not a list, set TAIL just for gc pro. */ tail = alist; - if (! list) + if (type == 2) { - index = 0; obsize = XVECTOR (alist)->size; bucket = XVECTOR (alist)->contents[index]; } while (1) { - /* Get the next element of the alist or obarray. */ + /* Get the next element of the alist, obarray, or hash-table. */ /* Exit the loop if the elements are all used up. */ /* elt gets the alist element or symbol. eltstring gets the name to check as a completion. */ - if (list) + if (type == 1) { if (!CONSP (tail)) break; @@ -1149,7 +1152,7 @@ is used to further constrain the set of candidates. */) eltstring = CONSP (elt) ? XCAR (elt) : elt; tail = XCDR (tail); } - else + else if (type == 2) { if (XFASTINT (bucket) != 0) { @@ -1168,6 +1171,16 @@ is used to further constrain the set of candidates. */) continue; } } + else /* if (type == 3) */ + { + while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist)) + && NILP (HASH_HASH (XHASH_TABLE (alist), index))) + index++; + if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist))) + break; + else + elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++); + } /* Is this element a possible completion? */ @@ -1205,7 +1218,10 @@ is used to further constrain the set of candidates. */) else { GCPRO4 (tail, string, eltstring, bestmatch); - tem = call1 (predicate, elt); + tem = type == 3 + ? call2 (predicate, elt, + HASH_VALUE (XHASH_TABLE (alist), index - 1)) + : call1 (predicate, elt); UNGCPRO; } if (NILP (tem)) continue; @@ -1213,9 +1229,9 @@ is used to further constrain the set of candidates. */) /* Update computation of how much all possible completions match */ - matchcount++; if (NILP (bestmatch)) { + matchcount = 1; bestmatch = eltstring; bestmatchsize = XSTRING (eltstring)->size; } @@ -1269,6 +1285,10 @@ is used to further constrain the set of candidates. */) ! EQ (Qt, tem)))) bestmatch = eltstring; } + if (bestmatchsize != XSTRING (eltstring)->size + || bestmatchsize != matchsize) + /* Don't count the same string multiple times. */ + matchcount++; bestmatchsize = matchsize; if (matchsize <= XSTRING (string)->size && matchcount > 1) @@ -1308,8 +1328,9 @@ DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 4, 0, Each car of each element of ALIST is tested to see if it begins with STRING. The value is a list of all the strings from ALIST that match. -ALIST can be an obarray instead of an alist. -Then the print names of all symbols in the obarray are the possible matches. +If ALIST is a hash-table, all the string keys are the possible matches. +If ALIST is an obarray, the names of all symbols in the obarray +are the possible matches. ALIST can also be a function to do the completion itself. It receives three arguments: the values STRING, PREDICATE and t. @@ -1319,7 +1340,8 @@ If optional third argument PREDICATE is non-nil, it is used to test each possible match. The match is a candidate only if PREDICATE returns non-nil. The argument given to PREDICATE is the alist element -or the symbol from the obarray. +or the symbol from the obarray. If ALIST is a hash-table, +predicate is called with two arguments: the key and the value. Additionally to this predicate, `completion-regexp-list' is used to further constrain the set of candidates. @@ -1331,37 +1353,36 @@ are ignored unless STRING itself starts with a space. */) { Lisp_Object tail, elt, eltstring; Lisp_Object allmatches; - int list = NILP (alist) || (CONSP (alist) - && (!SYMBOLP (XCAR (alist)) - || NILP (XCAR (alist)))); + int type = HASH_TABLE_P (alist) ? 3 + : VECTORP (alist) ? 2 + : 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; CHECK_STRING (string); - if (!list && !VECTORP (alist)) - { - return call3 (alist, string, predicate, Qt); - } + if (type == 0) + return call3 (alist, string, predicate, Qt); allmatches = bucket = Qnil; /* If ALIST is not a list, set TAIL just for gc pro. */ tail = alist; - if (! list) + if (type == 2) { - index = 0; obsize = XVECTOR (alist)->size; bucket = XVECTOR (alist)->contents[index]; } while (1) { - /* Get the next element of the alist or obarray. */ + /* Get the next element of the alist, obarray, or hash-table. */ /* Exit the loop if the elements are all used up. */ /* elt gets the alist element or symbol. eltstring gets the name to check as a completion. */ - if (list) + if (type == 1) { if (!CONSP (tail)) break; @@ -1369,7 +1390,7 @@ are ignored unless STRING itself starts with a space. */) eltstring = CONSP (elt) ? XCAR (elt) : elt; tail = XCDR (tail); } - else + else if (type == 2) { if (XFASTINT (bucket) != 0) { @@ -1388,6 +1409,16 @@ are ignored unless STRING itself starts with a space. */) continue; } } + else /* if (type == 3) */ + { + while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist)) + && NILP (HASH_HASH (XHASH_TABLE (alist), index))) + index++; + if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist))) + break; + else + elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++); + } /* Is this element a possible completion? */ @@ -1432,7 +1463,10 @@ are ignored unless STRING itself starts with a space. */) else { GCPRO4 (tail, eltstring, allmatches, string); - tem = call1 (predicate, elt); + tem = type == 3 + ? call2 (predicate, elt, + HASH_VALUE (XHASH_TABLE (alist), index - 1)) + : call1 (predicate, elt); UNGCPRO; } if (NILP (tem)) continue; @@ -1564,6 +1598,7 @@ the values STRING, PREDICATE and `lambda'. */) Lisp_Object string, alist, predicate; { Lisp_Object regexps, tem = Qnil; + int i = 0; CHECK_STRING (string); @@ -1571,9 +1606,7 @@ the values STRING, PREDICATE and `lambda'. */) || NILP (alist)) { tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil); - if (CONSP (tem)) - tem = XCAR (tem); - else + if NILP (tem) return Qnil; } else if (VECTORP (alist)) @@ -1598,6 +1631,14 @@ the values STRING, PREDICATE and `lambda'. */) return Qnil; } } + else if (HASH_TABLE_P (alist)) + { + i = hash_lookup (XHASH_TABLE (alist), string, NULL); + if (i >= 0) + tem = HASH_KEY (XHASH_TABLE (alist), i); + else + return Qnil; + } else return call3 (alist, string, predicate, Qlambda); @@ -1613,7 +1654,9 @@ the values STRING, PREDICATE and `lambda'. */) /* Finally, check the predicate. */ if (!NILP (predicate)) - return call1 (predicate, tem); + return HASH_TABLE_P (alist) + ? call2 (predicate, tem, HASH_VALUE (XHASH_TABLE (alist), i)) + : call1 (predicate, tem); else return Qt; }