Function: test-completion
test-completion is a function defined in minibuf.c.
Signature
(test-completion STRING COLLECTION &optional PREDICATE)
Documentation
Return non-nil if STRING is a valid completion.
For instance, if COLLECTION is a list of strings, STRING is a valid completion if it appears in the list and PREDICATE is satisfied.
Takes the same arguments as all-completions and try-completion.
If COLLECTION is a function, it is called with three arguments:
the values STRING, PREDICATE and lambda.
Probably introduced at or before Emacs version 22.1.
Aliases
Source Code
// Defined in /usr/src/emacs/src/minibuf.c
{
Lisp_Object regexps, tail, tem = Qnil;
ptrdiff_t i = 0;
CHECK_STRING (string);
if (NILP (collection) || (CONSP (collection) && !FUNCTIONP (collection)))
{
tem = Fassoc_string (string, collection, completion_ignore_case ? Qt : Qnil);
if (NILP (tem))
return Qnil;
}
else if (VECTORP (collection))
{
/* Bypass intern-soft as that loses for nil. */
tem = oblookup (collection,
SSDATA (string),
SCHARS (string),
SBYTES (string));
if (!SYMBOLP (tem))
{
if (STRING_MULTIBYTE (string))
string = Fstring_make_unibyte (string);
else
string = Fstring_make_multibyte (string);
tem = oblookup (collection,
SSDATA (string),
SCHARS (string),
SBYTES (string));
}
if (completion_ignore_case && !SYMBOLP (tem))
{
for (i = ASIZE (collection) - 1; i >= 0; i--)
{
tail = AREF (collection, i);
if (SYMBOLP (tail))
while (1)
{
if (EQ (Fcompare_strings (string, make_fixnum (0), Qnil,
Fsymbol_name (tail),
make_fixnum (0) , Qnil, Qt),
Qt))
{
tem = tail;
break;
}
if (XSYMBOL (tail)->u.s.next == 0)
break;
XSETSYMBOL (tail, XSYMBOL (tail)->u.s.next);
}
}
}
if (!SYMBOLP (tem))
return Qnil;
}
else if (HASH_TABLE_P (collection))
{
struct Lisp_Hash_Table *h = XHASH_TABLE (collection);
i = hash_lookup (h, string, NULL);
if (i >= 0)
{
tem = HASH_KEY (h, i);
goto found_matching_key;
}
else
for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
{
tem = HASH_KEY (h, i);
if (EQ (tem, Qunbound)) continue;
Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem);
if (!STRINGP (strkey)) continue;
if (EQ (Fcompare_strings (string, Qnil, Qnil,
strkey, Qnil, Qnil,
completion_ignore_case ? Qt : Qnil),
Qt))
goto found_matching_key;
}
return Qnil;
found_matching_key: ;
}
else
return call3 (collection, string, predicate, Qlambda);
/* Reject this element if it fails to match all the regexps. */
if (CONSP (Vcompletion_regexp_list))
{
ptrdiff_t count = SPECPDL_INDEX ();
specbind (Qcase_fold_search, completion_ignore_case ? Qt : Qnil);
for (regexps = Vcompletion_regexp_list; CONSP (regexps);
regexps = XCDR (regexps))
{
/* We can test against STRING, because if we got here, then
the element is equivalent to it. */
if (NILP (Fstring_match (XCAR (regexps), string, Qnil)))
return unbind_to (count, Qnil);
}
unbind_to (count, Qnil);
}
/* Finally, check the predicate. */
if (!NILP (predicate))
{
return HASH_TABLE_P (collection)
? call2 (predicate, tem, HASH_VALUE (XHASH_TABLE (collection), i))
: call1 (predicate, tem);
}
else
return Qt;
}