comparison src/dired.c @ 94890:907ac6ecef89

(file_name_completion): Tweak the code so as to always do it in a single pass. Tighten the scope of some variables.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Tue, 13 May 2008 05:16:43 +0000
parents 77013c501e34
children 8971ddf55736
comparison
equal deleted inserted replaced
94889:e80a3956601b 94890:907ac6ecef89
464 Lisp_Object file, dirname; 464 Lisp_Object file, dirname;
465 int all_flag, ver_flag; 465 int all_flag, ver_flag;
466 Lisp_Object predicate; 466 Lisp_Object predicate;
467 { 467 {
468 DIR *d; 468 DIR *d;
469 int bestmatchsize = 0, skip; 469 int bestmatchsize = 0;
470 register int compare, matchsize;
471 int matchcount = 0; 470 int matchcount = 0;
472 /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded. 471 /* If ALL_FLAG is 1, BESTMATCH is the list of all matches, decoded.
473 If ALL_FLAG is 0, BESTMATCH is either nil 472 If ALL_FLAG is 0, BESTMATCH is either nil
474 or the best match so far, not decoded. */ 473 or the best match so far, not decoded. */
475 Lisp_Object bestmatch, tem, elt, name; 474 Lisp_Object bestmatch, tem, elt, name;
476 Lisp_Object encoded_file; 475 Lisp_Object encoded_file;
477 Lisp_Object encoded_dir; 476 Lisp_Object encoded_dir;
478 struct stat st; 477 struct stat st;
479 int directoryp; 478 int directoryp;
480 int passcount; 479 /* If includeall is zero, exclude files in completion-ignored-extensions as
480 well as "." and "..". Until shown otherwise, assume we can't exclude
481 anything. */
482 int includeall = 1;
481 int count = SPECPDL_INDEX (); 483 int count = SPECPDL_INDEX ();
482 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 484 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
483 485
484 elt = Qnil; 486 elt = Qnil;
485 487
516 on the encoded file name. */ 518 on the encoded file name. */
517 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file; 519 encoded_file = STRING_MULTIBYTE (file) ? ENCODE_FILE (file) : file;
518 520
519 encoded_dir = ENCODE_FILE (dirname); 521 encoded_dir = ENCODE_FILE (dirname);
520 522
521 /* With passcount = 0, ignore files that end in an ignored extension. 523 BLOCK_INPUT;
522 If nothing found then try again with passcount = 1, don't ignore them. 524 d = opendir (SDATA (Fdirectory_file_name (encoded_dir)));
523 If looking for all completions, start with passcount = 1, 525 UNBLOCK_INPUT;
524 so always take even the ignored ones. 526 if (!d)
525 527 report_file_error ("Opening directory", Fcons (dirname, Qnil));
526 ** It would not actually be helpful to the user to ignore any possible 528
527 completions when making a list of them.** */ 529 record_unwind_protect (directory_files_internal_unwind,
528 530 make_save_value (d, 0));
529 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++) 531
532 /* Loop reading blocks */
533 /* (att3b compiler bug requires do a null comparison this way) */
534 while (1)
530 { 535 {
531 int inner_count = SPECPDL_INDEX (); 536 DIRENTRY *dp;
532 537 int len;
533 BLOCK_INPUT; 538 int canexclude = 0;
534 d = opendir (SDATA (Fdirectory_file_name (encoded_dir)));
535 UNBLOCK_INPUT;
536 if (!d)
537 report_file_error ("Opening directory", Fcons (dirname, Qnil));
538
539 record_unwind_protect (directory_files_internal_unwind,
540 make_save_value (d, 0));
541
542 /* Loop reading blocks */
543 /* (att3b compiler bug requires do a null comparison this way) */
544 while (1)
545 {
546 DIRENTRY *dp;
547 int len;
548 539
549 #ifdef VMS 540 #ifdef VMS
550 dp = (*readfunc) (d); 541 dp = (*readfunc) (d);
551 #else 542 #else
552 errno = 0; 543 errno = 0;
553 dp = readdir (d); 544 dp = readdir (d);
554 if (dp == NULL && (0 545 if (dp == NULL && (0
555 # ifdef EAGAIN 546 # ifdef EAGAIN
556 || errno == EAGAIN 547 || errno == EAGAIN
557 # endif 548 # endif
558 # ifdef EINTR 549 # ifdef EINTR
559 || errno == EINTR 550 || errno == EINTR
560 # endif 551 # endif
561 )) 552 ))
562 { QUIT; continue; } 553 { QUIT; continue; }
563 #endif 554 #endif
564 555
565 if (!dp) break; 556 if (!dp) break;
566 557
567 len = NAMLEN (dp); 558 len = NAMLEN (dp);
568 559
569 QUIT; 560 QUIT;
570 if (! DIRENTRY_NONEMPTY (dp) 561 if (! DIRENTRY_NONEMPTY (dp)
571 || len < SCHARS (encoded_file) 562 || len < SCHARS (encoded_file)
572 || 0 <= scmp (dp->d_name, SDATA (encoded_file), 563 || 0 <= scmp (dp->d_name, SDATA (encoded_file),
573 SCHARS (encoded_file))) 564 SCHARS (encoded_file)))
574 continue; 565 continue;
575 566
576 if (file_name_completion_stat (encoded_dir, dp, &st) < 0) 567 if (file_name_completion_stat (encoded_dir, dp, &st) < 0)
577 continue; 568 continue;
578 569
579 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR); 570 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
580 tem = Qnil; 571 tem = Qnil;
581 if (directoryp) 572 /* If all_flag is set, always include all.
573 It would not actually be helpful to the user to ignore any possible
574 completions when making a list of them. */
575 if (!all_flag)
576 {
577 int skip;
578 if (directoryp)
582 { 579 {
583 #ifndef TRIVIAL_DIRECTORY_ENTRY 580 #ifndef TRIVIAL_DIRECTORY_ENTRY
584 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, "..")) 581 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
585 #endif 582 #endif
586 /* "." and ".." are never interesting as completions, and are 583 /* "." and ".." are never interesting as completions, and are
587 actually in the way in a directory with only one file. */ 584 actually in the way in a directory with only one file. */
588 if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name)) 585 if (TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
589 continue; 586 canexclude = 1;
590 if (!passcount && len > SCHARS (encoded_file)) 587 else if (len > SCHARS (encoded_file))
591 /* Ignore directories if they match an element of 588 /* Ignore directories if they match an element of
592 completion-ignored-extensions which ends in a slash. */ 589 completion-ignored-extensions which ends in a slash. */
593 for (tem = Vcompletion_ignored_extensions; 590 for (tem = Vcompletion_ignored_extensions;
594 CONSP (tem); tem = XCDR (tem)) 591 CONSP (tem); tem = XCDR (tem))
595 { 592 {
616 continue; 613 continue;
617 break; 614 break;
618 } 615 }
619 } 616 }
620 else 617 else
621 { 618 {
622 /* Compare extensions-to-be-ignored against end of this file name */ 619 /* Compare extensions-to-be-ignored against end of this file name */
623 /* if name is not an exact match against specified string */ 620 /* if name is not an exact match against specified string */
624 if (!passcount && len > SCHARS (encoded_file)) 621 if (len > SCHARS (encoded_file))
625 /* and exit this for loop if a match is found */ 622 /* and exit this for loop if a match is found */
626 for (tem = Vcompletion_ignored_extensions; 623 for (tem = Vcompletion_ignored_extensions;
627 CONSP (tem); tem = XCDR (tem)) 624 CONSP (tem); tem = XCDR (tem))
628 { 625 {
629 elt = XCAR (tem); 626 elt = XCAR (tem);
642 } 639 }
643 } 640 }
644 641
645 /* If an ignored-extensions match was found, 642 /* If an ignored-extensions match was found,
646 don't process this name as a completion. */ 643 don't process this name as a completion. */
647 if (!passcount && CONSP (tem)) 644 if (CONSP (tem))
645 canexclude = 1;
646
647 if (!includeall && canexclude)
648 /* We're not including all files and this file can be excluded. */
648 continue; 649 continue;
649 650
650 /* FIXME: If we move this `decode' earlier we can eliminate 651 if (includeall && !canexclude)
651 the repeated ENCODE_FILE on Vcompletion_ignored_extensions. */ 652 { /* If we have one non-excludable file, we want to exclude the
652 name = make_unibyte_string (dp->d_name, len); 653 excudable files. */
653 name = DECODE_FILE (name); 654 includeall = 0;
654 655 /* Throw away any previous excludable match found. */
655 if (!passcount) 656 bestmatch = Qnil;
656 { 657 bestmatchsize = 0;
657 Lisp_Object regexps; 658 matchcount = 0;
658 Lisp_Object zero;
659 XSETFASTINT (zero, 0);
660
661 /* Ignore this element if it fails to match all the regexps. */
662 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
663 regexps = XCDR (regexps))
664 if (fast_string_match (XCAR (regexps), name) < 0)
665 break;
666 if (CONSP (regexps))
667 continue;
668 }
669
670 /* This is a possible completion */
671 if (directoryp)
672 /* This completion is a directory; make it end with '/'. */
673 name = Ffile_name_as_directory (name);
674
675 /* Test the predicate, if any. */
676 if (!NILP (predicate))
677 {
678 Lisp_Object val;
679 struct gcpro gcpro1;
680
681 GCPRO1 (name);
682 val = call1 (predicate, name);
683 UNGCPRO;
684
685 if (NILP (val))
686 continue;
687 }
688
689 /* Suitably record this match. */
690
691 matchcount++;
692
693 if (all_flag)
694 bestmatch = Fcons (name, bestmatch);
695 else if (NILP (bestmatch))
696 {
697 bestmatch = name;
698 bestmatchsize = SCHARS (name);
699 }
700 else
701 {
702 Lisp_Object zero = make_number (0);
703 /* FIXME: This is a copy of the code in Ftry_completion. */
704 compare = min (bestmatchsize, SCHARS (name));
705 tem = Fcompare_strings (bestmatch, zero,
706 make_number (compare),
707 name, zero,
708 make_number (compare),
709 completion_ignore_case ? Qt : Qnil);
710 if (EQ (tem, Qt))
711 matchsize = compare;
712 else if (XINT (tem) < 0)
713 matchsize = - XINT (tem) - 1;
714 else
715 matchsize = XINT (tem) - 1;
716
717 if (completion_ignore_case)
718 {
719 /* If this is an exact match except for case,
720 use it as the best match rather than one that is not
721 an exact match. This way, we get the case pattern
722 of the actual match. */
723 /* This tests that the current file is an exact match
724 but BESTMATCH is not (it is too long). */
725 if ((matchsize == SCHARS (name)
726 && matchsize + !!directoryp
727 < SCHARS (bestmatch))
728 ||
729 /* If there is no exact match ignoring case,
730 prefer a match that does not change the case
731 of the input. */
732 /* If there is more than one exact match aside from
733 case, and one of them is exact including case,
734 prefer that one. */
735 /* This == checks that, of current file and BESTMATCH,
736 either both or neither are exact. */
737 (((matchsize == SCHARS (name))
738 ==
739 (matchsize + !!directoryp == SCHARS (bestmatch)))
740 && (tem = Fcompare_strings (name, zero,
741 make_number (SCHARS (file)),
742 file, zero,
743 Qnil,
744 Qnil),
745 EQ (Qt, tem))
746 && (tem = Fcompare_strings (bestmatch, zero,
747 make_number (SCHARS (file)),
748 file, zero,
749 Qnil,
750 Qnil),
751 ! EQ (Qt, tem))))
752 bestmatch = name;
753 }
754 bestmatchsize = matchsize;
755 } 659 }
756 } 660 }
757 /* This closes the directory. */ 661 /* FIXME: If we move this `decode' earlier we can eliminate
758 bestmatch = unbind_to (inner_count, bestmatch); 662 the repeated ENCODE_FILE on Vcompletion_ignored_extensions. */
663 name = make_unibyte_string (dp->d_name, len);
664 name = DECODE_FILE (name);
665
666 {
667 Lisp_Object regexps;
668 Lisp_Object zero;
669 XSETFASTINT (zero, 0);
670
671 /* Ignore this element if it fails to match all the regexps. */
672 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
673 regexps = XCDR (regexps))
674 if (fast_string_match (XCAR (regexps), name) < 0)
675 break;
676 if (CONSP (regexps))
677 continue;
678 }
679
680 /* This is a possible completion */
681 if (directoryp)
682 /* This completion is a directory; make it end with '/'. */
683 name = Ffile_name_as_directory (name);
684
685 /* Test the predicate, if any. */
686 if (!NILP (predicate))
687 {
688 Lisp_Object val;
689 struct gcpro gcpro1;
690
691 GCPRO1 (name);
692 val = call1 (predicate, name);
693 UNGCPRO;
694
695 if (NILP (val))
696 continue;
697 }
698
699 /* Suitably record this match. */
700
701 matchcount++;
702
703 if (all_flag)
704 bestmatch = Fcons (name, bestmatch);
705 else if (NILP (bestmatch))
706 {
707 bestmatch = name;
708 bestmatchsize = SCHARS (name);
709 }
710 else
711 {
712 Lisp_Object zero = make_number (0);
713 /* FIXME: This is a copy of the code in Ftry_completion. */
714 int compare = min (bestmatchsize, SCHARS (name));
715 Lisp_Object tem
716 = Fcompare_strings (bestmatch, zero,
717 make_number (compare),
718 name, zero,
719 make_number (compare),
720 completion_ignore_case ? Qt : Qnil);
721 int matchsize
722 = (EQ (tem, Qt) ? compare
723 : XINT (tem) < 0 ? - XINT (tem) - 1
724 : XINT (tem) - 1);
725
726 if (completion_ignore_case)
727 {
728 /* If this is an exact match except for case,
729 use it as the best match rather than one that is not
730 an exact match. This way, we get the case pattern
731 of the actual match. */
732 /* This tests that the current file is an exact match
733 but BESTMATCH is not (it is too long). */
734 if ((matchsize == SCHARS (name)
735 && matchsize + !!directoryp
736 < SCHARS (bestmatch))
737 ||
738 /* If there is no exact match ignoring case,
739 prefer a match that does not change the case
740 of the input. */
741 /* If there is more than one exact match aside from
742 case, and one of them is exact including case,
743 prefer that one. */
744 /* This == checks that, of current file and BESTMATCH,
745 either both or neither are exact. */
746 (((matchsize == SCHARS (name))
747 ==
748 (matchsize + !!directoryp == SCHARS (bestmatch)))
749 && (tem = Fcompare_strings (name, zero,
750 make_number (SCHARS (file)),
751 file, zero,
752 Qnil,
753 Qnil),
754 EQ (Qt, tem))
755 && (tem = Fcompare_strings (bestmatch, zero,
756 make_number (SCHARS (file)),
757 file, zero,
758 Qnil,
759 Qnil),
760 ! EQ (Qt, tem))))
761 bestmatch = name;
762 }
763 bestmatchsize = matchsize;
764 }
759 } 765 }
760 766
761 UNGCPRO; 767 UNGCPRO;
768 /* This closes the directory. */
762 bestmatch = unbind_to (count, bestmatch); 769 bestmatch = unbind_to (count, bestmatch);
763 770
764 if (all_flag || NILP (bestmatch)) 771 if (all_flag || NILP (bestmatch))
765 return bestmatch; 772 return bestmatch;
766 if (matchcount == 1 && bestmatchsize == SCHARS (file)) 773 if (matchcount == 1 && bestmatchsize == SCHARS (file))