aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2002-07-07 21:09:14 +0000
committerStefan Monnier2002-07-07 21:09:14 +0000
commit85cd4372bcaf22d8f12116bd01ed332bc867902b (patch)
treecf3cddde054487dafc38528dbc6e28b24ed42548
parentb14323798719688ea2725a9b80e8e6e4d9139b6e (diff)
downloademacs-85cd4372bcaf22d8f12116bd01ed332bc867902b.tar.gz
emacs-85cd4372bcaf22d8f12116bd01ed332bc867902b.zip
(Ftry_completion, Fall_completions, Ftest_completion):
Add support for hash-tables. (Ftry_completion): Return t even if the string appears multiple times.
-rw-r--r--src/minibuf.c111
1 files changed, 77 insertions, 34 deletions
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.
1089If there is no match at all, nil is returned. 1089If there is no match at all, nil is returned.
1090For a unique match which is exact, t is returned. 1090For a unique match which is exact, t is returned.
1091 1091
1092ALIST can be an obarray instead of an alist. 1092If ALIST is a hash-table, all the string keys are the possible matches.
1093Then the print names of all symbols in the obarray are the possible matches. 1093If ALIST is an obarray, the names of all symbols in the obarray
1094are the possible matches.
1094 1095
1095ALIST can also be a function to do the completion itself. 1096ALIST can also be a function to do the completion itself.
1096It receives three arguments: the values STRING, PREDICATE and nil. 1097It receives three arguments: the values STRING, PREDICATE and nil.
@@ -1100,7 +1101,8 @@ If optional third argument PREDICATE is non-nil,
1100it is used to test each possible match. 1101it is used to test each possible match.
1101The match is a candidate only if PREDICATE returns non-nil. 1102The match is a candidate only if PREDICATE returns non-nil.
1102The argument given to PREDICATE is the alist element 1103The argument given to PREDICATE is the alist element
1103or the symbol from the obarray. 1104or the symbol from the obarray. If ALIST is a hash-table,
1105predicate is called with two arguments: the key and the value.
1104Additionally to this predicate, `completion-regexp-list' 1106Additionally to this predicate, `completion-regexp-list'
1105is used to further constrain the set of candidates. */) 1107is used to further constrain the set of candidates. */)
1106 (string, alist, predicate) 1108 (string, alist, predicate)
@@ -1111,37 +1113,38 @@ is used to further constrain the set of candidates. */)
1111 int bestmatchsize = 0; 1113 int bestmatchsize = 0;
1112 /* These are in bytes, too. */ 1114 /* These are in bytes, too. */
1113 int compare, matchsize; 1115 int compare, matchsize;
1114 int list = NILP (alist) || (CONSP (alist) 1116 int type = HASH_TABLE_P (alist) ? 3
1115 && (!SYMBOLP (XCAR (alist)) 1117 : VECTORP (alist) ? 2
1116 || NILP (XCAR (alist)))); 1118 : NILP (alist) || (CONSP (alist)
1119 && (!SYMBOLP (XCAR (alist))
1120 || NILP (XCAR (alist))));
1117 int index = 0, obsize = 0; 1121 int index = 0, obsize = 0;
1118 int matchcount = 0; 1122 int matchcount = 0;
1119 Lisp_Object bucket, zero, end, tem; 1123 Lisp_Object bucket, zero, end, tem;
1120 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 1124 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1121 1125
1122 CHECK_STRING (string); 1126 CHECK_STRING (string);
1123 if (!list && !VECTORP (alist)) 1127 if (type == 0)
1124 return call3 (alist, string, predicate, Qnil); 1128 return call3 (alist, string, predicate, Qnil);
1125 1129
1126 bestmatch = bucket = Qnil; 1130 bestmatch = bucket = Qnil;
1127 1131
1128 /* If ALIST is not a list, set TAIL just for gc pro. */ 1132 /* If ALIST is not a list, set TAIL just for gc pro. */
1129 tail = alist; 1133 tail = alist;
1130 if (! list) 1134 if (type == 2)
1131 { 1135 {
1132 index = 0;
1133 obsize = XVECTOR (alist)->size; 1136 obsize = XVECTOR (alist)->size;
1134 bucket = XVECTOR (alist)->contents[index]; 1137 bucket = XVECTOR (alist)->contents[index];
1135 } 1138 }
1136 1139
1137 while (1) 1140 while (1)
1138 { 1141 {
1139 /* Get the next element of the alist or obarray. */ 1142 /* Get the next element of the alist, obarray, or hash-table. */
1140 /* Exit the loop if the elements are all used up. */ 1143 /* Exit the loop if the elements are all used up. */
1141 /* elt gets the alist element or symbol. 1144 /* elt gets the alist element or symbol.
1142 eltstring gets the name to check as a completion. */ 1145 eltstring gets the name to check as a completion. */
1143 1146
1144 if (list) 1147 if (type == 1)
1145 { 1148 {
1146 if (!CONSP (tail)) 1149 if (!CONSP (tail))
1147 break; 1150 break;
@@ -1149,7 +1152,7 @@ is used to further constrain the set of candidates. */)
1149 eltstring = CONSP (elt) ? XCAR (elt) : elt; 1152 eltstring = CONSP (elt) ? XCAR (elt) : elt;
1150 tail = XCDR (tail); 1153 tail = XCDR (tail);
1151 } 1154 }
1152 else 1155 else if (type == 2)
1153 { 1156 {
1154 if (XFASTINT (bucket) != 0) 1157 if (XFASTINT (bucket) != 0)
1155 { 1158 {
@@ -1168,6 +1171,16 @@ is used to further constrain the set of candidates. */)
1168 continue; 1171 continue;
1169 } 1172 }
1170 } 1173 }
1174 else /* if (type == 3) */
1175 {
1176 while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist))
1177 && NILP (HASH_HASH (XHASH_TABLE (alist), index)))
1178 index++;
1179 if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist)))
1180 break;
1181 else
1182 elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++);
1183 }
1171 1184
1172 /* Is this element a possible completion? */ 1185 /* Is this element a possible completion? */
1173 1186
@@ -1205,7 +1218,10 @@ is used to further constrain the set of candidates. */)
1205 else 1218 else
1206 { 1219 {
1207 GCPRO4 (tail, string, eltstring, bestmatch); 1220 GCPRO4 (tail, string, eltstring, bestmatch);
1208 tem = call1 (predicate, elt); 1221 tem = type == 3
1222 ? call2 (predicate, elt,
1223 HASH_VALUE (XHASH_TABLE (alist), index - 1))
1224 : call1 (predicate, elt);
1209 UNGCPRO; 1225 UNGCPRO;
1210 } 1226 }
1211 if (NILP (tem)) continue; 1227 if (NILP (tem)) continue;
@@ -1213,9 +1229,9 @@ is used to further constrain the set of candidates. */)
1213 1229
1214 /* Update computation of how much all possible completions match */ 1230 /* Update computation of how much all possible completions match */
1215 1231
1216 matchcount++;
1217 if (NILP (bestmatch)) 1232 if (NILP (bestmatch))
1218 { 1233 {
1234 matchcount = 1;
1219 bestmatch = eltstring; 1235 bestmatch = eltstring;
1220 bestmatchsize = XSTRING (eltstring)->size; 1236 bestmatchsize = XSTRING (eltstring)->size;
1221 } 1237 }
@@ -1269,6 +1285,10 @@ is used to further constrain the set of candidates. */)
1269 ! EQ (Qt, tem)))) 1285 ! EQ (Qt, tem))))
1270 bestmatch = eltstring; 1286 bestmatch = eltstring;
1271 } 1287 }
1288 if (bestmatchsize != XSTRING (eltstring)->size
1289 || bestmatchsize != matchsize)
1290 /* Don't count the same string multiple times. */
1291 matchcount++;
1272 bestmatchsize = matchsize; 1292 bestmatchsize = matchsize;
1273 if (matchsize <= XSTRING (string)->size 1293 if (matchsize <= XSTRING (string)->size
1274 && matchcount > 1) 1294 && matchcount > 1)
@@ -1308,8 +1328,9 @@ DEFUN ("all-completions", Fall_completions, Sall_completions, 2, 4, 0,
1308Each car of each element of ALIST is tested to see if it begins with STRING. 1328Each car of each element of ALIST is tested to see if it begins with STRING.
1309The value is a list of all the strings from ALIST that match. 1329The value is a list of all the strings from ALIST that match.
1310 1330
1311ALIST can be an obarray instead of an alist. 1331If ALIST is a hash-table, all the string keys are the possible matches.
1312Then the print names of all symbols in the obarray are the possible matches. 1332If ALIST is an obarray, the names of all symbols in the obarray
1333are the possible matches.
1313 1334
1314ALIST can also be a function to do the completion itself. 1335ALIST can also be a function to do the completion itself.
1315It receives three arguments: the values STRING, PREDICATE and t. 1336It receives three arguments: the values STRING, PREDICATE and t.
@@ -1319,7 +1340,8 @@ If optional third argument PREDICATE is non-nil,
1319it is used to test each possible match. 1340it is used to test each possible match.
1320The match is a candidate only if PREDICATE returns non-nil. 1341The match is a candidate only if PREDICATE returns non-nil.
1321The argument given to PREDICATE is the alist element 1342The argument given to PREDICATE is the alist element
1322or the symbol from the obarray. 1343or the symbol from the obarray. If ALIST is a hash-table,
1344predicate is called with two arguments: the key and the value.
1323Additionally to this predicate, `completion-regexp-list' 1345Additionally to this predicate, `completion-regexp-list'
1324is used to further constrain the set of candidates. 1346is used to further constrain the set of candidates.
1325 1347
@@ -1331,37 +1353,36 @@ are ignored unless STRING itself starts with a space. */)
1331{ 1353{
1332 Lisp_Object tail, elt, eltstring; 1354 Lisp_Object tail, elt, eltstring;
1333 Lisp_Object allmatches; 1355 Lisp_Object allmatches;
1334 int list = NILP (alist) || (CONSP (alist) 1356 int type = HASH_TABLE_P (alist) ? 3
1335 && (!SYMBOLP (XCAR (alist)) 1357 : VECTORP (alist) ? 2
1336 || NILP (XCAR (alist)))); 1358 : NILP (alist) || (CONSP (alist)
1359 && (!SYMBOLP (XCAR (alist))
1360 || NILP (XCAR (alist))));
1337 int index = 0, obsize = 0; 1361 int index = 0, obsize = 0;
1338 Lisp_Object bucket, tem; 1362 Lisp_Object bucket, tem;
1339 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 1363 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1340 1364
1341 CHECK_STRING (string); 1365 CHECK_STRING (string);
1342 if (!list && !VECTORP (alist)) 1366 if (type == 0)
1343 { 1367 return call3 (alist, string, predicate, Qt);
1344 return call3 (alist, string, predicate, Qt);
1345 }
1346 allmatches = bucket = Qnil; 1368 allmatches = bucket = Qnil;
1347 1369
1348 /* If ALIST is not a list, set TAIL just for gc pro. */ 1370 /* If ALIST is not a list, set TAIL just for gc pro. */
1349 tail = alist; 1371 tail = alist;
1350 if (! list) 1372 if (type == 2)
1351 { 1373 {
1352 index = 0;
1353 obsize = XVECTOR (alist)->size; 1374 obsize = XVECTOR (alist)->size;
1354 bucket = XVECTOR (alist)->contents[index]; 1375 bucket = XVECTOR (alist)->contents[index];
1355 } 1376 }
1356 1377
1357 while (1) 1378 while (1)
1358 { 1379 {
1359 /* Get the next element of the alist or obarray. */ 1380 /* Get the next element of the alist, obarray, or hash-table. */
1360 /* Exit the loop if the elements are all used up. */ 1381 /* Exit the loop if the elements are all used up. */
1361 /* elt gets the alist element or symbol. 1382 /* elt gets the alist element or symbol.
1362 eltstring gets the name to check as a completion. */ 1383 eltstring gets the name to check as a completion. */
1363 1384
1364 if (list) 1385 if (type == 1)
1365 { 1386 {
1366 if (!CONSP (tail)) 1387 if (!CONSP (tail))
1367 break; 1388 break;
@@ -1369,7 +1390,7 @@ are ignored unless STRING itself starts with a space. */)
1369 eltstring = CONSP (elt) ? XCAR (elt) : elt; 1390 eltstring = CONSP (elt) ? XCAR (elt) : elt;
1370 tail = XCDR (tail); 1391 tail = XCDR (tail);
1371 } 1392 }
1372 else 1393 else if (type == 2)
1373 { 1394 {
1374 if (XFASTINT (bucket) != 0) 1395 if (XFASTINT (bucket) != 0)
1375 { 1396 {
@@ -1388,6 +1409,16 @@ are ignored unless STRING itself starts with a space. */)
1388 continue; 1409 continue;
1389 } 1410 }
1390 } 1411 }
1412 else /* if (type == 3) */
1413 {
1414 while (index < HASH_TABLE_SIZE (XHASH_TABLE (alist))
1415 && NILP (HASH_HASH (XHASH_TABLE (alist), index)))
1416 index++;
1417 if (index >= HASH_TABLE_SIZE (XHASH_TABLE (alist)))
1418 break;
1419 else
1420 elt = eltstring = HASH_KEY (XHASH_TABLE (alist), index++);
1421 }
1391 1422
1392 /* Is this element a possible completion? */ 1423 /* Is this element a possible completion? */
1393 1424
@@ -1432,7 +1463,10 @@ are ignored unless STRING itself starts with a space. */)
1432 else 1463 else
1433 { 1464 {
1434 GCPRO4 (tail, eltstring, allmatches, string); 1465 GCPRO4 (tail, eltstring, allmatches, string);
1435 tem = call1 (predicate, elt); 1466 tem = type == 3
1467 ? call2 (predicate, elt,
1468 HASH_VALUE (XHASH_TABLE (alist), index - 1))
1469 : call1 (predicate, elt);
1436 UNGCPRO; 1470 UNGCPRO;
1437 } 1471 }
1438 if (NILP (tem)) continue; 1472 if (NILP (tem)) continue;
@@ -1564,6 +1598,7 @@ the values STRING, PREDICATE and `lambda'. */)
1564 Lisp_Object string, alist, predicate; 1598 Lisp_Object string, alist, predicate;
1565{ 1599{
1566 Lisp_Object regexps, tem = Qnil; 1600 Lisp_Object regexps, tem = Qnil;
1601 int i = 0;
1567 1602
1568 CHECK_STRING (string); 1603 CHECK_STRING (string);
1569 1604
@@ -1571,9 +1606,7 @@ the values STRING, PREDICATE and `lambda'. */)
1571 || NILP (alist)) 1606 || NILP (alist))
1572 { 1607 {
1573 tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil); 1608 tem = Fassoc_string (string, alist, completion_ignore_case ? Qt : Qnil);
1574 if (CONSP (tem)) 1609 if NILP (tem)
1575 tem = XCAR (tem);
1576 else
1577 return Qnil; 1610 return Qnil;
1578 } 1611 }
1579 else if (VECTORP (alist)) 1612 else if (VECTORP (alist))
@@ -1598,6 +1631,14 @@ the values STRING, PREDICATE and `lambda'. */)
1598 return Qnil; 1631 return Qnil;
1599 } 1632 }
1600 } 1633 }
1634 else if (HASH_TABLE_P (alist))
1635 {
1636 i = hash_lookup (XHASH_TABLE (alist), string, NULL);
1637 if (i >= 0)
1638 tem = HASH_KEY (XHASH_TABLE (alist), i);
1639 else
1640 return Qnil;
1641 }
1601 else 1642 else
1602 return call3 (alist, string, predicate, Qlambda); 1643 return call3 (alist, string, predicate, Qlambda);
1603 1644
@@ -1613,7 +1654,9 @@ the values STRING, PREDICATE and `lambda'. */)
1613 1654
1614 /* Finally, check the predicate. */ 1655 /* Finally, check the predicate. */
1615 if (!NILP (predicate)) 1656 if (!NILP (predicate))
1616 return call1 (predicate, tem); 1657 return HASH_TABLE_P (alist)
1658 ? call2 (predicate, tem, HASH_VALUE (XHASH_TABLE (alist), i))
1659 : call1 (predicate, tem);
1617 else 1660 else
1618 return Qt; 1661 return Qt;
1619} 1662}