Mercurial > hg > xemacs-beta
comparison src/minibuf.c @ 5634:2014ff433daf
Support hash COLLECTIONs, #'{all,try}-completion{s,}; add #'test-completion
src/ChangeLog addition:
2012-01-01 Aidan Kehoe <kehoea@parhasard.net>
Add #'test-completion, API from GNU.
Accept hash table COLLECTIONs in it and in the other
completion-oriented functions, #'try-completion,
#'all-completions, and those Lisp functions implemented in terms
of them.
* lisp.h: Update the prototype of map_obarray(), making FN
compatible with the FUNCTION argument of elisp_maphash();
* abbrev.c (abbrev_match_mapper):
* abbrev.c (record_symbol):
* doc.c (verify_doc_mapper):
* symbols.c (mapatoms_1):
* symbols.c (apropos_mapper):
Update these mapper functions to reflect the new argument to
map_obarray().
* symbols.c (map_obarray):
Call FN with two arguments, the string name of the symbol, and the
symbol itself, for API (mapper) compatibility with
elisp_maphash().
* minibuf.c (map_completion): New. Map a maphash_function_t across
a non function COLLECTION, as appropriate for #'try-completion and
friends.
* minibuf.c (map_completion_list): New. Map a maphash_function_t
across a pseudo-alist, as appropriate for the completion
functions.
* minibuf.c (ignore_completion_p): PRED needs to be called with
two args if and only if the collection is a hash table. Implement
this.
* minibuf.c (try_completion_mapper): New. The loop body of
#'try-completion, refactored out.
* minibuf.c (Ftry_completion): Use try_completion_mapper(),
map_completion().
* minibuf.c (all_completions_mapper): New. The loop body of
#'all-completions, refactored out.
* minibuf.c (Fall_completions): Use all_completions_mapper(),
map_completion().
* minibuf.c (test_completion_mapper): New. The loop body of
#'test-completion.
* minibuf.c (Ftest_completion): New, API from GNU.
* minibuf.c (syms_of_minibuf): Make Ftest_completion available.
tests/ChangeLog addition:
2012-01-01 Aidan Kehoe <kehoea@parhasard.net>
* automated/completion-tests.el: New.
Test #'try-completion, #'all-completion and #'test-completion with
list, vector and hash-table COLLECTION arguments.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Sun, 01 Jan 2012 15:18:52 +0000 |
parents | 56144c8593a8 |
children | daf5accfe973 |
comparison
equal
deleted
inserted
replaced
5633:49c36ed998b6 | 5634:2014ff433daf |
---|---|
33 #include "events.h" | 33 #include "events.h" |
34 #include "frame-impl.h" | 34 #include "frame-impl.h" |
35 #include "insdel.h" | 35 #include "insdel.h" |
36 #include "redisplay.h" | 36 #include "redisplay.h" |
37 #include "window-impl.h" | 37 #include "window-impl.h" |
38 #include "elhash.h" | |
38 | 39 |
39 /* Depth in minibuffer invocations. */ | 40 /* Depth in minibuffer invocations. */ |
40 int minibuf_level; | 41 int minibuf_level; |
41 | 42 |
42 Lisp_Object Qcompletion_ignore_case; | 43 Lisp_Object Qcompletion_ignore_case; |
242 if (l == 0) | 243 if (l == 0) |
243 return -1; | 244 return -1; |
244 else return len - l; | 245 else return len - l; |
245 } | 246 } |
246 | 247 |
248 /* Map FUNCTION, a C function, across LISZT, a pseudo-alist, calling | |
249 it with three args, ELTSTRING (the car of the element if a cons, | |
250 otherwise the element itself), ELT (the element, always) and | |
251 EXTRA_ARG. Stop if FUNCTION returns non-zero. */ | |
252 static void | |
253 map_completion_list (maphash_function_t function, Lisp_Object liszt, | |
254 void *extra_arg) | |
255 { | |
256 Lisp_Object eltstring; | |
257 | |
258 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt) | |
259 { | |
260 eltstring = CONSP (elt) ? XCAR (elt) : elt; | |
261 if (function (eltstring, elt, extra_arg)) | |
262 { | |
263 XUNGCPRO (elt); | |
264 return; | |
265 } | |
266 } | |
267 END_GC_EXTERNAL_LIST_LOOP (elt); | |
268 } | |
269 | |
270 static void | |
271 map_completion (maphash_function_t function, Lisp_Object collection, | |
272 void *extra_arg, Lisp_Object predicate) | |
273 { | |
274 if (LISTP (collection)) | |
275 { | |
276 map_completion_list (function, collection, extra_arg); | |
277 } | |
278 else if (VECTORP (collection)) | |
279 { | |
280 map_obarray (collection, function, extra_arg); | |
281 } | |
282 else if (NILP (predicate)) | |
283 { | |
284 /* This can't call Lisp, no need to copy and compress the hash | |
285 table entries. */ | |
286 elisp_maphash_unsafe (function, collection, extra_arg); | |
287 } | |
288 else | |
289 { | |
290 elisp_maphash (function, collection, extra_arg); | |
291 } | |
292 } | |
247 | 293 |
248 int | 294 int |
249 regexp_ignore_completion_p (const Ibyte *nonreloc, | 295 regexp_ignore_completion_p (const Ibyte *nonreloc, |
250 Lisp_Object reloc, Bytecount offset, | 296 Lisp_Object reloc, Bytecount offset, |
251 Bytecount length) | 297 Bytecount length) |
262 } | 308 } |
263 } | 309 } |
264 return 0; | 310 return 0; |
265 } | 311 } |
266 | 312 |
267 | |
268 /* Callers should GCPRO, since this may call eval */ | 313 /* Callers should GCPRO, since this may call eval */ |
269 static int | 314 static int |
270 ignore_completion_p (Lisp_Object completion_string, | 315 ignore_completion_p (Lisp_Object completion_string, |
271 Lisp_Object pred, Lisp_Object completion) | 316 Lisp_Object pred, Lisp_Object completion, |
272 { | 317 Boolint hash_tablep) |
318 { | |
319 Lisp_Object tem; | |
320 | |
273 if (regexp_ignore_completion_p (0, completion_string, 0, -1)) | 321 if (regexp_ignore_completion_p (0, completion_string, 0, -1)) |
274 return 1; | 322 return 1; |
275 | 323 |
276 /* Ignore this element if there is a predicate | 324 if (NILP (pred)) |
277 and the predicate doesn't like it. */ | 325 { |
278 if (!NILP (pred)) | 326 return 0; |
279 { | 327 } |
280 Lisp_Object tem; | 328 |
281 if (EQ (pred, Qcommandp)) | 329 /* Ignore this element if there is a predicate and the predicate doesn't |
330 like it. */ | |
331 if (hash_tablep) | |
332 { | |
333 tem = call2 (pred, completion_string, completion); | |
334 } | |
335 else if (EQ (pred, Qcommandp)) | |
336 { | |
282 tem = Fcommandp (completion); | 337 tem = Fcommandp (completion); |
283 else | 338 } |
339 else | |
340 { | |
284 tem = call1 (pred, completion); | 341 tem = call1 (pred, completion); |
285 if (NILP (tem)) | 342 } |
286 return 1; | 343 |
287 } | 344 return NILP (tem); |
345 } | |
346 | |
347 struct try_completion_closure | |
348 { | |
349 Lisp_Object string; | |
350 Charcount slength; | |
351 Lisp_Object predicate; | |
352 Lisp_Object bestmatch; | |
353 Charcount blength; | |
354 Charcount bestmatchsize; | |
355 Boolint hash_tablep; | |
356 int matchcount; | |
357 }; | |
358 | |
359 static int | |
360 try_completion_mapper (Lisp_Object eltstring, Lisp_Object value, | |
361 void *arg) | |
362 { | |
363 struct try_completion_closure *tcc = (struct try_completion_closure *) arg; | |
364 Charcount eltlength; | |
365 | |
366 if (SYMBOLP (eltstring)) | |
367 { | |
368 eltstring = XSYMBOL_NAME (eltstring); | |
369 } | |
370 | |
371 if (!STRINGP (eltstring)) | |
372 { | |
373 return 0; | |
374 } | |
375 | |
376 /* Is this element a possible completion? */ | |
377 eltlength = string_char_length (eltstring); | |
378 if (tcc->slength <= eltlength | |
379 && (0 > scmp (XSTRING_DATA (eltstring), XSTRING_DATA (tcc->string), | |
380 tcc->slength))) | |
381 { | |
382 struct gcpro gcpro1, gcpro2, gcpro3; | |
383 int loser; | |
384 GCPRO3 (tcc->string, eltstring, tcc->bestmatch); | |
385 loser = ignore_completion_p (eltstring, tcc->predicate, value, | |
386 tcc->hash_tablep); | |
387 UNGCPRO; | |
388 if (loser) /* reject this one */ | |
389 { | |
390 return 0; | |
391 } | |
392 | |
393 /* Update computation of how much all possible completions | |
394 match */ | |
395 | |
396 tcc->matchcount++; | |
397 if (NILP (tcc->bestmatch)) | |
398 { | |
399 tcc->bestmatch = eltstring; | |
400 tcc->blength = eltlength; | |
401 tcc->bestmatchsize = eltlength; | |
402 } | |
403 else | |
404 { | |
405 Charcount compare = min (tcc->bestmatchsize, eltlength); | |
406 Charcount matchsize = | |
407 scmp (XSTRING_DATA (tcc->bestmatch), XSTRING_DATA (eltstring), | |
408 compare); | |
409 if (matchsize < 0) | |
410 matchsize = compare; | |
411 if (completion_ignore_case) | |
412 { | |
413 /* If this is an exact match except for case, use it as | |
414 the best match rather than one that is not an exact | |
415 match. This way, we get the case pattern of the | |
416 actual match. */ | |
417 if ((matchsize == eltlength | |
418 && matchsize < tcc->blength) | |
419 || | |
420 /* If there is more than one exact match ignoring | |
421 case, and one of them is exact including case, | |
422 prefer that one. */ | |
423 /* If there is no exact match ignoring case, | |
424 prefer a match that does not change the case of | |
425 the input. */ | |
426 ((matchsize == eltlength) | |
427 == | |
428 (matchsize == tcc->blength) | |
429 && 0 > scmp_1 (XSTRING_DATA (eltstring), | |
430 XSTRING_DATA (tcc->string), | |
431 tcc->slength, 0) | |
432 && 0 <= scmp_1 (XSTRING_DATA (tcc->bestmatch), | |
433 XSTRING_DATA (tcc->string), | |
434 tcc->slength, 0))) | |
435 { | |
436 tcc->bestmatch = eltstring; | |
437 tcc->blength = eltlength; | |
438 } | |
439 } | |
440 tcc->bestmatchsize = matchsize; | |
441 } | |
442 } | |
443 | |
288 return 0; | 444 return 0; |
289 } | 445 } |
290 | |
291 | |
292 /* #### Maybe we should allow COLLECTION to be a hash table. | |
293 It is wrong for the use of obarrays to be better-rewarded than the | |
294 use of hash tables. By better-rewarded I mean that you can pass an | |
295 obarray to all of the completion functions, whereas you can't do | |
296 anything like that with a hash table. | |
297 | |
298 To do so, there should probably be a | |
299 map_obarray_or_alist_or_hash_table function which would be used by | |
300 both Ftry_completion and Fall_completions. [[ But would the | |
301 additional funcalls slow things down? ]] Seriously doubtful. --ben */ | |
302 | 446 |
303 DEFUN ("try-completion", Ftry_completion, 2, 3, 0, /* | 447 DEFUN ("try-completion", Ftry_completion, 2, 3, 0, /* |
304 Return common substring of all completions of STRING in COLLECTION. | 448 Return common substring of all completions of STRING in COLLECTION. |
305 COLLECTION must be an alist, an obarray, or a function. | 449 COLLECTION must be a list, a hash table, an obarray, or a function. |
306 Each string in COLLECTION is tested to see if it begins with STRING. | 450 |
307 All that match are compared together; the longest initial sequence | 451 Each string (or symbol) in COLLECTION is tested to see if it (or its |
308 common to all matches is returned as a string. If there is no match | 452 name) begins with STRING. All that match are compared together; the |
309 at all, nil is returned. For an exact match, t is returned. | 453 longest initial sequence common to all matches is returned as a |
310 | 454 string. If there is no match at all, nil is returned. For an exact |
311 If COLLECTION is list, the elements of the list that are not cons | 455 match, t is returned. |
456 | |
457 If COLLECTION is a list, the elements of the list that are not cons | |
312 cells and the cars of the elements of the list that are cons cells | 458 cells and the cars of the elements of the list that are cons cells |
313 (which must be strings) form the set of possible completions. | 459 \(which must be strings or symbols) form the set of possible |
460 completions. | |
461 | |
462 If COLLECTION is a hash table, all the keys that are strings or symbols | |
463 are the possible completions. | |
314 | 464 |
315 If COLLECTION is an obarray, the names of all symbols in the obarray | 465 If COLLECTION is an obarray, the names of all symbols in the obarray |
316 are the possible completions. | 466 are the possible completions. |
317 | 467 |
318 If COLLECTION is a function, it is called with three arguments: the | 468 If COLLECTION is a function, it is called with three arguments: the |
320 value of `try-completion'. | 470 value of `try-completion'. |
321 | 471 |
322 If optional third argument PREDICATE is non-nil, it is used to test | 472 If optional third argument PREDICATE is non-nil, it is used to test |
323 each possible match. The match is a candidate only if PREDICATE | 473 each possible match. The match is a candidate only if PREDICATE |
324 returns non-nil. The argument given to PREDICATE is the alist element | 474 returns non-nil. The argument given to PREDICATE is the alist element |
325 or the symbol from the obarray. | 475 or the symbol from the obarray. If COLLECTION is a hash table, |
476 PREDICATE is passed two arguments, the key and the value of the hash | |
477 table entry. | |
326 */ | 478 */ |
327 (string, collection, predicate)) | 479 (string, collection, predicate)) |
328 { | 480 { |
329 /* This function can GC */ | 481 /* This function can GC */ |
330 Lisp_Object bestmatch, tail; | 482 struct try_completion_closure tcc; |
331 Charcount bestmatchsize = 0; | |
332 int list; | |
333 int indice = 0; | |
334 int matchcount = 0; | |
335 int obsize; | |
336 Lisp_Object bucket; | |
337 Charcount slength, blength; | |
338 | 483 |
339 CHECK_STRING (string); | 484 CHECK_STRING (string); |
340 | 485 |
341 if (CONSP (collection)) | 486 if (!NILP (Ffunctionp (collection))) |
342 { | 487 { |
343 Lisp_Object tem = XCAR (collection); | 488 return call3 (collection, string, predicate, Qnil); |
344 if (SYMBOLP (tem)) /* lambda, autoload, etc. Emacs-lisp sucks */ | 489 } |
345 return call3 (collection, string, predicate, Qnil); | 490 |
346 else | 491 if (!(LISTP (collection) || VECTORP (collection) || HASH_TABLEP (collection))) |
347 list = 1; | 492 { |
348 } | 493 signal_error (Qwrong_type_argument, |
349 else if (VECTORP (collection)) | 494 "must be a list, vector, hash table or function", |
350 list = 0; | 495 collection); |
351 else if (NILP (collection)) | 496 } |
352 list = 1; | 497 |
353 else | 498 tcc.string = string; |
354 return call3 (collection, string, predicate, Qnil); | 499 tcc.slength = string_char_length (string); |
355 | 500 tcc.bestmatch = Qnil; |
356 bestmatch = Qnil; | 501 tcc.blength = 0; |
357 blength = 0; | 502 tcc.bestmatchsize = 0; |
358 slength = string_char_length (string); | 503 tcc.predicate = predicate; |
359 | 504 tcc.hash_tablep = HASH_TABLEP (collection); |
360 /* If COLLECTION is not a list, set TAIL just for gc pro. */ | 505 tcc.matchcount = 0; |
361 tail = collection; | 506 |
362 if (!list) | 507 map_completion (try_completion_mapper, collection, &tcc, predicate); |
363 { | 508 |
364 obsize = XVECTOR_LENGTH (collection); | 509 if (NILP (tcc.bestmatch)) |
365 bucket = XVECTOR_DATA (collection)[indice]; | |
366 } | |
367 else /* warning suppression */ | |
368 { | |
369 obsize = 0; | |
370 bucket = Qnil; | |
371 } | |
372 | |
373 while (1) | |
374 { | |
375 /* Get the next element of the alist or obarray. */ | |
376 /* Exit the loop if the elements are all used up. */ | |
377 /* elt gets the alist element or symbol. | |
378 eltstring gets the name to check as a completion. */ | |
379 Lisp_Object elt; | |
380 Lisp_Object eltstring; | |
381 | |
382 if (list) | |
383 { | |
384 if (NILP (tail)) | |
385 break; | |
386 elt = Fcar (tail); | |
387 if (CONSP (elt)) | |
388 eltstring = Fcar (elt); | |
389 else | |
390 eltstring = elt; | |
391 tail = Fcdr (tail); | |
392 } | |
393 else | |
394 { | |
395 if (!ZEROP (bucket)) | |
396 { | |
397 Lisp_Symbol *next; | |
398 if (!SYMBOLP (bucket)) | |
399 { | |
400 invalid_argument ("Bad obarray passed to try-completions", | |
401 bucket); | |
402 } | |
403 next = symbol_next (XSYMBOL (bucket)); | |
404 elt = bucket; | |
405 eltstring = Fsymbol_name (elt); | |
406 if (next) | |
407 bucket = wrap_symbol (next); | |
408 else | |
409 bucket = Qzero; | |
410 } | |
411 else if (++indice >= obsize) | |
412 break; | |
413 else | |
414 { | |
415 bucket = XVECTOR_DATA (collection)[indice]; | |
416 continue; | |
417 } | |
418 } | |
419 | |
420 /* Is this element a possible completion? */ | |
421 | |
422 if (STRINGP (eltstring)) | |
423 { | |
424 Charcount eltlength = string_char_length (eltstring); | |
425 if (slength <= eltlength | |
426 && (0 > scmp (XSTRING_DATA (eltstring), | |
427 XSTRING_DATA (string), | |
428 slength))) | |
429 { | |
430 { | |
431 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
432 int loser; | |
433 GCPRO4 (tail, string, eltstring, bestmatch); | |
434 loser = ignore_completion_p (eltstring, predicate, elt); | |
435 UNGCPRO; | |
436 if (loser) /* reject this one */ | |
437 continue; | |
438 } | |
439 | |
440 /* Update computation of how much all possible | |
441 completions match */ | |
442 | |
443 matchcount++; | |
444 if (NILP (bestmatch)) | |
445 { | |
446 bestmatch = eltstring; | |
447 blength = eltlength; | |
448 bestmatchsize = eltlength; | |
449 } | |
450 else | |
451 { | |
452 Charcount compare = min (bestmatchsize, eltlength); | |
453 Charcount matchsize = | |
454 scmp (XSTRING_DATA (bestmatch), | |
455 XSTRING_DATA (eltstring), | |
456 compare); | |
457 if (matchsize < 0) | |
458 matchsize = compare; | |
459 if (completion_ignore_case) | |
460 { | |
461 /* If this is an exact match except for case, | |
462 use it as the best match rather than one that is not | |
463 an exact match. This way, we get the case pattern | |
464 of the actual match. */ | |
465 if ((matchsize == eltlength | |
466 && matchsize < blength) | |
467 || | |
468 /* If there is more than one exact match ignoring | |
469 case, and one of them is exact including case, | |
470 prefer that one. */ | |
471 /* If there is no exact match ignoring case, | |
472 prefer a match that does not change the case | |
473 of the input. */ | |
474 ((matchsize == eltlength) | |
475 == | |
476 (matchsize == blength) | |
477 && 0 > scmp_1 (XSTRING_DATA (eltstring), | |
478 XSTRING_DATA (string), | |
479 slength, 0) | |
480 && 0 <= scmp_1 (XSTRING_DATA (bestmatch), | |
481 XSTRING_DATA (string), | |
482 slength, 0))) | |
483 { | |
484 bestmatch = eltstring; | |
485 blength = eltlength; | |
486 } | |
487 } | |
488 bestmatchsize = matchsize; | |
489 } | |
490 } | |
491 } | |
492 } | |
493 | |
494 if (NILP (bestmatch)) | |
495 return Qnil; /* No completions found */ | 510 return Qnil; /* No completions found */ |
496 /* If we are ignoring case, and there is no exact match, | 511 |
497 and no additional text was supplied, | 512 /* If we are ignoring case, and there is no exact match, and no |
498 don't change the case of what the user typed. */ | 513 additional text was supplied, don't change the case of what the |
499 if (completion_ignore_case | 514 user typed. */ |
500 && bestmatchsize == slength | 515 if (completion_ignore_case && tcc.bestmatchsize == tcc.slength |
501 && blength > bestmatchsize) | 516 && tcc.blength > tcc.bestmatchsize) |
502 return string; | 517 return string; |
503 | 518 |
504 /* Return t if the supplied string is an exact match (counting case); | 519 /* Return t if the supplied string is an exact match (counting |
505 it does not require any change to be made. */ | 520 case); it does not require any change to be made. */ |
506 if (matchcount == 1 | 521 if (tcc.matchcount == 1 && tcc.bestmatchsize == tcc.slength |
507 && bestmatchsize == slength | 522 && 0 > scmp_1 (XSTRING_DATA (tcc.bestmatch), XSTRING_DATA (tcc.string), |
508 && 0 > scmp_1 (XSTRING_DATA (bestmatch), | 523 tcc.bestmatchsize, 0)) |
509 XSTRING_DATA (string), | |
510 bestmatchsize, 0)) | |
511 return Qt; | 524 return Qt; |
512 | 525 |
513 /* Else extract the part in which all completions agree */ | 526 /* Else extract the part in which all completions agree */ |
514 return Fsubseq (bestmatch, Qzero, make_fixnum (bestmatchsize)); | 527 return Fsubseq (tcc.bestmatch, Qzero, make_fixnum (tcc.bestmatchsize)); |
515 } | 528 } |
516 | |
517 | 529 |
530 struct all_completions_closure | |
531 { | |
532 Lisp_Object string; | |
533 Charcount slength; | |
534 Lisp_Object predicate; | |
535 Lisp_Object allmatches; | |
536 Boolint hash_tablep; | |
537 }; | |
538 | |
539 static int | |
540 all_completions_mapper (Lisp_Object eltstring, Lisp_Object value, void *arg) | |
541 { | |
542 struct all_completions_closure *acc = (struct all_completions_closure *) arg; | |
543 /* Is this element a possible completion? */ | |
544 | |
545 if (SYMBOLP (eltstring)) | |
546 { | |
547 eltstring = XSYMBOL_NAME (eltstring); | |
548 } | |
549 | |
550 if (STRINGP (eltstring) && (acc->slength <= string_char_length (eltstring)) | |
551 /* Reject alternatives that start with space unless the input | |
552 starts with space. */ | |
553 && ((acc->slength > 0 && string_ichar (acc->string, 0) == ' ') | |
554 || string_ichar (eltstring, 0) != ' ') | |
555 && (0 > scmp (XSTRING_DATA (eltstring), XSTRING_DATA (acc->string), | |
556 acc->slength))) | |
557 { | |
558 /* Yes. Now check whether predicate likes it. */ | |
559 struct gcpro gcpro1, gcpro2; | |
560 int loser; | |
561 GCPRO2 (eltstring, acc->string); | |
562 loser = ignore_completion_p (eltstring, acc->predicate, value, | |
563 acc->hash_tablep); | |
564 UNGCPRO; | |
565 if (!loser) | |
566 { | |
567 /* Ok => put it on the list. */ | |
568 XSETCDR (acc->allmatches, Fcons (eltstring, Qnil)); | |
569 acc->allmatches = XCDR (acc->allmatches); | |
570 } | |
571 } | |
572 | |
573 return 0; | |
574 } | |
575 | |
518 DEFUN ("all-completions", Fall_completions, 2, 3, 0, /* | 576 DEFUN ("all-completions", Fall_completions, 2, 3, 0, /* |
519 Search for partial matches to STRING in COLLECTION. | 577 Search for partial matches to STRING in COLLECTION. |
520 COLLECTION must be an alist, an obarray, or a function. | 578 COLLECTION must be an list, a hash table, an obarray, or a function. |
521 Each string in COLLECTION is tested to see if it begins with STRING. | 579 |
522 The value is a list of all the strings from COLLECTION that match. | 580 Each string (or symbol) in COLLECTION is tested to see if it (or its |
523 | 581 name) begins with STRING. The value is a list of all the strings from |
524 If COLLECTION is an alist, the cars of the elements of the alist | 582 COLLECTION that match. |
525 \(which must be strings) form the set of possible completions. | 583 |
584 If COLLECTION is a list, the elements of the list that are not cons | |
585 cells and the cars of the elements of the list that are cons cells | |
586 \(which must be strings or symbols) form the set of possible | |
587 completions. | |
588 | |
589 If COLLECTION is a hash-table, all the keys that are strings or symbols | |
590 are the possible completions. | |
526 | 591 |
527 If COLLECTION is an obarray, the names of all symbols in the obarray | 592 If COLLECTION is an obarray, the names of all symbols in the obarray |
528 are the possible completions. | 593 are the possible completions. |
529 | 594 |
530 If COLLECTION is a function, it is called with three arguments: the | 595 If COLLECTION is a function, it is called with three arguments: the |
532 value of `all-completions'. | 597 value of `all-completions'. |
533 | 598 |
534 If optional third argument PREDICATE is non-nil, it is used to test | 599 If optional third argument PREDICATE is non-nil, it is used to test |
535 each possible match. The match is a candidate only if PREDICATE | 600 each possible match. The match is a candidate only if PREDICATE |
536 returns non-nil. The argument given to PREDICATE is the alist element | 601 returns non-nil. The argument given to PREDICATE is the alist element |
537 or the symbol from the obarray. | 602 or the symbol from the obarray. If COLLECTION is a hash table, |
603 PREDICATE is passed two arguments, the key and the value of the hash | |
604 table entry. | |
538 */ | 605 */ |
539 (string, collection, predicate)) | 606 (string, collection, predicate)) |
540 { | 607 { |
541 /* This function can GC */ | 608 /* This function can GC */ |
542 Lisp_Object tail; | 609 struct all_completions_closure acc; |
543 Lisp_Object allmatches; | 610 Lisp_Object allmatches = noseeum_cons (Qnil, Qnil); |
544 int list; | 611 struct gcpro gcpro1; |
545 int indice = 0; | |
546 int obsize; | |
547 Lisp_Object bucket; | |
548 Charcount slength; | |
549 | 612 |
550 CHECK_STRING (string); | 613 CHECK_STRING (string); |
551 | 614 |
552 if (CONSP (collection)) | 615 if (!NILP (Ffunctionp (collection))) |
553 { | 616 { |
554 Lisp_Object tem = XCAR (collection); | 617 return call3 (collection, string, predicate, Qt); |
555 if (SYMBOLP (tem)) /* lambda, autoload, etc. Emacs-lisp sucks */ | 618 } |
556 return call3 (collection, string, predicate, Qt); | 619 |
557 else | 620 if (!(LISTP (collection) || VECTORP (collection) || HASH_TABLEP (collection))) |
558 list = 1; | 621 { |
559 } | 622 signal_error (Qwrong_type_argument, |
560 else if (VECTORP (collection)) | 623 "must be a list, vector, hash table or function", |
561 list = 0; | 624 collection); |
562 else if (NILP (collection)) | 625 } |
563 list = 1; | 626 GCPRO1 (allmatches); |
627 acc.string = string; | |
628 acc.slength = string_char_length (string); | |
629 acc.predicate = predicate; | |
630 acc.allmatches = allmatches; | |
631 acc.hash_tablep = HASH_TABLEP (collection); | |
632 | |
633 map_completion (all_completions_mapper, collection, &acc, predicate); | |
634 | |
635 acc.allmatches = XCDR (allmatches); | |
636 free_cons (allmatches); | |
637 UNGCPRO; | |
638 return acc.allmatches; | |
639 } | |
640 | |
641 struct test_completion_closure | |
642 { | |
643 Lisp_Object string; | |
644 Lisp_Object predicate; | |
645 Lisp_Object result; | |
646 Boolint hash_tablep; | |
647 }; | |
648 | |
649 static int | |
650 test_completion_mapper (Lisp_Object eltstring, Lisp_Object value, void *arg) | |
651 { | |
652 struct test_completion_closure *tcc = (struct test_completion_closure *) arg; | |
653 | |
654 if (SYMBOLP (eltstring)) | |
655 { | |
656 eltstring = XSYMBOL_NAME (eltstring); | |
657 } | |
658 | |
659 if (!STRINGP (eltstring)) | |
660 { | |
661 return 0; | |
662 } | |
663 | |
664 if (completion_ignore_case ? | |
665 0 == qxetextcasecmp (XSTRING_DATA (tcc->string), | |
666 XSTRING_LENGTH (tcc->string), | |
667 XSTRING_DATA (eltstring), | |
668 XSTRING_LENGTH (eltstring)) | |
669 : 0 == qxememcmp4 (XSTRING_DATA (tcc->string), | |
670 XSTRING_LENGTH (tcc->string), | |
671 XSTRING_DATA (eltstring), | |
672 XSTRING_LENGTH (eltstring))) | |
673 { | |
674 struct gcpro gcpro1, gcpro2, gcpro3; | |
675 int loser; | |
676 GCPRO3 (eltstring, tcc->string, tcc->predicate); | |
677 loser = ignore_completion_p (eltstring, tcc->predicate, value, | |
678 tcc->hash_tablep); | |
679 UNGCPRO; | |
680 if (!loser) | |
681 { | |
682 tcc->result = Qt; | |
683 return 1; | |
684 } | |
685 } | |
686 | |
687 return 0; | |
688 } | |
689 | |
690 DEFUN ("test-completion", Ftest_completion, 2, 3, 0, /* | |
691 Return non-nil if STRING is a valid completion in COLLECTION. | |
692 | |
693 COLLECTION must be a list, a hash table, an obarray, or a function. | |
694 | |
695 Each string (or symbol) in COLLECTION is tested to see if it (or its | |
696 name) begins with STRING. The value is a list of all the strings from | |
697 COLLECTION that match. | |
698 | |
699 If COLLECTION is a list, the elements of the list that are not cons | |
700 cells and the cars of the elements of the list that are cons cells | |
701 \(which must be strings or symbols) form the set of possible | |
702 completions. | |
703 | |
704 If COLLECTION is a hash-table, all the keys that are strings or symbols | |
705 are the possible completions. | |
706 | |
707 If COLLECTION is an obarray, the names of all symbols in the obarray | |
708 are the possible completions. | |
709 | |
710 If COLLECTION is a function, it is called with three arguments: the | |
711 values STRING, PREDICATE and the symbol `lambda'. Whatever it returns | |
712 is passed back by `test-completion'. | |
713 | |
714 If optional third argument PREDICATE is non-nil, it is used to test | |
715 for possible matches. The match is a candidate only if PREDICATE | |
716 returns non-nil. The argument given to PREDICATE is the alist element | |
717 or the symbol from the obarray. If COLLECTION is a hash table, | |
718 PREDICATE is passed two arguments, the key and the value of the hash | |
719 table entry. | |
720 */ | |
721 (string, collection, predicate)) | |
722 { | |
723 struct test_completion_closure tcc; | |
724 | |
725 CHECK_STRING (string); | |
726 | |
727 if (!NILP (Ffunctionp (collection))) | |
728 { | |
729 return call3 (collection, string, predicate, Qlambda); | |
730 } | |
731 | |
732 if (!(LISTP (collection) || VECTORP (collection) || HASH_TABLEP (collection))) | |
733 { | |
734 signal_error (Qwrong_type_argument, | |
735 "must be a list, vector, hash table or function", | |
736 collection); | |
737 } | |
738 | |
739 tcc.string = string; | |
740 tcc.predicate = predicate; | |
741 tcc.result = Qnil; | |
742 tcc.hash_tablep = HASH_TABLEP (collection); | |
743 | |
744 if (VECTORP (collection) && !completion_ignore_case) | |
745 { | |
746 /* We're case sensitive -> no need for a linear search. */ | |
747 Lisp_Object lookup = Fintern_soft (string, collection, Qzero); | |
748 | |
749 if (ZEROP (lookup)) | |
750 { | |
751 return Qnil; | |
752 } | |
753 | |
754 return ignore_completion_p (XSYMBOL_NAME (lookup), tcc.predicate, | |
755 lookup, 0) ? Qnil : Qt; | |
756 | |
757 /* It would be reasonable to do something similar for the hash | |
758 tables, except, both symbol and string keys are vaild | |
759 completions there. So a negative #'gethash for the string | |
760 (with #'equal as the hash table tests) still means you have | |
761 to do the linear search, for any symbols with that string | |
762 name, which hash very differently; returning t is a little | |
763 quicker, but returning nil is just as slow, so our average | |
764 performance barely changes, at the cost of code | |
765 complexity. */ | |
766 } | |
564 else | 767 else |
565 return call3 (collection, string, predicate, Qt); | 768 { |
566 | 769 map_completion (test_completion_mapper, collection, &tcc, predicate); |
567 allmatches = Qnil; | 770 } |
568 slength = string_char_length (string); | 771 |
569 | 772 return tcc.result; |
570 /* If COLLECTION is not a list, set TAIL just for gc pro. */ | 773 } |
571 tail = collection; | 774 |
572 if (!list) | |
573 { | |
574 obsize = XVECTOR_LENGTH (collection); | |
575 bucket = XVECTOR_DATA (collection)[indice]; | |
576 } | |
577 else /* warning suppression */ | |
578 { | |
579 obsize = 0; | |
580 bucket = Qnil; | |
581 } | |
582 | |
583 while (1) | |
584 { | |
585 /* Get the next element of the alist or obarray. */ | |
586 /* Exit the loop if the elements are all used up. */ | |
587 /* elt gets the alist element or symbol. | |
588 eltstring gets the name to check as a completion. */ | |
589 Lisp_Object elt; | |
590 Lisp_Object eltstring; | |
591 | |
592 if (list) | |
593 { | |
594 if (NILP (tail)) | |
595 break; | |
596 elt = Fcar (tail); | |
597 eltstring = Fcar (elt); | |
598 tail = Fcdr (tail); | |
599 } | |
600 else | |
601 { | |
602 if (!ZEROP (bucket)) | |
603 { | |
604 Lisp_Symbol *next = symbol_next (XSYMBOL (bucket)); | |
605 elt = bucket; | |
606 eltstring = Fsymbol_name (elt); | |
607 if (next) | |
608 bucket = wrap_symbol (next); | |
609 else | |
610 bucket = Qzero; | |
611 } | |
612 else if (++indice >= obsize) | |
613 break; | |
614 else | |
615 { | |
616 bucket = XVECTOR_DATA (collection)[indice]; | |
617 continue; | |
618 } | |
619 } | |
620 | |
621 /* Is this element a possible completion? */ | |
622 | |
623 if (STRINGP (eltstring) | |
624 && (slength <= string_char_length (eltstring)) | |
625 /* Reject alternatives that start with space | |
626 unless the input starts with space. */ | |
627 && ((string_char_length (string) > 0 && | |
628 string_ichar (string, 0) == ' ') | |
629 || string_ichar (eltstring, 0) != ' ') | |
630 && (0 > scmp (XSTRING_DATA (eltstring), | |
631 XSTRING_DATA (string), | |
632 slength))) | |
633 { | |
634 /* Yes. Now check whether predicate likes it. */ | |
635 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
636 int loser; | |
637 GCPRO4 (tail, eltstring, allmatches, string); | |
638 loser = ignore_completion_p (eltstring, predicate, elt); | |
639 UNGCPRO; | |
640 if (!loser) | |
641 /* Ok => put it on the list. */ | |
642 allmatches = Fcons (eltstring, allmatches); | |
643 } | |
644 } | |
645 | |
646 return Fnreverse (allmatches); | |
647 } | |
648 | 775 |
649 /* Useless FSFmacs functions */ | 776 /* Useless FSFmacs functions */ |
650 /* More than useless. I've nuked minibuf_prompt_width so they won't | 777 /* More than useless. I've nuked minibuf_prompt_width so they won't |
651 function at all in XEmacs at the moment. They are used to | 778 function at all in XEmacs at the moment. They are used to |
652 implement some braindamage in FSF which we aren't including. --cet */ | 779 implement some braindamage in FSF which we aren't including. --cet */ |
937 DEFSUBR (Fset_minibuffer_preprompt); | 1064 DEFSUBR (Fset_minibuffer_preprompt); |
938 DEFSUBR (Fread_minibuffer_internal); | 1065 DEFSUBR (Fread_minibuffer_internal); |
939 | 1066 |
940 DEFSUBR (Ftry_completion); | 1067 DEFSUBR (Ftry_completion); |
941 DEFSUBR (Fall_completions); | 1068 DEFSUBR (Fall_completions); |
1069 DEFSUBR (Ftest_completion); | |
942 | 1070 |
943 DEFSYMBOL (Qappend_message); | 1071 DEFSYMBOL (Qappend_message); |
944 DEFSYMBOL (Qclear_message); | 1072 DEFSYMBOL (Qclear_message); |
945 DEFSYMBOL (Qdisplay_message); | 1073 DEFSYMBOL (Qdisplay_message); |
946 DEFSYMBOL (Qcurrent_message_label); | 1074 DEFSYMBOL (Qcurrent_message_label); |