Comment changes.
[bpt/emacs.git] / src / dired.c
1 /* Lisp functions for making directory listings.
2 Copyright (C) 1985, 1986, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27
28 #ifdef VMS
29 #include <string.h>
30 #include <rms.h>
31 #include <rmsdef.h>
32 #endif
33
34 /* The d_nameln member of a struct dirent includes the '\0' character
35 on some systems, but not on others. What's worse, you can't tell
36 at compile-time which one it will be, since it really depends on
37 the sort of system providing the filesystem you're reading from,
38 not the system you are running on. Paul Eggert
39 <eggert@bi.twinsun.com> says this occurs when Emacs is running on a
40 SunOS 4.1.2 host, reading a directory that is remote-mounted from a
41 Solaris 2.1 host and is in a native Solaris 2.1 filesystem.
42
43 Since applying strlen to the name always works, we'll just do that. */
44 #define NAMLEN(p) strlen (p->d_name)
45
46 #ifdef SYSV_SYSTEM_DIR
47
48 #include <dirent.h>
49 #define DIRENTRY struct dirent
50
51 #else /* not SYSV_SYSTEM_DIR */
52
53 #ifdef NONSYSTEM_DIR_LIBRARY
54 #include "ndir.h"
55 #else /* not NONSYSTEM_DIR_LIBRARY */
56 #ifdef MSDOS
57 #include <dirent.h>
58 #else
59 #include <sys/dir.h>
60 #endif
61 #endif /* not NONSYSTEM_DIR_LIBRARY */
62
63 #ifndef MSDOS
64 #define DIRENTRY struct direct
65
66 extern DIR *opendir ();
67 extern struct direct *readdir ();
68
69 #endif /* not MSDOS */
70 #endif /* not SYSV_SYSTEM_DIR */
71
72 #ifdef MSDOS
73 #define DIRENTRY_NONEMPTY(p) ((p)->d_name[0] != 0)
74 #else
75 #define DIRENTRY_NONEMPTY(p) ((p)->d_ino)
76 #endif
77
78 #include "lisp.h"
79 #include "buffer.h"
80 #include "commands.h"
81
82 #include "regex.h"
83
84 /* Returns a search buffer, with a fastmap allocated and ready to go. */
85 extern struct re_pattern_buffer *compile_pattern ();
86
87 #define min(a, b) ((a) < (b) ? (a) : (b))
88
89 /* if system does not have symbolic links, it does not have lstat.
90 In that case, use ordinary stat instead. */
91
92 #ifndef S_IFLNK
93 #define lstat stat
94 #endif
95
96 extern int completion_ignore_case;
97 extern Lisp_Object Vcompletion_regexp_list;
98
99 Lisp_Object Vcompletion_ignored_extensions;
100 Lisp_Object Qcompletion_ignore_case;
101 Lisp_Object Qdirectory_files;
102 Lisp_Object Qfile_name_completion;
103 Lisp_Object Qfile_name_all_completions;
104 Lisp_Object Qfile_attributes;
105 \f
106 DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
107 "Return a list of names of files in DIRECTORY.\n\
108 There are three optional arguments:\n\
109 If FULL is non-nil, return absolute file names. Otherwise return names\n\
110 that are relative to the specified directory.\n\
111 If MATCH is non-nil, mention only file names that match the regexp MATCH.\n\
112 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.\n\
113 NOSORT is useful if you plan to sort the result yourself.")
114 (directory, full, match, nosort)
115 Lisp_Object directory, full, match, nosort;
116 {
117 DIR *d;
118 int dirnamelen;
119 Lisp_Object list, name, dirfilename;
120 Lisp_Object handler;
121 struct re_pattern_buffer *bufp;
122
123 /* If the file name has special constructs in it,
124 call the corresponding file handler. */
125 handler = Ffind_file_name_handler (directory, Qdirectory_files);
126 if (!NILP (handler))
127 {
128 Lisp_Object args[6];
129
130 args[0] = handler;
131 args[1] = Qdirectory_files;
132 args[2] = directory;
133 args[3] = full;
134 args[4] = match;
135 args[5] = nosort;
136 return Ffuncall (6, args);
137 }
138
139 {
140 struct gcpro gcpro1, gcpro2;
141
142 /* Because of file name handlers, these functions might call
143 Ffuncall, and cause a GC. */
144 GCPRO1 (match);
145 directory = Fexpand_file_name (directory, Qnil);
146 UNGCPRO;
147 GCPRO2 (match, directory);
148 dirfilename = Fdirectory_file_name (directory);
149 UNGCPRO;
150 }
151
152 if (!NILP (match))
153 {
154 CHECK_STRING (match, 3);
155
156 /* MATCH might be a flawed regular expression. Rather than
157 catching and signaling our own errors, we just call
158 compile_pattern to do the work for us. */
159 #ifdef VMS
160 bufp = compile_pattern (match, 0,
161 buffer_defaults.downcase_table->contents, 0);
162 #else
163 bufp = compile_pattern (match, 0, 0, 0);
164 #endif
165 }
166
167 /* Now *bufp is the compiled form of MATCH; don't call anything
168 which might compile a new regexp until we're done with the loop! */
169
170 /* Do this opendir after anything which might signal an error; if
171 an error is signaled while the directory stream is open, we
172 have to make sure it gets closed, and setting up an
173 unwind_protect to do so would be a pain. */
174 d = opendir (XSTRING (dirfilename)->data);
175 if (! d)
176 report_file_error ("Opening directory", Fcons (directory, Qnil));
177
178 list = Qnil;
179 dirnamelen = XSTRING (directory)->size;
180
181 /* Loop reading blocks */
182 while (1)
183 {
184 DIRENTRY *dp = readdir (d);
185 int len;
186
187 if (!dp) break;
188 len = NAMLEN (dp);
189 if (DIRENTRY_NONEMPTY (dp))
190 {
191 if (NILP (match)
192 || (0 <= re_search (bufp, dp->d_name, len, 0, len, 0)))
193 {
194 if (!NILP (full))
195 {
196 int afterdirindex = dirnamelen;
197 int total = len + dirnamelen;
198 int needsep = 0;
199
200 /* Decide whether we need to add a directory separator. */
201 #ifndef VMS
202 if (dirnamelen == 0
203 || !IS_ANY_SEP (XSTRING (directory)->data[dirnamelen - 1]))
204 needsep = 1;
205 #endif /* VMS */
206
207 name = make_uninit_string (total + needsep);
208 bcopy (XSTRING (directory)->data, XSTRING (name)->data,
209 dirnamelen);
210 if (needsep)
211 XSTRING (name)->data[afterdirindex++] = DIRECTORY_SEP;
212 bcopy (dp->d_name,
213 XSTRING (name)->data + afterdirindex, len);
214 }
215 else
216 name = make_string (dp->d_name, len);
217 list = Fcons (name, list);
218 }
219 }
220 }
221 closedir (d);
222 if (!NILP (nosort))
223 return list;
224 return Fsort (Fnreverse (list), Qstring_lessp);
225 }
226 \f
227 Lisp_Object file_name_completion ();
228
229 DEFUN ("file-name-completion", Ffile_name_completion, Sfile_name_completion,
230 2, 2, 0,
231 "Complete file name FILE in directory DIRECTORY.\n\
232 Returns the longest string\n\
233 common to all file names in DIRECTORY that start with FILE.\n\
234 If there is only one and FILE matches it exactly, returns t.\n\
235 Returns nil if DIR contains no name starting with FILE.")
236 (file, directory)
237 Lisp_Object file, directory;
238 {
239 Lisp_Object handler;
240
241 /* If the directory name has special constructs in it,
242 call the corresponding file handler. */
243 handler = Ffind_file_name_handler (directory, Qfile_name_completion);
244 if (!NILP (handler))
245 return call3 (handler, Qfile_name_completion, file, directory);
246
247 /* If the file name has special constructs in it,
248 call the corresponding file handler. */
249 handler = Ffind_file_name_handler (file, Qfile_name_completion);
250 if (!NILP (handler))
251 return call3 (handler, Qfile_name_completion, file, directory);
252
253 return file_name_completion (file, directory, 0, 0);
254 }
255
256 DEFUN ("file-name-all-completions", Ffile_name_all_completions,
257 Sfile_name_all_completions, 2, 2, 0,
258 "Return a list of all completions of file name FILE in directory DIRECTORY.\n\
259 These are all file names in directory DIRECTORY which begin with FILE.")
260 (file, directory)
261 Lisp_Object file, directory;
262 {
263 Lisp_Object handler;
264
265 /* If the directory name has special constructs in it,
266 call the corresponding file handler. */
267 handler = Ffind_file_name_handler (directory, Qfile_name_all_completions);
268 if (!NILP (handler))
269 return call3 (handler, Qfile_name_all_completions, file, directory);
270
271 /* If the file name has special constructs in it,
272 call the corresponding file handler. */
273 handler = Ffind_file_name_handler (file, Qfile_name_all_completions);
274 if (!NILP (handler))
275 return call3 (handler, Qfile_name_all_completions, file, directory);
276
277 return file_name_completion (file, directory, 1, 0);
278 }
279
280 Lisp_Object
281 file_name_completion (file, dirname, all_flag, ver_flag)
282 Lisp_Object file, dirname;
283 int all_flag, ver_flag;
284 {
285 DIR *d;
286 DIRENTRY *dp;
287 int bestmatchsize, skip;
288 register int compare, matchsize;
289 unsigned char *p1, *p2;
290 int matchcount = 0;
291 Lisp_Object bestmatch, tem, elt, name;
292 struct stat st;
293 int directoryp;
294 int passcount;
295 int count = specpdl_ptr - specpdl;
296 struct gcpro gcpro1, gcpro2, gcpro3;
297
298 #ifdef VMS
299 extern DIRENTRY * readdirver ();
300
301 DIRENTRY *((* readfunc) ());
302
303 /* Filename completion on VMS ignores case, since VMS filesys does. */
304 specbind (Qcompletion_ignore_case, Qt);
305
306 readfunc = readdir;
307 if (ver_flag)
308 readfunc = readdirver;
309 file = Fupcase (file);
310 #else /* not VMS */
311 CHECK_STRING (file, 0);
312 #endif /* not VMS */
313
314 #ifdef FILE_SYSTEM_CASE
315 file = FILE_SYSTEM_CASE (file);
316 #endif
317 bestmatch = Qnil;
318 GCPRO3 (file, dirname, bestmatch);
319 dirname = Fexpand_file_name (dirname, Qnil);
320
321 /* With passcount = 0, ignore files that end in an ignored extension.
322 If nothing found then try again with passcount = 1, don't ignore them.
323 If looking for all completions, start with passcount = 1,
324 so always take even the ignored ones.
325
326 ** It would not actually be helpful to the user to ignore any possible
327 completions when making a list of them.** */
328
329 for (passcount = !!all_flag; NILP (bestmatch) && passcount < 2; passcount++)
330 {
331 if (!(d = opendir (XSTRING (Fdirectory_file_name (dirname))->data)))
332 report_file_error ("Opening directory", Fcons (dirname, Qnil));
333
334 /* Loop reading blocks */
335 /* (att3b compiler bug requires do a null comparison this way) */
336 while (1)
337 {
338 DIRENTRY *dp;
339 int len;
340
341 #ifdef VMS
342 dp = (*readfunc) (d);
343 #else
344 dp = readdir (d);
345 #endif
346 if (!dp) break;
347
348 len = NAMLEN (dp);
349
350 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit))
351 goto quit;
352 if (! DIRENTRY_NONEMPTY (dp)
353 || len < XSTRING (file)->size
354 || 0 <= scmp (dp->d_name, XSTRING (file)->data,
355 XSTRING (file)->size))
356 continue;
357
358 if (file_name_completion_stat (dirname, dp, &st) < 0)
359 continue;
360
361 directoryp = ((st.st_mode & S_IFMT) == S_IFDIR);
362 tem = Qnil;
363 if (directoryp)
364 {
365 #ifndef TRIVIAL_DIRECTORY_ENTRY
366 #define TRIVIAL_DIRECTORY_ENTRY(n) (!strcmp (n, ".") || !strcmp (n, ".."))
367 #endif
368 /* "." and ".." are never interesting as completions, but are
369 actually in the way in a directory contains only one file. */
370 if (!passcount && TRIVIAL_DIRECTORY_ENTRY (dp->d_name))
371 continue;
372 }
373 else
374 {
375 /* Compare extensions-to-be-ignored against end of this file name */
376 /* if name is not an exact match against specified string */
377 if (!passcount && len > XSTRING (file)->size)
378 /* and exit this for loop if a match is found */
379 for (tem = Vcompletion_ignored_extensions;
380 CONSP (tem); tem = XCONS (tem)->cdr)
381 {
382 elt = XCONS (tem)->car;
383 if (!STRINGP (elt)) continue;
384 skip = len - XSTRING (elt)->size;
385 if (skip < 0) continue;
386
387 if (0 <= scmp (dp->d_name + skip,
388 XSTRING (elt)->data,
389 XSTRING (elt)->size))
390 continue;
391 break;
392 }
393 }
394
395 /* If an ignored-extensions match was found,
396 don't process this name as a completion. */
397 if (!passcount && CONSP (tem))
398 continue;
399
400 if (!passcount)
401 {
402 Lisp_Object regexps;
403 Lisp_Object zero;
404 XSETFASTINT (zero, 0);
405
406 /* Ignore this element if it fails to match all the regexps. */
407 for (regexps = Vcompletion_regexp_list; CONSP (regexps);
408 regexps = XCONS (regexps)->cdr)
409 {
410 tem = Fstring_match (XCONS (regexps)->car, elt, zero);
411 if (NILP (tem))
412 break;
413 }
414 if (CONSP (regexps))
415 continue;
416 }
417
418 /* Update computation of how much all possible completions match */
419
420 matchcount++;
421
422 if (all_flag || NILP (bestmatch))
423 {
424 /* This is a possible completion */
425 if (directoryp)
426 {
427 /* This completion is a directory; make it end with '/' */
428 name = Ffile_name_as_directory (make_string (dp->d_name, len));
429 }
430 else
431 name = make_string (dp->d_name, len);
432 if (all_flag)
433 {
434 bestmatch = Fcons (name, bestmatch);
435 }
436 else
437 {
438 bestmatch = name;
439 bestmatchsize = XSTRING (name)->size;
440 }
441 }
442 else
443 {
444 compare = min (bestmatchsize, len);
445 p1 = XSTRING (bestmatch)->data;
446 p2 = (unsigned char *) dp->d_name;
447 matchsize = scmp(p1, p2, compare);
448 if (matchsize < 0)
449 matchsize = compare;
450 if (completion_ignore_case)
451 {
452 /* If this is an exact match except for case,
453 use it as the best match rather than one that is not
454 an exact match. This way, we get the case pattern
455 of the actual match. */
456 /* This tests that the current file is an exact match
457 but BESTMATCH is not (it is too long). */
458 if ((matchsize == len
459 && matchsize + !!directoryp
460 < XSTRING (bestmatch)->size)
461 ||
462 /* If there is no exact match ignoring case,
463 prefer a match that does not change the case
464 of the input. */
465 /* If there is more than one exact match aside from
466 case, and one of them is exact including case,
467 prefer that one. */
468 /* This == checks that, of current file and BESTMATCH,
469 either both or neither are exact. */
470 (((matchsize == len)
471 ==
472 (matchsize + !!directoryp
473 == XSTRING (bestmatch)->size))
474 && !bcmp (p2, XSTRING (file)->data, XSTRING (file)->size)
475 && bcmp (p1, XSTRING (file)->data, XSTRING (file)->size)))
476 {
477 bestmatch = make_string (dp->d_name, len);
478 if (directoryp)
479 bestmatch = Ffile_name_as_directory (bestmatch);
480 }
481 }
482
483 /* If this dirname all matches, see if implicit following
484 slash does too. */
485 if (directoryp
486 && compare == matchsize
487 && bestmatchsize > matchsize
488 && IS_ANY_SEP (p1[matchsize]))
489 matchsize++;
490 bestmatchsize = matchsize;
491 }
492 }
493 closedir (d);
494 }
495
496 UNGCPRO;
497 bestmatch = unbind_to (count, bestmatch);
498
499 if (all_flag || NILP (bestmatch))
500 return bestmatch;
501 if (matchcount == 1 && bestmatchsize == XSTRING (file)->size)
502 return Qt;
503 return Fsubstring (bestmatch, make_number (0), make_number (bestmatchsize));
504 quit:
505 if (d) closedir (d);
506 Vquit_flag = Qnil;
507 return Fsignal (Qquit, Qnil);
508 }
509
510 file_name_completion_stat (dirname, dp, st_addr)
511 Lisp_Object dirname;
512 DIRENTRY *dp;
513 struct stat *st_addr;
514 {
515 int len = NAMLEN (dp);
516 int pos = XSTRING (dirname)->size;
517 int value;
518 char *fullname = (char *) alloca (len + pos + 2);
519
520 bcopy (XSTRING (dirname)->data, fullname, pos);
521 #ifndef VMS
522 if (!IS_DIRECTORY_SEP (fullname[pos - 1]))
523 fullname[pos++] = DIRECTORY_SEP;
524 #endif
525
526 bcopy (dp->d_name, fullname + pos, len);
527 fullname[pos + len] = 0;
528
529 #ifdef S_IFLNK
530 /* We want to return success if a link points to a nonexistent file,
531 but we want to return the status for what the link points to,
532 in case it is a directory. */
533 value = lstat (fullname, st_addr);
534 stat (fullname, st_addr);
535 return value;
536 #else
537 return stat (fullname, st_addr);
538 #endif
539 }
540 \f
541 #ifdef VMS
542
543 DEFUN ("file-name-all-versions", Ffile_name_all_versions,
544 Sfile_name_all_versions, 2, 2, 0,
545 "Return a list of all versions of file name FILE in directory DIRECTORY.")
546 (file, directory)
547 Lisp_Object file, directory;
548 {
549 return file_name_completion (file, directory, 1, 1);
550 }
551
552 DEFUN ("file-version-limit", Ffile_version_limit, Sfile_version_limit, 1, 1, 0,
553 "Return the maximum number of versions allowed for FILE.\n\
554 Returns nil if the file cannot be opened or if there is no version limit.")
555 (filename)
556 Lisp_Object filename;
557 {
558 Lisp_Object retval;
559 struct FAB fab;
560 struct RAB rab;
561 struct XABFHC xabfhc;
562 int status;
563
564 filename = Fexpand_file_name (filename, Qnil);
565 fab = cc$rms_fab;
566 xabfhc = cc$rms_xabfhc;
567 fab.fab$l_fna = XSTRING (filename)->data;
568 fab.fab$b_fns = strlen (fab.fab$l_fna);
569 fab.fab$l_xab = (char *) &xabfhc;
570 status = sys$open (&fab, 0, 0);
571 if (status != RMS$_NORMAL) /* Probably non-existent file */
572 return Qnil;
573 sys$close (&fab, 0, 0);
574 if (xabfhc.xab$w_verlimit == 32767)
575 return Qnil; /* No version limit */
576 else
577 return make_number (xabfhc.xab$w_verlimit);
578 }
579
580 #endif /* VMS */
581 \f
582 Lisp_Object
583 make_time (time)
584 int time;
585 {
586 return Fcons (make_number (time >> 16),
587 Fcons (make_number (time & 0177777), Qnil));
588 }
589
590 DEFUN ("file-attributes", Ffile_attributes, Sfile_attributes, 1, 1, 0,
591 "Return a list of attributes of file FILENAME.\n\
592 Value is nil if specified file cannot be opened.\n\
593 Otherwise, list elements are:\n\
594 0. t for directory, string (name linked to) for symbolic link, or nil.\n\
595 1. Number of links to file.\n\
596 2. File uid.\n\
597 3. File gid.\n\
598 4. Last access time, as a list of two integers.\n\
599 First integer has high-order 16 bits of time, second has low 16 bits.\n\
600 5. Last modification time, likewise.\n\
601 6. Last status change time, likewise.\n\
602 7. Size in bytes (-1, if number is out of range).\n\
603 8. File modes, as a string of ten letters or dashes as in ls -l.\n\
604 9. t iff file's gid would change if file were deleted and recreated.\n\
605 10. inode number.\n\
606 11. Device number.\n\
607 \n\
608 If file does not exist, returns nil.")
609 (filename)
610 Lisp_Object filename;
611 {
612 Lisp_Object values[12];
613 Lisp_Object dirname;
614 struct stat s;
615 struct stat sdir;
616 char modes[10];
617 Lisp_Object handler;
618
619 filename = Fexpand_file_name (filename, Qnil);
620
621 /* If the file name has special constructs in it,
622 call the corresponding file handler. */
623 handler = Ffind_file_name_handler (filename, Qfile_attributes);
624 if (!NILP (handler))
625 return call2 (handler, Qfile_attributes, filename);
626
627 if (lstat (XSTRING (filename)->data, &s) < 0)
628 return Qnil;
629
630 switch (s.st_mode & S_IFMT)
631 {
632 default:
633 values[0] = Qnil; break;
634 case S_IFDIR:
635 values[0] = Qt; break;
636 #ifdef S_IFLNK
637 case S_IFLNK:
638 values[0] = Ffile_symlink_p (filename); break;
639 #endif
640 }
641 values[1] = make_number (s.st_nlink);
642 values[2] = make_number (s.st_uid);
643 values[3] = make_number (s.st_gid);
644 values[4] = make_time (s.st_atime);
645 values[5] = make_time (s.st_mtime);
646 values[6] = make_time (s.st_ctime);
647 values[7] = make_number ((int) s.st_size);
648 /* If the size is out of range, give back -1. */
649 if (XINT (values[7]) != s.st_size)
650 XSETINT (values[7], -1);
651 filemodestring (&s, modes);
652 values[8] = make_string (modes, 10);
653 #ifdef BSD4_3 /* Gross kludge to avoid lack of "#if defined(...)" in VMS */
654 #define BSD4_2 /* A new meaning to the term `backwards compatibility' */
655 #endif
656 #ifdef BSD4_2 /* file gid will be dir gid */
657 dirname = Ffile_name_directory (filename);
658 if (! NILP (dirname) && stat (XSTRING (dirname)->data, &sdir) == 0)
659 values[9] = (sdir.st_gid != s.st_gid) ? Qt : Qnil;
660 else /* if we can't tell, assume worst */
661 values[9] = Qt;
662 #else /* file gid will be egid */
663 values[9] = (s.st_gid != getegid ()) ? Qt : Qnil;
664 #endif /* BSD4_2 (or BSD4_3) */
665 #ifdef BSD4_3
666 #undef BSD4_2 /* ok, you can look again without throwing up */
667 #endif
668 values[10] = make_number (s.st_ino);
669 values[11] = make_number (s.st_dev);
670 return Flist (sizeof(values) / sizeof(values[0]), values);
671 }
672 \f
673 syms_of_dired ()
674 {
675 Qdirectory_files = intern ("directory-files");
676 Qfile_name_completion = intern ("file-name-completion");
677 Qfile_name_all_completions = intern ("file-name-all-completions");
678 Qfile_attributes = intern ("file-attributes");
679
680 defsubr (&Sdirectory_files);
681 defsubr (&Sfile_name_completion);
682 #ifdef VMS
683 defsubr (&Sfile_name_all_versions);
684 defsubr (&Sfile_version_limit);
685 #endif /* VMS */
686 defsubr (&Sfile_name_all_completions);
687 defsubr (&Sfile_attributes);
688
689 #ifdef VMS
690 Qcompletion_ignore_case = intern ("completion-ignore-case");
691 staticpro (&Qcompletion_ignore_case);
692 #endif /* VMS */
693
694 DEFVAR_LISP ("completion-ignored-extensions", &Vcompletion_ignored_extensions,
695 "*Completion ignores filenames ending in any string in this list.\n\
696 This variable does not affect lists of possible completions,\n\
697 but does affect the commands that actually do completions.");
698 Vcompletion_ignored_extensions = Qnil;
699 }