diff options
| author | Stefan Monnier | 2002-04-09 19:28:42 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2002-04-09 19:28:42 +0000 |
| commit | 695deb1857dd95239df0139894e40719699a6cc8 (patch) | |
| tree | b9cce6189a878e362759110c5ca026f74d980a19 /src | |
| parent | da2a1edf5b6286e186d440ca3ede0356cebdd2ed (diff) | |
| download | emacs-695deb1857dd95239df0139894e40719699a6cc8.tar.gz emacs-695deb1857dd95239df0139894e40719699a6cc8.zip | |
(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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/minibuf.c | 134 |
1 files changed, 88 insertions, 46 deletions
diff --git a/src/minibuf.c b/src/minibuf.c index 103020b1693..92a33022080 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -427,7 +427,7 @@ read_minibuf (map, initial, prompt, backup_n, expflag, | |||
| 427 | GCPRO5 (map, initial, val, ambient_dir, input_method); | 427 | GCPRO5 (map, initial, val, ambient_dir, input_method); |
| 428 | 428 | ||
| 429 | if (!STRINGP (prompt)) | 429 | if (!STRINGP (prompt)) |
| 430 | prompt = build_string (""); | 430 | prompt = empty_string; |
| 431 | 431 | ||
| 432 | if (!enable_recursive_minibuffers | 432 | if (!enable_recursive_minibuffers |
| 433 | && minibuf_level > 0) | 433 | && minibuf_level > 0) |
| @@ -1103,7 +1103,9 @@ is used to further constrain the set of candidates. */) | |||
| 1103 | int bestmatchsize = 0; | 1103 | int bestmatchsize = 0; |
| 1104 | /* These are in bytes, too. */ | 1104 | /* These are in bytes, too. */ |
| 1105 | int compare, matchsize; | 1105 | int compare, matchsize; |
| 1106 | int list = CONSP (alist) || NILP (alist); | 1106 | int list = NILP (alist) || (CONSP (alist) |
| 1107 | && (!SYMBOLP (XCAR (alist)) | ||
| 1108 | || NILP (XCAR (alist)))); | ||
| 1107 | int index = 0, obsize = 0; | 1109 | int index = 0, obsize = 0; |
| 1108 | int matchcount = 0; | 1110 | int matchcount = 0; |
| 1109 | Lisp_Object bucket, zero, end, tem; | 1111 | Lisp_Object bucket, zero, end, tem; |
| @@ -1133,11 +1135,11 @@ is used to further constrain the set of candidates. */) | |||
| 1133 | 1135 | ||
| 1134 | if (list) | 1136 | if (list) |
| 1135 | { | 1137 | { |
| 1136 | if (NILP (tail)) | 1138 | if (!CONSP (tail)) |
| 1137 | break; | 1139 | break; |
| 1138 | elt = Fcar (tail); | 1140 | elt = XCAR (tail); |
| 1139 | eltstring = Fcar (elt); | 1141 | eltstring = CONSP (elt) ? XCAR (elt) : elt; |
| 1140 | tail = Fcdr (tail); | 1142 | tail = XCDR (tail); |
| 1141 | } | 1143 | } |
| 1142 | else | 1144 | else |
| 1143 | { | 1145 | { |
| @@ -1225,6 +1227,7 @@ is used to further constrain the set of candidates. */) | |||
| 1225 | matchsize = XINT (tem) - 1; | 1227 | matchsize = XINT (tem) - 1; |
| 1226 | 1228 | ||
| 1227 | if (matchsize < 0) | 1229 | if (matchsize < 0) |
| 1230 | /* When can this happen ? -stef */ | ||
| 1228 | matchsize = compare; | 1231 | matchsize = compare; |
| 1229 | if (completion_ignore_case) | 1232 | if (completion_ignore_case) |
| 1230 | { | 1233 | { |
| @@ -1259,6 +1262,10 @@ is used to further constrain the set of candidates. */) | |||
| 1259 | bestmatch = eltstring; | 1262 | bestmatch = eltstring; |
| 1260 | } | 1263 | } |
| 1261 | bestmatchsize = matchsize; | 1264 | bestmatchsize = matchsize; |
| 1265 | if (matchsize <= XSTRING (string)->size | ||
| 1266 | && matchcount > 1) | ||
| 1267 | /* No need to look any further. */ | ||
| 1268 | break; | ||
| 1262 | } | 1269 | } |
| 1263 | } | 1270 | } |
| 1264 | } | 1271 | } |
| @@ -1316,7 +1323,9 @@ are ignored unless STRING itself starts with a space. */) | |||
| 1316 | { | 1323 | { |
| 1317 | Lisp_Object tail, elt, eltstring; | 1324 | Lisp_Object tail, elt, eltstring; |
| 1318 | Lisp_Object allmatches; | 1325 | Lisp_Object allmatches; |
| 1319 | int list = CONSP (alist) || NILP (alist); | 1326 | int list = NILP (alist) || (CONSP (alist) |
| 1327 | && (!SYMBOLP (XCAR (alist)) | ||
| 1328 | || NILP (XCAR (alist)))); | ||
| 1320 | int index = 0, obsize = 0; | 1329 | int index = 0, obsize = 0; |
| 1321 | Lisp_Object bucket, tem; | 1330 | Lisp_Object bucket, tem; |
| 1322 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 1331 | struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
| @@ -1346,11 +1355,11 @@ are ignored unless STRING itself starts with a space. */) | |||
| 1346 | 1355 | ||
| 1347 | if (list) | 1356 | if (list) |
| 1348 | { | 1357 | { |
| 1349 | if (NILP (tail)) | 1358 | if (!CONSP (tail)) |
| 1350 | break; | 1359 | break; |
| 1351 | elt = Fcar (tail); | 1360 | elt = XCAR (tail); |
| 1352 | eltstring = Fcar (elt); | 1361 | eltstring = CONSP (elt) ? XCAR (elt) : elt; |
| 1353 | tail = Fcdr (tail); | 1362 | tail = XCDR (tail); |
| 1354 | } | 1363 | } |
| 1355 | else | 1364 | else |
| 1356 | { | 1365 | { |
| @@ -1486,7 +1495,7 @@ Completion ignores case if the ambient value of | |||
| 1486 | specbind (Qminibuffer_completion_table, table); | 1495 | specbind (Qminibuffer_completion_table, table); |
| 1487 | specbind (Qminibuffer_completion_predicate, predicate); | 1496 | specbind (Qminibuffer_completion_predicate, predicate); |
| 1488 | specbind (Qminibuffer_completion_confirm, | 1497 | specbind (Qminibuffer_completion_confirm, |
| 1489 | EQ (require_match, Qt) ? Qnil : Qt); | 1498 | EQ (require_match, Qt) ? Qnil : require_match); |
| 1490 | last_exact_completion = Qnil; | 1499 | last_exact_completion = Qnil; |
| 1491 | 1500 | ||
| 1492 | position = Qnil; | 1501 | position = Qnil; |
| @@ -1535,47 +1544,70 @@ Completion ignores case if the ambient value of | |||
| 1535 | } | 1544 | } |
| 1536 | 1545 | ||
| 1537 | Lisp_Object Fminibuffer_completion_help (); | 1546 | Lisp_Object Fminibuffer_completion_help (); |
| 1538 | Lisp_Object assoc_for_completion (); | 1547 | Lisp_Object Fassoc_string (); |
| 1539 | 1548 | ||
| 1540 | /* Test whether TXT is an exact completion. */ | 1549 | /* Test whether TXT is an exact completion. */ |
| 1541 | Lisp_Object | 1550 | DEFUN ("test-completion", Ftest_completion, Stest_completion, 2, 3, 0, |
| 1542 | test_completion (txt) | 1551 | doc: /* Return non-nil if STRING is a valid completion. |
| 1543 | Lisp_Object txt; | 1552 | Takes the same arguments as `all-completions' and `try-completion'. |
| 1553 | If ALIST is a function, it is called with three arguments: | ||
| 1554 | the values STRING, PREDICATE and `lambda'. */) | ||
| 1555 | (string, alist, predicate) | ||
| 1556 | Lisp_Object string, alist, predicate; | ||
| 1544 | { | 1557 | { |
| 1545 | Lisp_Object tem; | 1558 | Lisp_Object regexps, tem = Qnil; |
| 1546 | 1559 | ||
| 1547 | if (CONSP (Vminibuffer_completion_table) | 1560 | CHECK_STRING (string); |
| 1548 | || NILP (Vminibuffer_completion_table)) | 1561 | |
| 1549 | return assoc_for_completion (txt, Vminibuffer_completion_table); | 1562 | if ((CONSP (alist) && (!SYMBOLP (XCAR (alist)) || NILP (XCAR (alist)))) |
| 1550 | else if (VECTORP (Vminibuffer_completion_table)) | 1563 | || NILP (alist)) |
| 1564 | { | ||
| 1565 | tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil); | ||
| 1566 | if (CONSP (tem)) | ||
| 1567 | tem = XCAR (tem); | ||
| 1568 | else | ||
| 1569 | return Qnil; | ||
| 1570 | } | ||
| 1571 | else if (VECTORP (alist)) | ||
| 1551 | { | 1572 | { |
| 1552 | /* Bypass intern-soft as that loses for nil */ | 1573 | /* Bypass intern-soft as that loses for nil. */ |
| 1553 | tem = oblookup (Vminibuffer_completion_table, | 1574 | tem = oblookup (alist, |
| 1554 | XSTRING (txt)->data, | 1575 | XSTRING (string)->data, |
| 1555 | XSTRING (txt)->size, | 1576 | XSTRING (string)->size, |
| 1556 | STRING_BYTES (XSTRING (txt))); | 1577 | STRING_BYTES (XSTRING (string))); |
| 1557 | if (!SYMBOLP (tem)) | 1578 | if (!SYMBOLP (tem)) |
| 1558 | { | 1579 | { |
| 1559 | if (STRING_MULTIBYTE (txt)) | 1580 | if (STRING_MULTIBYTE (string)) |
| 1560 | txt = Fstring_make_unibyte (txt); | 1581 | string = Fstring_make_unibyte (string); |
| 1561 | else | 1582 | else |
| 1562 | txt = Fstring_make_multibyte (txt); | 1583 | string = Fstring_make_multibyte (string); |
| 1563 | 1584 | ||
| 1564 | tem = oblookup (Vminibuffer_completion_table, | 1585 | tem = oblookup (Vminibuffer_completion_table, |
| 1565 | XSTRING (txt)->data, | 1586 | XSTRING (string)->data, |
| 1566 | XSTRING (txt)->size, | 1587 | XSTRING (string)->size, |
| 1567 | STRING_BYTES (XSTRING (txt))); | 1588 | STRING_BYTES (XSTRING (string))); |
| 1568 | if (!SYMBOLP (tem)) | 1589 | if (!SYMBOLP (tem)) |
| 1569 | return Qnil; | 1590 | return Qnil; |
| 1570 | } | 1591 | } |
| 1571 | if (!NILP (Vminibuffer_completion_predicate)) | ||
| 1572 | return call1 (Vminibuffer_completion_predicate, tem); | ||
| 1573 | else | ||
| 1574 | return Qt; | ||
| 1575 | } | 1592 | } |
| 1576 | else | 1593 | else |
| 1577 | return call3 (Vminibuffer_completion_table, txt, | 1594 | return call3 (alist, string, predicate, Qlambda); |
| 1578 | Vminibuffer_completion_predicate, Qlambda); | 1595 | |
| 1596 | /* Reject this element if it fails to match all the regexps. */ | ||
| 1597 | for (regexps = Vcompletion_regexp_list; CONSP (regexps); | ||
| 1598 | regexps = XCDR (regexps)) | ||
| 1599 | { | ||
| 1600 | if (NILP (Fstring_match (XCAR (regexps), | ||
| 1601 | SYMBOLP (tem) ? string : tem, | ||
| 1602 | Qnil))) | ||
| 1603 | return Qnil; | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | /* Finally, check the predicate. */ | ||
| 1607 | if (!NILP (predicate)) | ||
| 1608 | return call1 (predicate, tem); | ||
| 1609 | else | ||
| 1610 | return Qt; | ||
| 1579 | } | 1611 | } |
| 1580 | 1612 | ||
| 1581 | /* returns: | 1613 | /* returns: |
| @@ -1645,7 +1677,9 @@ do_completion () | |||
| 1645 | } | 1677 | } |
| 1646 | 1678 | ||
| 1647 | /* It did find a match. Do we match some possibility exactly now? */ | 1679 | /* It did find a match. Do we match some possibility exactly now? */ |
| 1648 | tem = test_completion (Fminibuffer_contents ()); | 1680 | tem = Ftest_completion (Fminibuffer_contents (), |
| 1681 | Vminibuffer_completion_table, | ||
| 1682 | Vminibuffer_completion_predicate); | ||
| 1649 | if (NILP (tem)) | 1683 | if (NILP (tem)) |
| 1650 | { | 1684 | { |
| 1651 | /* not an exact match */ | 1685 | /* not an exact match */ |
| @@ -1679,10 +1713,15 @@ do_completion () | |||
| 1679 | 1713 | ||
| 1680 | /* Like assoc but assumes KEY is a string, and ignores case if appropriate. */ | 1714 | /* Like assoc but assumes KEY is a string, and ignores case if appropriate. */ |
| 1681 | 1715 | ||
| 1682 | Lisp_Object | 1716 | DEFUN ("assoc-string", Fassoc_string, Sassoc_string, 2, 3, 0, |
| 1683 | assoc_for_completion (key, list) | 1717 | doc: /* Like `assoc' but specifically for strings. |
| 1718 | Unibyte strings are converted to multibyte for comparison. | ||
| 1719 | And case is ignored if CASE-FOLD is non-nil. | ||
| 1720 | As opposed to `assoc', it will also match an entry consisting of a single | ||
| 1721 | string rather than a cons cell whose car is a string. */) | ||
| 1722 | (key, list, case_fold) | ||
| 1684 | register Lisp_Object key; | 1723 | register Lisp_Object key; |
| 1685 | Lisp_Object list; | 1724 | Lisp_Object list, case_fold; |
| 1686 | { | 1725 | { |
| 1687 | register Lisp_Object tail; | 1726 | register Lisp_Object tail; |
| 1688 | 1727 | ||
| @@ -1690,13 +1729,12 @@ assoc_for_completion (key, list) | |||
| 1690 | { | 1729 | { |
| 1691 | register Lisp_Object elt, tem, thiscar; | 1730 | register Lisp_Object elt, tem, thiscar; |
| 1692 | elt = Fcar (tail); | 1731 | elt = Fcar (tail); |
| 1693 | if (!CONSP (elt)) continue; | 1732 | thiscar = CONSP (elt) ? XCAR (elt) : elt; |
| 1694 | thiscar = Fcar (elt); | ||
| 1695 | if (!STRINGP (thiscar)) | 1733 | if (!STRINGP (thiscar)) |
| 1696 | continue; | 1734 | continue; |
| 1697 | tem = Fcompare_strings (thiscar, make_number (0), Qnil, | 1735 | tem = Fcompare_strings (thiscar, make_number (0), Qnil, |
| 1698 | key, make_number (0), Qnil, | 1736 | key, make_number (0), Qnil, |
| 1699 | completion_ignore_case ? Qt : Qnil); | 1737 | case_fold); |
| 1700 | if (EQ (tem, Qt)) | 1738 | if (EQ (tem, Qt)) |
| 1701 | return elt; | 1739 | return elt; |
| 1702 | QUIT; | 1740 | QUIT; |
| @@ -1797,7 +1835,9 @@ a repetition of this command will exit. */) | |||
| 1797 | if (XINT (Fminibuffer_prompt_end ()) == ZV) | 1835 | if (XINT (Fminibuffer_prompt_end ()) == ZV) |
| 1798 | goto exit; | 1836 | goto exit; |
| 1799 | 1837 | ||
| 1800 | if (!NILP (test_completion (Fminibuffer_contents ()))) | 1838 | if (!NILP (Ftest_completion (Fminibuffer_contents (), |
| 1839 | Vminibuffer_completion_table, | ||
| 1840 | Vminibuffer_completion_predicate))) | ||
| 1801 | goto exit; | 1841 | goto exit; |
| 1802 | 1842 | ||
| 1803 | /* Call do_completion, but ignore errors. */ | 1843 | /* Call do_completion, but ignore errors. */ |
| @@ -2476,6 +2516,8 @@ properties. */); | |||
| 2476 | 2516 | ||
| 2477 | defsubr (&Stry_completion); | 2517 | defsubr (&Stry_completion); |
| 2478 | defsubr (&Sall_completions); | 2518 | defsubr (&Sall_completions); |
| 2519 | defsubr (&Stest_completion); | ||
| 2520 | defsubr (&Sassoc_string); | ||
| 2479 | defsubr (&Scompleting_read); | 2521 | defsubr (&Scompleting_read); |
| 2480 | defsubr (&Sminibuffer_complete); | 2522 | defsubr (&Sminibuffer_complete); |
| 2481 | defsubr (&Sminibuffer_complete_word); | 2523 | defsubr (&Sminibuffer_complete_word); |