11acd27e7Smillert /* complete.c -- filename completion for readline. */
21acd27e7Smillert
31acd27e7Smillert /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
41acd27e7Smillert
51acd27e7Smillert This file is part of the GNU Readline Library, a library for
61acd27e7Smillert reading lines of text with interactive input and history editing.
71acd27e7Smillert
81acd27e7Smillert The GNU Readline Library is free software; you can redistribute it
91acd27e7Smillert and/or modify it under the terms of the GNU General Public License
101acd27e7Smillert as published by the Free Software Foundation; either version 2, or
111acd27e7Smillert (at your option) any later version.
121acd27e7Smillert
131acd27e7Smillert The GNU Readline Library is distributed in the hope that it will be
141acd27e7Smillert useful, but WITHOUT ANY WARRANTY; without even the implied warranty
151acd27e7Smillert of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
161acd27e7Smillert GNU General Public License for more details.
171acd27e7Smillert
181acd27e7Smillert The GNU General Public License is often shipped with GNU software, and
191acd27e7Smillert is generally kept in a file called COPYING or LICENSE. If you do not
201acd27e7Smillert have a copy of the license, write to the Free Software Foundation,
211acd27e7Smillert 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
221acd27e7Smillert #define READLINE_LIBRARY
231acd27e7Smillert
241acd27e7Smillert #if defined (HAVE_CONFIG_H)
251acd27e7Smillert # include <config.h>
261acd27e7Smillert #endif
271acd27e7Smillert
281acd27e7Smillert #include <sys/types.h>
291acd27e7Smillert #include <fcntl.h>
301acd27e7Smillert #if defined (HAVE_SYS_FILE_H)
311acd27e7Smillert #include <sys/file.h>
321acd27e7Smillert #endif
331acd27e7Smillert
341acd27e7Smillert #if defined (HAVE_UNISTD_H)
351acd27e7Smillert # include <unistd.h>
361acd27e7Smillert #endif /* HAVE_UNISTD_H */
371acd27e7Smillert
381acd27e7Smillert #if defined (HAVE_STDLIB_H)
391acd27e7Smillert # include <stdlib.h>
401acd27e7Smillert #else
411acd27e7Smillert # include "ansi_stdlib.h"
421acd27e7Smillert #endif /* HAVE_STDLIB_H */
431acd27e7Smillert
441acd27e7Smillert #include <stdio.h>
451acd27e7Smillert
461acd27e7Smillert #include <errno.h>
471acd27e7Smillert #if !defined (errno)
481acd27e7Smillert extern int errno;
491acd27e7Smillert #endif /* !errno */
501acd27e7Smillert
511acd27e7Smillert #include <pwd.h>
521acd27e7Smillert
531acd27e7Smillert #include "posixdir.h"
541acd27e7Smillert #include "posixstat.h"
551acd27e7Smillert
561acd27e7Smillert /* System-specific feature definitions and include files. */
571acd27e7Smillert #include "rldefs.h"
58af70c2dfSkettenis #include "rlmbutil.h"
591acd27e7Smillert
601acd27e7Smillert /* Some standard library routines. */
611acd27e7Smillert #include "readline.h"
621acd27e7Smillert #include "xmalloc.h"
631acd27e7Smillert #include "rlprivate.h"
641acd27e7Smillert
651acd27e7Smillert #ifdef __STDC__
661acd27e7Smillert typedef int QSFUNC (const void *, const void *);
671acd27e7Smillert #else
681acd27e7Smillert typedef int QSFUNC ();
691acd27e7Smillert #endif
701acd27e7Smillert
71af70c2dfSkettenis #ifdef HAVE_LSTAT
72af70c2dfSkettenis # define LSTAT lstat
73af70c2dfSkettenis #else
74af70c2dfSkettenis # define LSTAT stat
75af70c2dfSkettenis #endif
76af70c2dfSkettenis
77af70c2dfSkettenis /* Unix version of a hidden file. Could be different on other systems. */
78af70c2dfSkettenis #define HIDDEN_FILE(fname) ((fname)[0] == '.')
79af70c2dfSkettenis
80af70c2dfSkettenis /* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
81af70c2dfSkettenis defined. */
82af70c2dfSkettenis #if !defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE)
83af70c2dfSkettenis extern struct passwd *getpwent PARAMS((void));
84af70c2dfSkettenis #endif /* !HAVE_GETPW_DECLS || _POSIX_SOURCE */
85af70c2dfSkettenis
861acd27e7Smillert /* If non-zero, then this is the address of a function to call when
871acd27e7Smillert completing a word would normally display the list of possible matches.
881acd27e7Smillert This function is called instead of actually doing the display.
891acd27e7Smillert It takes three arguments: (char **matches, int num_matches, int max_length)
901acd27e7Smillert where MATCHES is the array of strings that matched, NUM_MATCHES is the
911acd27e7Smillert number of strings in that array, and MAX_LENGTH is the length of the
921acd27e7Smillert longest string in that array. */
93af70c2dfSkettenis rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
941acd27e7Smillert
951acd27e7Smillert #if defined (VISIBLE_STATS)
961acd27e7Smillert # if !defined (X_OK)
971acd27e7Smillert # define X_OK 1
981acd27e7Smillert # endif
99af70c2dfSkettenis static int stat_char PARAMS((char *));
1001acd27e7Smillert #endif
1011acd27e7Smillert
102af70c2dfSkettenis static char *rl_quote_filename PARAMS((char *, int, char *));
1031acd27e7Smillert
104af70c2dfSkettenis static void set_completion_defaults PARAMS((int));
105af70c2dfSkettenis static int get_y_or_n PARAMS((int));
106af70c2dfSkettenis static int _rl_internal_pager PARAMS((int));
107af70c2dfSkettenis static char *printable_part PARAMS((char *));
108af70c2dfSkettenis static int print_filename PARAMS((char *, char *));
109af70c2dfSkettenis
110af70c2dfSkettenis static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
111af70c2dfSkettenis
112af70c2dfSkettenis static char **remove_duplicate_matches PARAMS((char **));
113af70c2dfSkettenis static void insert_match PARAMS((char *, int, int, char *));
114af70c2dfSkettenis static int append_to_match PARAMS((char *, int, int, int));
115af70c2dfSkettenis static void insert_all_matches PARAMS((char **, int, char *));
116af70c2dfSkettenis static void display_matches PARAMS((char **));
117af70c2dfSkettenis static int compute_lcd_of_matches PARAMS((char **, int, const char *));
118af70c2dfSkettenis static int postprocess_matches PARAMS((char ***, int));
119af70c2dfSkettenis
120af70c2dfSkettenis static char *make_quoted_replacement PARAMS((char *, int, char *));
1211acd27e7Smillert
1221acd27e7Smillert /* **************************************************************** */
1231acd27e7Smillert /* */
1241acd27e7Smillert /* Completion matching, from readline's point of view. */
1251acd27e7Smillert /* */
1261acd27e7Smillert /* **************************************************************** */
1271acd27e7Smillert
1281acd27e7Smillert /* Variables known only to the readline library. */
1291acd27e7Smillert
1301acd27e7Smillert /* If non-zero, non-unique completions always show the list of matches. */
1311acd27e7Smillert int _rl_complete_show_all = 0;
1321acd27e7Smillert
1331acd27e7Smillert /* If non-zero, completed directory names have a slash appended. */
1341acd27e7Smillert int _rl_complete_mark_directories = 1;
1351acd27e7Smillert
136af70c2dfSkettenis /* If non-zero, the symlinked directory completion behavior introduced in
137af70c2dfSkettenis readline-4.2a is disabled, and symlinks that point to directories have
138af70c2dfSkettenis a slash appended (subject to the value of _rl_complete_mark_directories).
139af70c2dfSkettenis This is user-settable via the mark-symlinked-directories variable. */
140af70c2dfSkettenis int _rl_complete_mark_symlink_dirs = 0;
141af70c2dfSkettenis
1421acd27e7Smillert /* If non-zero, completions are printed horizontally in alphabetical order,
1431acd27e7Smillert like `ls -x'. */
1441acd27e7Smillert int _rl_print_completions_horizontally;
1451acd27e7Smillert
1461acd27e7Smillert /* Non-zero means that case is not significant in filename completion. */
1471acd27e7Smillert #if defined (__MSDOS__) && !defined (__DJGPP__)
1481acd27e7Smillert int _rl_completion_case_fold = 1;
1491acd27e7Smillert #else
1501acd27e7Smillert int _rl_completion_case_fold;
1511acd27e7Smillert #endif
1521acd27e7Smillert
153af70c2dfSkettenis /* If non-zero, don't match hidden files (filenames beginning with a `.' on
154af70c2dfSkettenis Unix) when doing filename completion. */
155af70c2dfSkettenis int _rl_match_hidden_files = 1;
156af70c2dfSkettenis
1571acd27e7Smillert /* Global variables available to applications using readline. */
1581acd27e7Smillert
1591acd27e7Smillert #if defined (VISIBLE_STATS)
1601acd27e7Smillert /* Non-zero means add an additional character to each filename displayed
1611acd27e7Smillert during listing completion iff rl_filename_completion_desired which helps
1621acd27e7Smillert to indicate the type of file being listed. */
1631acd27e7Smillert int rl_visible_stats = 0;
1641acd27e7Smillert #endif /* VISIBLE_STATS */
1651acd27e7Smillert
1661acd27e7Smillert /* If non-zero, then this is the address of a function to call when
1671acd27e7Smillert completing on a directory name. The function is called with
1681acd27e7Smillert the address of a string (the current directory name) as an arg. */
169af70c2dfSkettenis rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
170af70c2dfSkettenis
171af70c2dfSkettenis rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
1721acd27e7Smillert
1731acd27e7Smillert /* Non-zero means readline completion functions perform tilde expansion. */
1741acd27e7Smillert int rl_complete_with_tilde_expansion = 0;
1751acd27e7Smillert
1761acd27e7Smillert /* Pointer to the generator function for completion_matches ().
177af70c2dfSkettenis NULL means to use rl_filename_completion_function (), the default filename
1781acd27e7Smillert completer. */
179af70c2dfSkettenis rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
1801acd27e7Smillert
1811acd27e7Smillert /* Pointer to alternative function to create matches.
1821acd27e7Smillert Function is called with TEXT, START, and END.
1831acd27e7Smillert START and END are indices in RL_LINE_BUFFER saying what the boundaries
1841acd27e7Smillert of TEXT are.
1851acd27e7Smillert If this function exists and returns NULL then call the value of
1861acd27e7Smillert rl_completion_entry_function to try to match, otherwise use the
1871acd27e7Smillert array of strings returned. */
188af70c2dfSkettenis rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL;
1891acd27e7Smillert
1901acd27e7Smillert /* Non-zero means to suppress normal filename completion after the
1911acd27e7Smillert user-specified completion function has been called. */
1921acd27e7Smillert int rl_attempted_completion_over = 0;
1931acd27e7Smillert
1941acd27e7Smillert /* Set to a character indicating the type of completion being performed
1951acd27e7Smillert by rl_complete_internal, available for use by application completion
1961acd27e7Smillert functions. */
1971acd27e7Smillert int rl_completion_type = 0;
1981acd27e7Smillert
1991acd27e7Smillert /* Up to this many items will be displayed in response to a
2001acd27e7Smillert possible-completions call. After that, we ask the user if
2011acd27e7Smillert she is sure she wants to see them all. */
2021acd27e7Smillert int rl_completion_query_items = 100;
2031acd27e7Smillert
204af70c2dfSkettenis int _rl_page_completions = 1;
205af70c2dfSkettenis
2061acd27e7Smillert /* The basic list of characters that signal a break between words for the
2071acd27e7Smillert completer routine. The contents of this variable is what breaks words
2081acd27e7Smillert in the shell, i.e. " \t\n\"\\'`@$><=" */
209af70c2dfSkettenis const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
2101acd27e7Smillert
2111acd27e7Smillert /* List of basic quoting characters. */
212af70c2dfSkettenis const char *rl_basic_quote_characters = "\"'";
2131acd27e7Smillert
2141acd27e7Smillert /* The list of characters that signal a break between words for
2151acd27e7Smillert rl_complete_internal. The default list is the contents of
2161acd27e7Smillert rl_basic_word_break_characters. */
217af70c2dfSkettenis const char *rl_completer_word_break_characters = (const char *)NULL;
2181acd27e7Smillert
2191acd27e7Smillert /* List of characters which can be used to quote a substring of the line.
2201acd27e7Smillert Completion occurs on the entire substring, and within the substring
2211acd27e7Smillert rl_completer_word_break_characters are treated as any other character,
2221acd27e7Smillert unless they also appear within this list. */
223af70c2dfSkettenis const char *rl_completer_quote_characters = (const char *)NULL;
2241acd27e7Smillert
2251acd27e7Smillert /* List of characters that should be quoted in filenames by the completer. */
226af70c2dfSkettenis const char *rl_filename_quote_characters = (const char *)NULL;
2271acd27e7Smillert
2281acd27e7Smillert /* List of characters that are word break characters, but should be left
2291acd27e7Smillert in TEXT when it is passed to the completion function. The shell uses
2301acd27e7Smillert this to help determine what kind of completing to do. */
231af70c2dfSkettenis const char *rl_special_prefixes = (const char *)NULL;
2321acd27e7Smillert
2331acd27e7Smillert /* If non-zero, then disallow duplicates in the matches. */
2341acd27e7Smillert int rl_ignore_completion_duplicates = 1;
2351acd27e7Smillert
2361acd27e7Smillert /* Non-zero means that the results of the matches are to be treated
2371acd27e7Smillert as filenames. This is ALWAYS zero on entry, and can only be changed
2381acd27e7Smillert within a completion entry finder function. */
2391acd27e7Smillert int rl_filename_completion_desired = 0;
2401acd27e7Smillert
2411acd27e7Smillert /* Non-zero means that the results of the matches are to be quoted using
2421acd27e7Smillert double quotes (or an application-specific quoting mechanism) if the
2431acd27e7Smillert filename contains any characters in rl_filename_quote_chars. This is
2441acd27e7Smillert ALWAYS non-zero on entry, and can only be changed within a completion
2451acd27e7Smillert entry finder function. */
2461acd27e7Smillert int rl_filename_quoting_desired = 1;
2471acd27e7Smillert
2481acd27e7Smillert /* This function, if defined, is called by the completer when real
2491acd27e7Smillert filename completion is done, after all the matching names have been
2501acd27e7Smillert generated. It is passed a (char**) known as matches in the code below.
2511acd27e7Smillert It consists of a NULL-terminated array of pointers to potential
2521acd27e7Smillert matching strings. The 1st element (matches[0]) is the maximal
2531acd27e7Smillert substring that is common to all matches. This function can re-arrange
2541acd27e7Smillert the list of matches as required, but all elements of the array must be
2551acd27e7Smillert free()'d if they are deleted. The main intent of this function is
2561acd27e7Smillert to implement FIGNORE a la SunOS csh. */
257af70c2dfSkettenis rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL;
2581acd27e7Smillert
2591acd27e7Smillert /* Set to a function to quote a filename in an application-specific fashion.
2601acd27e7Smillert Called with the text to quote, the type of match found (single or multiple)
2611acd27e7Smillert and a pointer to the quoting character to be used, which the function can
2621acd27e7Smillert reset if desired. */
263af70c2dfSkettenis rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename;
2641acd27e7Smillert
2651acd27e7Smillert /* Function to call to remove quoting characters from a filename. Called
2661acd27e7Smillert before completion is attempted, so the embedded quotes do not interfere
2671acd27e7Smillert with matching names in the file system. Readline doesn't do anything
2681acd27e7Smillert with this; it's set only by applications. */
269af70c2dfSkettenis rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
2701acd27e7Smillert
2711acd27e7Smillert /* Function to call to decide whether or not a word break character is
2721acd27e7Smillert quoted. If a character is quoted, it does not break words for the
2731acd27e7Smillert completer. */
274af70c2dfSkettenis rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
275af70c2dfSkettenis
276af70c2dfSkettenis /* If non-zero, the completion functions don't append anything except a
277af70c2dfSkettenis possible closing quote. This is set to 0 by rl_complete_internal and
278af70c2dfSkettenis may be changed by an application-specific completion function. */
279af70c2dfSkettenis int rl_completion_suppress_append = 0;
2801acd27e7Smillert
2811acd27e7Smillert /* Character appended to completed words when at the end of the line. The
2821acd27e7Smillert default is a space. */
2831acd27e7Smillert int rl_completion_append_character = ' ';
2841acd27e7Smillert
285af70c2dfSkettenis /* If non-zero, a slash will be appended to completed filenames that are
286af70c2dfSkettenis symbolic links to directory names, subject to the value of the
287af70c2dfSkettenis mark-directories variable (which is user-settable). This exists so
288af70c2dfSkettenis that application completion functions can override the user's preference
289af70c2dfSkettenis (set via the mark-symlinked-directories variable) if appropriate.
290af70c2dfSkettenis It's set to the value of _rl_complete_mark_symlink_dirs in
291af70c2dfSkettenis rl_complete_internal before any application-specific completion
292af70c2dfSkettenis function is called, so without that function doing anything, the user's
293af70c2dfSkettenis preferences are honored. */
294af70c2dfSkettenis int rl_completion_mark_symlink_dirs;
295af70c2dfSkettenis
2961acd27e7Smillert /* If non-zero, inhibit completion (temporarily). */
2971acd27e7Smillert int rl_inhibit_completion;
2981acd27e7Smillert
2991acd27e7Smillert /* Variables local to this file. */
3001acd27e7Smillert
3011acd27e7Smillert /* Local variable states what happened during the last completion attempt. */
3021acd27e7Smillert static int completion_changed_buffer;
3031acd27e7Smillert
3041acd27e7Smillert /*************************************/
3051acd27e7Smillert /* */
3061acd27e7Smillert /* Bindable completion functions */
3071acd27e7Smillert /* */
3081acd27e7Smillert /*************************************/
3091acd27e7Smillert
3101acd27e7Smillert /* Complete the word at or before point. You have supplied the function
3111acd27e7Smillert that does the initial simple matching selection algorithm (see
312af70c2dfSkettenis rl_completion_matches ()). The default is to do filename completion. */
3131acd27e7Smillert int
rl_complete(ignore,invoking_key)3141acd27e7Smillert rl_complete (ignore, invoking_key)
3151acd27e7Smillert int ignore, invoking_key;
3161acd27e7Smillert {
3171acd27e7Smillert if (rl_inhibit_completion)
318af70c2dfSkettenis return (_rl_insert_char (ignore, invoking_key));
3191acd27e7Smillert else if (rl_last_func == rl_complete && !completion_changed_buffer)
3201acd27e7Smillert return (rl_complete_internal ('?'));
3211acd27e7Smillert else if (_rl_complete_show_all)
3221acd27e7Smillert return (rl_complete_internal ('!'));
3231acd27e7Smillert else
3241acd27e7Smillert return (rl_complete_internal (TAB));
3251acd27e7Smillert }
3261acd27e7Smillert
3271acd27e7Smillert /* List the possible completions. See description of rl_complete (). */
3281acd27e7Smillert int
rl_possible_completions(ignore,invoking_key)3291acd27e7Smillert rl_possible_completions (ignore, invoking_key)
3301acd27e7Smillert int ignore, invoking_key;
3311acd27e7Smillert {
3321acd27e7Smillert return (rl_complete_internal ('?'));
3331acd27e7Smillert }
3341acd27e7Smillert
3351acd27e7Smillert int
rl_insert_completions(ignore,invoking_key)3361acd27e7Smillert rl_insert_completions (ignore, invoking_key)
3371acd27e7Smillert int ignore, invoking_key;
3381acd27e7Smillert {
3391acd27e7Smillert return (rl_complete_internal ('*'));
3401acd27e7Smillert }
3411acd27e7Smillert
342af70c2dfSkettenis /* Return the correct value to pass to rl_complete_internal performing
343af70c2dfSkettenis the same tests as rl_complete. This allows consecutive calls to an
344af70c2dfSkettenis application's completion function to list possible completions and for
345af70c2dfSkettenis an application-specific completion function to honor the
346af70c2dfSkettenis show-all-if-ambiguous readline variable. */
347af70c2dfSkettenis int
rl_completion_mode(cfunc)348af70c2dfSkettenis rl_completion_mode (cfunc)
349af70c2dfSkettenis rl_command_func_t *cfunc;
350af70c2dfSkettenis {
351af70c2dfSkettenis if (rl_last_func == cfunc && !completion_changed_buffer)
352af70c2dfSkettenis return '?';
353af70c2dfSkettenis else if (_rl_complete_show_all)
354af70c2dfSkettenis return '!';
355af70c2dfSkettenis else
356af70c2dfSkettenis return TAB;
357af70c2dfSkettenis }
358af70c2dfSkettenis
3591acd27e7Smillert /************************************/
3601acd27e7Smillert /* */
3611acd27e7Smillert /* Completion utility functions */
3621acd27e7Smillert /* */
3631acd27e7Smillert /************************************/
3641acd27e7Smillert
365af70c2dfSkettenis /* Set default values for readline word completion. These are the variables
366af70c2dfSkettenis that application completion functions can change or inspect. */
367af70c2dfSkettenis static void
set_completion_defaults(what_to_do)368af70c2dfSkettenis set_completion_defaults (what_to_do)
369af70c2dfSkettenis int what_to_do;
3701acd27e7Smillert {
371af70c2dfSkettenis /* Only the completion entry function can change these. */
372af70c2dfSkettenis rl_filename_completion_desired = 0;
373af70c2dfSkettenis rl_filename_quoting_desired = 1;
374af70c2dfSkettenis rl_completion_type = what_to_do;
375af70c2dfSkettenis rl_completion_suppress_append = 0;
3761acd27e7Smillert
377af70c2dfSkettenis /* The completion entry function may optionally change this. */
378af70c2dfSkettenis rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
3791acd27e7Smillert }
3801acd27e7Smillert
3811acd27e7Smillert /* The user must press "y" or "n". Non-zero return means "y" pressed. */
3821acd27e7Smillert static int
get_y_or_n(for_pager)383af70c2dfSkettenis get_y_or_n (for_pager)
384af70c2dfSkettenis int for_pager;
3851acd27e7Smillert {
3861acd27e7Smillert int c;
3871acd27e7Smillert
3881acd27e7Smillert for (;;)
3891acd27e7Smillert {
390af70c2dfSkettenis RL_SETSTATE(RL_STATE_MOREINPUT);
3911acd27e7Smillert c = rl_read_key ();
392af70c2dfSkettenis RL_UNSETSTATE(RL_STATE_MOREINPUT);
393af70c2dfSkettenis
3941acd27e7Smillert if (c == 'y' || c == 'Y' || c == ' ')
3951acd27e7Smillert return (1);
3961acd27e7Smillert if (c == 'n' || c == 'N' || c == RUBOUT)
3971acd27e7Smillert return (0);
3981acd27e7Smillert if (c == ABORT_CHAR)
3991acd27e7Smillert _rl_abort_internal ();
400af70c2dfSkettenis if (for_pager && (c == NEWLINE || c == RETURN))
401af70c2dfSkettenis return (2);
402af70c2dfSkettenis if (for_pager && (c == 'q' || c == 'Q'))
403af70c2dfSkettenis return (0);
404af70c2dfSkettenis rl_ding ();
4051acd27e7Smillert }
4061acd27e7Smillert }
4071acd27e7Smillert
408af70c2dfSkettenis static int
_rl_internal_pager(lines)409af70c2dfSkettenis _rl_internal_pager (lines)
410af70c2dfSkettenis int lines;
411af70c2dfSkettenis {
412af70c2dfSkettenis int i;
413af70c2dfSkettenis
414af70c2dfSkettenis fprintf (rl_outstream, "--More--");
415af70c2dfSkettenis fflush (rl_outstream);
416af70c2dfSkettenis i = get_y_or_n (1);
417af70c2dfSkettenis _rl_erase_entire_line ();
418af70c2dfSkettenis if (i == 0)
419af70c2dfSkettenis return -1;
420af70c2dfSkettenis else if (i == 2)
421af70c2dfSkettenis return (lines - 1);
422af70c2dfSkettenis else
423af70c2dfSkettenis return 0;
424af70c2dfSkettenis }
425af70c2dfSkettenis
4261acd27e7Smillert #if defined (VISIBLE_STATS)
4271acd27e7Smillert /* Return the character which best describes FILENAME.
4281acd27e7Smillert `@' for symbolic links
4291acd27e7Smillert `/' for directories
4301acd27e7Smillert `*' for executables
4311acd27e7Smillert `=' for sockets
4321acd27e7Smillert `|' for FIFOs
4331acd27e7Smillert `%' for character special devices
4341acd27e7Smillert `#' for block special devices */
4351acd27e7Smillert static int
stat_char(filename)4361acd27e7Smillert stat_char (filename)
4371acd27e7Smillert char *filename;
4381acd27e7Smillert {
4391acd27e7Smillert struct stat finfo;
4401acd27e7Smillert int character, r;
4411acd27e7Smillert
4421acd27e7Smillert #if defined (HAVE_LSTAT) && defined (S_ISLNK)
4431acd27e7Smillert r = lstat (filename, &finfo);
4441acd27e7Smillert #else
4451acd27e7Smillert r = stat (filename, &finfo);
4461acd27e7Smillert #endif
4471acd27e7Smillert
4481acd27e7Smillert if (r == -1)
4491acd27e7Smillert return (0);
4501acd27e7Smillert
4511acd27e7Smillert character = 0;
4521acd27e7Smillert if (S_ISDIR (finfo.st_mode))
4531acd27e7Smillert character = '/';
4541acd27e7Smillert #if defined (S_ISCHR)
4551acd27e7Smillert else if (S_ISCHR (finfo.st_mode))
4561acd27e7Smillert character = '%';
4571acd27e7Smillert #endif /* S_ISCHR */
4581acd27e7Smillert #if defined (S_ISBLK)
4591acd27e7Smillert else if (S_ISBLK (finfo.st_mode))
4601acd27e7Smillert character = '#';
4611acd27e7Smillert #endif /* S_ISBLK */
4621acd27e7Smillert #if defined (S_ISLNK)
4631acd27e7Smillert else if (S_ISLNK (finfo.st_mode))
4641acd27e7Smillert character = '@';
4651acd27e7Smillert #endif /* S_ISLNK */
4661acd27e7Smillert #if defined (S_ISSOCK)
4671acd27e7Smillert else if (S_ISSOCK (finfo.st_mode))
4681acd27e7Smillert character = '=';
4691acd27e7Smillert #endif /* S_ISSOCK */
4701acd27e7Smillert #if defined (S_ISFIFO)
4711acd27e7Smillert else if (S_ISFIFO (finfo.st_mode))
4721acd27e7Smillert character = '|';
4731acd27e7Smillert #endif
4741acd27e7Smillert else if (S_ISREG (finfo.st_mode))
4751acd27e7Smillert {
4761acd27e7Smillert if (access (filename, X_OK) == 0)
4771acd27e7Smillert character = '*';
4781acd27e7Smillert }
4791acd27e7Smillert return (character);
4801acd27e7Smillert }
4811acd27e7Smillert #endif /* VISIBLE_STATS */
4821acd27e7Smillert
4831acd27e7Smillert /* Return the portion of PATHNAME that should be output when listing
4841acd27e7Smillert possible completions. If we are hacking filename completion, we
4851acd27e7Smillert are only interested in the basename, the portion following the
486af70c2dfSkettenis final slash. Otherwise, we return what we were passed. Since
487af70c2dfSkettenis printing empty strings is not very informative, if we're doing
488af70c2dfSkettenis filename completion, and the basename is the empty string, we look
489af70c2dfSkettenis for the previous slash and return the portion following that. If
490af70c2dfSkettenis there's no previous slash, we just return what we were passed. */
4911acd27e7Smillert static char *
printable_part(pathname)4921acd27e7Smillert printable_part (pathname)
4931acd27e7Smillert char *pathname;
4941acd27e7Smillert {
495af70c2dfSkettenis char *temp, *x;
4961acd27e7Smillert
497af70c2dfSkettenis if (rl_filename_completion_desired == 0) /* don't need to do anything */
498af70c2dfSkettenis return (pathname);
499af70c2dfSkettenis
500af70c2dfSkettenis temp = strrchr (pathname, '/');
5011acd27e7Smillert #if defined (__MSDOS__)
502af70c2dfSkettenis if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
5031acd27e7Smillert temp = pathname + 1;
5041acd27e7Smillert #endif
505af70c2dfSkettenis
506af70c2dfSkettenis if (temp == 0 || *temp == '\0')
507af70c2dfSkettenis return (pathname);
508af70c2dfSkettenis /* If the basename is NULL, we might have a pathname like '/usr/src/'.
509af70c2dfSkettenis Look for a previous slash and, if one is found, return the portion
510af70c2dfSkettenis following that slash. If there's no previous slash, just return the
511af70c2dfSkettenis pathname we were passed. */
512af70c2dfSkettenis else if (temp[1] == '\0')
513af70c2dfSkettenis {
514af70c2dfSkettenis for (x = temp - 1; x > pathname; x--)
515af70c2dfSkettenis if (*x == '/')
516af70c2dfSkettenis break;
517af70c2dfSkettenis return ((*x == '/') ? x + 1 : pathname);
518af70c2dfSkettenis }
519af70c2dfSkettenis else
520af70c2dfSkettenis return ++temp;
5211acd27e7Smillert }
5221acd27e7Smillert
5231acd27e7Smillert /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
5241acd27e7Smillert are using it, check for and output a single character for `special'
5251acd27e7Smillert filenames. Return the number of characters we output. */
5261acd27e7Smillert
5271acd27e7Smillert #define PUTX(c) \
5281acd27e7Smillert do { \
5291acd27e7Smillert if (CTRL_CHAR (c)) \
5301acd27e7Smillert { \
5311acd27e7Smillert putc ('^', rl_outstream); \
5321acd27e7Smillert putc (UNCTRL (c), rl_outstream); \
5331acd27e7Smillert printed_len += 2; \
5341acd27e7Smillert } \
5351acd27e7Smillert else if (c == RUBOUT) \
5361acd27e7Smillert { \
5371acd27e7Smillert putc ('^', rl_outstream); \
5381acd27e7Smillert putc ('?', rl_outstream); \
5391acd27e7Smillert printed_len += 2; \
5401acd27e7Smillert } \
5411acd27e7Smillert else \
5421acd27e7Smillert { \
5431acd27e7Smillert putc (c, rl_outstream); \
5441acd27e7Smillert printed_len++; \
5451acd27e7Smillert } \
5461acd27e7Smillert } while (0)
5471acd27e7Smillert
5481acd27e7Smillert static int
print_filename(to_print,full_pathname)5491acd27e7Smillert print_filename (to_print, full_pathname)
5501acd27e7Smillert char *to_print, *full_pathname;
5511acd27e7Smillert {
5521acd27e7Smillert int printed_len = 0;
5531acd27e7Smillert #if !defined (VISIBLE_STATS)
5541acd27e7Smillert char *s;
5551acd27e7Smillert
5561acd27e7Smillert for (s = to_print; *s; s++)
5571acd27e7Smillert {
5581acd27e7Smillert PUTX (*s);
5591acd27e7Smillert }
5601acd27e7Smillert #else
5611acd27e7Smillert char *s, c, *new_full_pathname;
56263bef317Sbeck int extension_char;
5631acd27e7Smillert
5641acd27e7Smillert for (s = to_print; *s; s++)
5651acd27e7Smillert {
5661acd27e7Smillert PUTX (*s);
5671acd27e7Smillert }
5681acd27e7Smillert
5691acd27e7Smillert if (rl_filename_completion_desired && rl_visible_stats)
5701acd27e7Smillert {
5711acd27e7Smillert /* If to_print != full_pathname, to_print is the basename of the
5721acd27e7Smillert path passed. In this case, we try to expand the directory
5731acd27e7Smillert name before checking for the stat character. */
5741acd27e7Smillert if (to_print != full_pathname)
5751acd27e7Smillert {
5761acd27e7Smillert /* Terminate the directory name. */
5771acd27e7Smillert c = to_print[-1];
5781acd27e7Smillert to_print[-1] = '\0';
5791acd27e7Smillert
5801acd27e7Smillert /* If setting the last slash in full_pathname to a NUL results in
5811acd27e7Smillert full_pathname being the empty string, we are trying to complete
5821acd27e7Smillert files in the root directory. If we pass a null string to the
5831acd27e7Smillert bash directory completion hook, for example, it will expand it
5841acd27e7Smillert to the current directory. We just want the `/'. */
5851acd27e7Smillert s = tilde_expand (full_pathname && *full_pathname ? full_pathname : "/");
5861acd27e7Smillert if (rl_directory_completion_hook)
5871acd27e7Smillert (*rl_directory_completion_hook) (&s);
58863bef317Sbeck if (asprintf(&new_full_pathname, "%s/%s", s, to_print) == -1)
58963bef317Sbeck memory_error_and_abort("asprintf");
5901acd27e7Smillert extension_char = stat_char (new_full_pathname);
5911acd27e7Smillert free (new_full_pathname);
5921acd27e7Smillert to_print[-1] = c;
5931acd27e7Smillert }
5941acd27e7Smillert else
5951acd27e7Smillert {
5961acd27e7Smillert s = tilde_expand (full_pathname);
5971acd27e7Smillert extension_char = stat_char (s);
5981acd27e7Smillert }
5991acd27e7Smillert
6001acd27e7Smillert free (s);
6011acd27e7Smillert if (extension_char)
6021acd27e7Smillert {
6031acd27e7Smillert putc (extension_char, rl_outstream);
6041acd27e7Smillert printed_len++;
6051acd27e7Smillert }
6061acd27e7Smillert }
6071acd27e7Smillert #endif /* VISIBLE_STATS */
6081acd27e7Smillert return printed_len;
6091acd27e7Smillert }
6101acd27e7Smillert
6111acd27e7Smillert static char *
rl_quote_filename(s,rtype,qcp)6121acd27e7Smillert rl_quote_filename (s, rtype, qcp)
6131acd27e7Smillert char *s;
6141acd27e7Smillert int rtype;
6151acd27e7Smillert char *qcp;
6161acd27e7Smillert {
6171acd27e7Smillert char *r;
61863bef317Sbeck int len = strlen(s) + 2;
6191acd27e7Smillert
620af70c2dfSkettenis r = (char *)xmalloc (len);
6211acd27e7Smillert *r = *rl_completer_quote_characters;
62263bef317Sbeck strlcpy (r + 1, s, len - 1);
6231acd27e7Smillert if (qcp)
6241acd27e7Smillert *qcp = *rl_completer_quote_characters;
6251acd27e7Smillert return r;
6261acd27e7Smillert }
6271acd27e7Smillert
6281acd27e7Smillert /* Find the bounds of the current word for completion purposes, and leave
6291acd27e7Smillert rl_point set to the end of the word. This function skips quoted
6301acd27e7Smillert substrings (characters between matched pairs of characters in
631af70c2dfSkettenis rl_completer_quote_characters). First we try to find an unclosed
6321acd27e7Smillert quoted substring on which to do matching. If one is not found, we use
6331acd27e7Smillert the word break characters to find the boundaries of the current word.
6341acd27e7Smillert We call an application-specific function to decide whether or not a
6351acd27e7Smillert particular word break character is quoted; if that function returns a
6361acd27e7Smillert non-zero result, the character does not break a word. This function
6371acd27e7Smillert returns the opening quote character if we found an unclosed quoted
6381acd27e7Smillert substring, '\0' otherwise. FP, if non-null, is set to a value saying
6391acd27e7Smillert which (shell-like) quote characters we found (single quote, double
6401acd27e7Smillert quote, or backslash) anywhere in the string. DP, if non-null, is set to
6411acd27e7Smillert the value of the delimiter character that caused a word break. */
6421acd27e7Smillert
643af70c2dfSkettenis char
_rl_find_completion_word(fp,dp)644af70c2dfSkettenis _rl_find_completion_word (fp, dp)
6451acd27e7Smillert int *fp, *dp;
6461acd27e7Smillert {
6471acd27e7Smillert int scan, end, found_quote, delimiter, pass_next, isbrk;
6481acd27e7Smillert char quote_char;
6491acd27e7Smillert
6501acd27e7Smillert end = rl_point;
6511acd27e7Smillert found_quote = delimiter = 0;
6521acd27e7Smillert quote_char = '\0';
6531acd27e7Smillert
6541acd27e7Smillert if (rl_completer_quote_characters)
6551acd27e7Smillert {
6561acd27e7Smillert /* We have a list of characters which can be used in pairs to
6571acd27e7Smillert quote substrings for the completer. Try to find the start
6581acd27e7Smillert of an unclosed quoted substring. */
6591acd27e7Smillert /* FOUND_QUOTE is set so we know what kind of quotes we found. */
6601acd27e7Smillert for (scan = pass_next = 0; scan < end; scan++)
6611acd27e7Smillert {
6621acd27e7Smillert if (pass_next)
6631acd27e7Smillert {
6641acd27e7Smillert pass_next = 0;
6651acd27e7Smillert continue;
6661acd27e7Smillert }
6671acd27e7Smillert
668af70c2dfSkettenis /* Shell-like semantics for single quotes -- don't allow backslash
669af70c2dfSkettenis to quote anything in single quotes, especially not the closing
670af70c2dfSkettenis quote. If you don't like this, take out the check on the value
671af70c2dfSkettenis of quote_char. */
672af70c2dfSkettenis if (quote_char != '\'' && rl_line_buffer[scan] == '\\')
6731acd27e7Smillert {
6741acd27e7Smillert pass_next = 1;
6751acd27e7Smillert found_quote |= RL_QF_BACKSLASH;
6761acd27e7Smillert continue;
6771acd27e7Smillert }
6781acd27e7Smillert
6791acd27e7Smillert if (quote_char != '\0')
6801acd27e7Smillert {
6811acd27e7Smillert /* Ignore everything until the matching close quote char. */
6821acd27e7Smillert if (rl_line_buffer[scan] == quote_char)
6831acd27e7Smillert {
6841acd27e7Smillert /* Found matching close. Abandon this substring. */
6851acd27e7Smillert quote_char = '\0';
6861acd27e7Smillert rl_point = end;
6871acd27e7Smillert }
6881acd27e7Smillert }
6891acd27e7Smillert else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
6901acd27e7Smillert {
6911acd27e7Smillert /* Found start of a quoted substring. */
6921acd27e7Smillert quote_char = rl_line_buffer[scan];
6931acd27e7Smillert rl_point = scan + 1;
6941acd27e7Smillert /* Shell-like quoting conventions. */
6951acd27e7Smillert if (quote_char == '\'')
6961acd27e7Smillert found_quote |= RL_QF_SINGLE_QUOTE;
6971acd27e7Smillert else if (quote_char == '"')
6981acd27e7Smillert found_quote |= RL_QF_DOUBLE_QUOTE;
699af70c2dfSkettenis else
700af70c2dfSkettenis found_quote |= RL_QF_OTHER_QUOTE;
7011acd27e7Smillert }
7021acd27e7Smillert }
7031acd27e7Smillert }
7041acd27e7Smillert
7051acd27e7Smillert if (rl_point == end && quote_char == '\0')
7061acd27e7Smillert {
7071acd27e7Smillert /* We didn't find an unclosed quoted substring upon which to do
7081acd27e7Smillert completion, so use the word break characters to find the
7091acd27e7Smillert substring on which to complete. */
710af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
711af70c2dfSkettenis while (rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_ANY))
712af70c2dfSkettenis #else
7131acd27e7Smillert while (--rl_point)
714af70c2dfSkettenis #endif
7151acd27e7Smillert {
7161acd27e7Smillert scan = rl_line_buffer[rl_point];
7171acd27e7Smillert
7181acd27e7Smillert if (strchr (rl_completer_word_break_characters, scan) == 0)
7191acd27e7Smillert continue;
7201acd27e7Smillert
7211acd27e7Smillert /* Call the application-specific function to tell us whether
7221acd27e7Smillert this word break character is quoted and should be skipped. */
7231acd27e7Smillert if (rl_char_is_quoted_p && found_quote &&
7241acd27e7Smillert (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
7251acd27e7Smillert continue;
7261acd27e7Smillert
7271acd27e7Smillert /* Convoluted code, but it avoids an n^2 algorithm with calls
7281acd27e7Smillert to char_is_quoted. */
7291acd27e7Smillert break;
7301acd27e7Smillert }
7311acd27e7Smillert }
7321acd27e7Smillert
7331acd27e7Smillert /* If we are at an unquoted word break, then advance past it. */
7341acd27e7Smillert scan = rl_line_buffer[rl_point];
7351acd27e7Smillert
7361acd27e7Smillert /* If there is an application-specific function to say whether or not
7371acd27e7Smillert a character is quoted and we found a quote character, let that
7381acd27e7Smillert function decide whether or not a character is a word break, even
7391acd27e7Smillert if it is found in rl_completer_word_break_characters. Don't bother
7401acd27e7Smillert if we're at the end of the line, though. */
7411acd27e7Smillert if (scan)
7421acd27e7Smillert {
7431acd27e7Smillert if (rl_char_is_quoted_p)
7441acd27e7Smillert isbrk = (found_quote == 0 ||
7451acd27e7Smillert (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
7461acd27e7Smillert strchr (rl_completer_word_break_characters, scan) != 0;
7471acd27e7Smillert else
7481acd27e7Smillert isbrk = strchr (rl_completer_word_break_characters, scan) != 0;
7491acd27e7Smillert
7501acd27e7Smillert if (isbrk)
7511acd27e7Smillert {
7521acd27e7Smillert /* If the character that caused the word break was a quoting
7531acd27e7Smillert character, then remember it as the delimiter. */
7541acd27e7Smillert if (rl_basic_quote_characters &&
7551acd27e7Smillert strchr (rl_basic_quote_characters, scan) &&
7561acd27e7Smillert (end - rl_point) > 1)
7571acd27e7Smillert delimiter = scan;
7581acd27e7Smillert
7591acd27e7Smillert /* If the character isn't needed to determine something special
7601acd27e7Smillert about what kind of completion to perform, then advance past it. */
7611acd27e7Smillert if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
7621acd27e7Smillert rl_point++;
7631acd27e7Smillert }
7641acd27e7Smillert }
7651acd27e7Smillert
7661acd27e7Smillert if (fp)
7671acd27e7Smillert *fp = found_quote;
7681acd27e7Smillert if (dp)
7691acd27e7Smillert *dp = delimiter;
7701acd27e7Smillert
7711acd27e7Smillert return (quote_char);
7721acd27e7Smillert }
7731acd27e7Smillert
7741acd27e7Smillert static char **
gen_completion_matches(text,start,end,our_func,found_quote,quote_char)7751acd27e7Smillert gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
7761acd27e7Smillert char *text;
7771acd27e7Smillert int start, end;
778af70c2dfSkettenis rl_compentry_func_t *our_func;
7791acd27e7Smillert int found_quote, quote_char;
7801acd27e7Smillert {
7811acd27e7Smillert char **matches, *temp;
7821acd27e7Smillert
7831acd27e7Smillert /* If the user wants to TRY to complete, but then wants to give
7841acd27e7Smillert up and use the default completion function, they set the
7851acd27e7Smillert variable rl_attempted_completion_function. */
7861acd27e7Smillert if (rl_attempted_completion_function)
7871acd27e7Smillert {
7881acd27e7Smillert matches = (*rl_attempted_completion_function) (text, start, end);
7891acd27e7Smillert
7901acd27e7Smillert if (matches || rl_attempted_completion_over)
7911acd27e7Smillert {
7921acd27e7Smillert rl_attempted_completion_over = 0;
7931acd27e7Smillert return (matches);
7941acd27e7Smillert }
7951acd27e7Smillert }
7961acd27e7Smillert
7971acd27e7Smillert /* Beware -- we're stripping the quotes here. Do this only if we know
7981acd27e7Smillert we are doing filename completion and the application has defined a
7991acd27e7Smillert filename dequoting function. */
8001acd27e7Smillert temp = (char *)NULL;
8011acd27e7Smillert
802af70c2dfSkettenis if (found_quote && our_func == rl_filename_completion_function &&
8031acd27e7Smillert rl_filename_dequoting_function)
8041acd27e7Smillert {
8051acd27e7Smillert /* delete single and double quotes */
8061acd27e7Smillert temp = (*rl_filename_dequoting_function) (text, quote_char);
8071acd27e7Smillert text = temp; /* not freeing text is not a memory leak */
8081acd27e7Smillert }
8091acd27e7Smillert
810af70c2dfSkettenis matches = rl_completion_matches (text, our_func);
8111acd27e7Smillert FREE (temp);
8121acd27e7Smillert return matches;
8131acd27e7Smillert }
8141acd27e7Smillert
8151acd27e7Smillert /* Filter out duplicates in MATCHES. This frees up the strings in
8161acd27e7Smillert MATCHES. */
8171acd27e7Smillert static char **
remove_duplicate_matches(matches)8181acd27e7Smillert remove_duplicate_matches (matches)
8191acd27e7Smillert char **matches;
8201acd27e7Smillert {
8211acd27e7Smillert char *lowest_common;
8221acd27e7Smillert int i, j, newlen;
8231acd27e7Smillert char dead_slot;
8241acd27e7Smillert char **temp_array;
8251acd27e7Smillert
8261acd27e7Smillert /* Sort the items. */
8271acd27e7Smillert for (i = 0; matches[i]; i++)
8281acd27e7Smillert ;
8291acd27e7Smillert
8301acd27e7Smillert /* Sort the array without matches[0], since we need it to
8311acd27e7Smillert stay in place no matter what. */
8321acd27e7Smillert if (i)
8331acd27e7Smillert qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
8341acd27e7Smillert
8351acd27e7Smillert /* Remember the lowest common denominator for it may be unique. */
8361acd27e7Smillert lowest_common = savestring (matches[0]);
8371acd27e7Smillert
8381acd27e7Smillert for (i = newlen = 0; matches[i + 1]; i++)
8391acd27e7Smillert {
8401acd27e7Smillert if (strcmp (matches[i], matches[i + 1]) == 0)
8411acd27e7Smillert {
8421acd27e7Smillert free (matches[i]);
8431acd27e7Smillert matches[i] = (char *)&dead_slot;
8441acd27e7Smillert }
8451acd27e7Smillert else
8461acd27e7Smillert newlen++;
8471acd27e7Smillert }
8481acd27e7Smillert
8491acd27e7Smillert /* We have marked all the dead slots with (char *)&dead_slot.
8501acd27e7Smillert Copy all the non-dead entries into a new array. */
8511acd27e7Smillert temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
8521acd27e7Smillert for (i = j = 1; matches[i]; i++)
8531acd27e7Smillert {
8541acd27e7Smillert if (matches[i] != (char *)&dead_slot)
8551acd27e7Smillert temp_array[j++] = matches[i];
8561acd27e7Smillert }
8571acd27e7Smillert temp_array[j] = (char *)NULL;
8581acd27e7Smillert
8591acd27e7Smillert if (matches[0] != (char *)&dead_slot)
8601acd27e7Smillert free (matches[0]);
8611acd27e7Smillert
8621acd27e7Smillert /* Place the lowest common denominator back in [0]. */
8631acd27e7Smillert temp_array[0] = lowest_common;
8641acd27e7Smillert
8651acd27e7Smillert /* If there is one string left, and it is identical to the
8661acd27e7Smillert lowest common denominator, then the LCD is the string to
8671acd27e7Smillert insert. */
8681acd27e7Smillert if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
8691acd27e7Smillert {
8701acd27e7Smillert free (temp_array[1]);
8711acd27e7Smillert temp_array[1] = (char *)NULL;
8721acd27e7Smillert }
8731acd27e7Smillert return (temp_array);
8741acd27e7Smillert }
8751acd27e7Smillert
8761acd27e7Smillert /* Find the common prefix of the list of matches, and put it into
8771acd27e7Smillert matches[0]. */
8781acd27e7Smillert static int
compute_lcd_of_matches(match_list,matches,text)8791acd27e7Smillert compute_lcd_of_matches (match_list, matches, text)
8801acd27e7Smillert char **match_list;
8811acd27e7Smillert int matches;
882af70c2dfSkettenis const char *text;
8831acd27e7Smillert {
8841acd27e7Smillert register int i, c1, c2, si;
8851acd27e7Smillert int low; /* Count of max-matched characters. */
886af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
887af70c2dfSkettenis int v;
888af70c2dfSkettenis mbstate_t ps1, ps2;
889af70c2dfSkettenis wchar_t wc1, wc2;
890af70c2dfSkettenis #endif
8911acd27e7Smillert
8921acd27e7Smillert /* If only one match, just use that. Otherwise, compare each
8931acd27e7Smillert member of the list with the next, finding out where they
8941acd27e7Smillert stop matching. */
8951acd27e7Smillert if (matches == 1)
8961acd27e7Smillert {
8971acd27e7Smillert match_list[0] = match_list[1];
8981acd27e7Smillert match_list[1] = (char *)NULL;
8991acd27e7Smillert return 1;
9001acd27e7Smillert }
9011acd27e7Smillert
9021acd27e7Smillert for (i = 1, low = 100000; i < matches; i++)
9031acd27e7Smillert {
904af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
905af70c2dfSkettenis if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
906af70c2dfSkettenis {
907af70c2dfSkettenis memset (&ps1, 0, sizeof (mbstate_t));
908af70c2dfSkettenis memset (&ps2, 0, sizeof (mbstate_t));
909af70c2dfSkettenis }
910af70c2dfSkettenis #endif
9111acd27e7Smillert if (_rl_completion_case_fold)
9121acd27e7Smillert {
9131acd27e7Smillert for (si = 0;
9141acd27e7Smillert (c1 = _rl_to_lower(match_list[i][si])) &&
9151acd27e7Smillert (c2 = _rl_to_lower(match_list[i + 1][si]));
9161acd27e7Smillert si++)
917af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
918af70c2dfSkettenis if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
919af70c2dfSkettenis {
920af70c2dfSkettenis v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
921af70c2dfSkettenis mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
922af70c2dfSkettenis wc1 = towlower (wc1);
923af70c2dfSkettenis wc2 = towlower (wc2);
924af70c2dfSkettenis if (wc1 != wc2)
925af70c2dfSkettenis break;
926af70c2dfSkettenis else if (v > 1)
927af70c2dfSkettenis si += v - 1;
928af70c2dfSkettenis }
929af70c2dfSkettenis else
930af70c2dfSkettenis #endif
9311acd27e7Smillert if (c1 != c2)
9321acd27e7Smillert break;
9331acd27e7Smillert }
9341acd27e7Smillert else
9351acd27e7Smillert {
9361acd27e7Smillert for (si = 0;
9371acd27e7Smillert (c1 = match_list[i][si]) &&
9381acd27e7Smillert (c2 = match_list[i + 1][si]);
9391acd27e7Smillert si++)
940af70c2dfSkettenis #if defined (HANDLE_MULTIBYTE)
941af70c2dfSkettenis if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
942af70c2dfSkettenis {
943af70c2dfSkettenis mbstate_t ps_back = ps1;
944af70c2dfSkettenis if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
945af70c2dfSkettenis break;
946af70c2dfSkettenis else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
947af70c2dfSkettenis si += v - 1;
948af70c2dfSkettenis }
949af70c2dfSkettenis else
950af70c2dfSkettenis #endif
9511acd27e7Smillert if (c1 != c2)
9521acd27e7Smillert break;
9531acd27e7Smillert }
9541acd27e7Smillert
9551acd27e7Smillert if (low > si)
9561acd27e7Smillert low = si;
9571acd27e7Smillert }
9581acd27e7Smillert
9591acd27e7Smillert /* If there were multiple matches, but none matched up to even the
9601acd27e7Smillert first character, and the user typed something, use that as the
9611acd27e7Smillert value of matches[0]. */
9621acd27e7Smillert if (low == 0 && text && *text)
9631acd27e7Smillert {
96463bef317Sbeck match_list[0] = strdup(text);
96563bef317Sbeck if (match_list[0] == NULL)
96663bef317Sbeck memory_error_and_abort("strdup");
9671acd27e7Smillert }
9681acd27e7Smillert else
9691acd27e7Smillert {
970af70c2dfSkettenis match_list[0] = (char *)xmalloc (low + 1);
971af70c2dfSkettenis
972af70c2dfSkettenis /* XXX - this might need changes in the presence of multibyte chars */
973af70c2dfSkettenis
974af70c2dfSkettenis /* If we are ignoring case, try to preserve the case of the string
975af70c2dfSkettenis the user typed in the face of multiple matches differing in case. */
976af70c2dfSkettenis if (_rl_completion_case_fold)
977af70c2dfSkettenis {
978af70c2dfSkettenis /* sort the list to get consistent answers. */
979af70c2dfSkettenis qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
980af70c2dfSkettenis
981af70c2dfSkettenis si = strlen (text);
982af70c2dfSkettenis if (si <= low)
983af70c2dfSkettenis {
984af70c2dfSkettenis for (i = 1; i <= matches; i++)
985af70c2dfSkettenis if (strncmp (match_list[i], text, si) == 0)
986af70c2dfSkettenis {
987af70c2dfSkettenis strncpy (match_list[0], match_list[i], low);
988af70c2dfSkettenis break;
989af70c2dfSkettenis }
990af70c2dfSkettenis /* no casematch, use first entry */
991af70c2dfSkettenis if (i > matches)
9921acd27e7Smillert strncpy (match_list[0], match_list[1], low);
993af70c2dfSkettenis }
994af70c2dfSkettenis else
995af70c2dfSkettenis /* otherwise, just use the text the user typed. */
996af70c2dfSkettenis strncpy (match_list[0], text, low);
997af70c2dfSkettenis }
998af70c2dfSkettenis else
999af70c2dfSkettenis strncpy (match_list[0], match_list[1], low);
1000af70c2dfSkettenis
10011acd27e7Smillert match_list[0][low] = '\0';
10021acd27e7Smillert }
10031acd27e7Smillert
10041acd27e7Smillert return matches;
10051acd27e7Smillert }
10061acd27e7Smillert
10071acd27e7Smillert static int
postprocess_matches(matchesp,matching_filenames)10081acd27e7Smillert postprocess_matches (matchesp, matching_filenames)
10091acd27e7Smillert char ***matchesp;
10101acd27e7Smillert int matching_filenames;
10111acd27e7Smillert {
10121acd27e7Smillert char *t, **matches, **temp_matches;
10131acd27e7Smillert int nmatch, i;
10141acd27e7Smillert
10151acd27e7Smillert matches = *matchesp;
10161acd27e7Smillert
1017af70c2dfSkettenis if (matches == 0)
1018af70c2dfSkettenis return 0;
1019af70c2dfSkettenis
10201acd27e7Smillert /* It seems to me that in all the cases we handle we would like
10211acd27e7Smillert to ignore duplicate possiblilities. Scan for the text to
10221acd27e7Smillert insert being identical to the other completions. */
10231acd27e7Smillert if (rl_ignore_completion_duplicates)
10241acd27e7Smillert {
10251acd27e7Smillert temp_matches = remove_duplicate_matches (matches);
10261acd27e7Smillert free (matches);
10271acd27e7Smillert matches = temp_matches;
10281acd27e7Smillert }
10291acd27e7Smillert
10301acd27e7Smillert /* If we are matching filenames, then here is our chance to
10311acd27e7Smillert do clever processing by re-examining the list. Call the
10321acd27e7Smillert ignore function with the array as a parameter. It can
10331acd27e7Smillert munge the array, deleting matches as it desires. */
10341acd27e7Smillert if (rl_ignore_some_completions_function && matching_filenames)
10351acd27e7Smillert {
10361acd27e7Smillert for (nmatch = 1; matches[nmatch]; nmatch++)
10371acd27e7Smillert ;
10381acd27e7Smillert (void)(*rl_ignore_some_completions_function) (matches);
10391acd27e7Smillert if (matches == 0 || matches[0] == 0)
10401acd27e7Smillert {
10411acd27e7Smillert FREE (matches);
10421acd27e7Smillert *matchesp = (char **)0;
10431acd27e7Smillert return 0;
10441acd27e7Smillert }
10451acd27e7Smillert else
10461acd27e7Smillert {
10471acd27e7Smillert /* If we removed some matches, recompute the common prefix. */
10481acd27e7Smillert for (i = 1; matches[i]; i++)
10491acd27e7Smillert ;
10501acd27e7Smillert if (i > 1 && i < nmatch)
10511acd27e7Smillert {
10521acd27e7Smillert t = matches[0];
10531acd27e7Smillert compute_lcd_of_matches (matches, i - 1, t);
10541acd27e7Smillert FREE (t);
10551acd27e7Smillert }
10561acd27e7Smillert }
10571acd27e7Smillert }
10581acd27e7Smillert
10591acd27e7Smillert *matchesp = matches;
10601acd27e7Smillert return (1);
10611acd27e7Smillert }
10621acd27e7Smillert
10631acd27e7Smillert /* A convenience function for displaying a list of strings in
10641acd27e7Smillert columnar format on readline's output stream. MATCHES is the list
10651acd27e7Smillert of strings, in argv format, LEN is the number of strings in MATCHES,
10661acd27e7Smillert and MAX is the length of the longest string in MATCHES. */
10671acd27e7Smillert void
rl_display_match_list(matches,len,max)10681acd27e7Smillert rl_display_match_list (matches, len, max)
10691acd27e7Smillert char **matches;
10701acd27e7Smillert int len, max;
10711acd27e7Smillert {
1072af70c2dfSkettenis int count, limit, printed_len, lines;
10731acd27e7Smillert int i, j, k, l;
10741acd27e7Smillert char *temp;
10751acd27e7Smillert
10761acd27e7Smillert /* How many items of MAX length can we fit in the screen window? */
10771acd27e7Smillert max += 2;
1078af70c2dfSkettenis limit = _rl_screenwidth / max;
1079af70c2dfSkettenis if (limit != 1 && (limit * max == _rl_screenwidth))
10801acd27e7Smillert limit--;
10811acd27e7Smillert
1082af70c2dfSkettenis /* Avoid a possible floating exception. If max > _rl_screenwidth,
10831acd27e7Smillert limit will be 0 and a divide-by-zero fault will result. */
10841acd27e7Smillert if (limit == 0)
10851acd27e7Smillert limit = 1;
10861acd27e7Smillert
10871acd27e7Smillert /* How many iterations of the printing loop? */
10881acd27e7Smillert count = (len + (limit - 1)) / limit;
10891acd27e7Smillert
10901acd27e7Smillert /* Watch out for special case. If LEN is less than LIMIT, then
10911acd27e7Smillert just do the inner printing loop.
10921acd27e7Smillert 0 < len <= limit implies count = 1. */
10931acd27e7Smillert
10941acd27e7Smillert /* Sort the items if they are not already sorted. */
10951acd27e7Smillert if (rl_ignore_completion_duplicates == 0)
10961acd27e7Smillert qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
10971acd27e7Smillert
1098af70c2dfSkettenis rl_crlf ();
10991acd27e7Smillert
1100af70c2dfSkettenis lines = 0;
11011acd27e7Smillert if (_rl_print_completions_horizontally == 0)
11021acd27e7Smillert {
11031acd27e7Smillert /* Print the sorted items, up-and-down alphabetically, like ls. */
11041acd27e7Smillert for (i = 1; i <= count; i++)
11051acd27e7Smillert {
11061acd27e7Smillert for (j = 0, l = i; j < limit; j++)
11071acd27e7Smillert {
11081acd27e7Smillert if (l > len || matches[l] == 0)
11091acd27e7Smillert break;
11101acd27e7Smillert else
11111acd27e7Smillert {
11121acd27e7Smillert temp = printable_part (matches[l]);
11131acd27e7Smillert printed_len = print_filename (temp, matches[l]);
11141acd27e7Smillert
11151acd27e7Smillert if (j + 1 < limit)
11161acd27e7Smillert for (k = 0; k < max - printed_len; k++)
11171acd27e7Smillert putc (' ', rl_outstream);
11181acd27e7Smillert }
11191acd27e7Smillert l += count;
11201acd27e7Smillert }
1121af70c2dfSkettenis rl_crlf ();
1122af70c2dfSkettenis lines++;
1123af70c2dfSkettenis if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
1124af70c2dfSkettenis {
1125af70c2dfSkettenis lines = _rl_internal_pager (lines);
1126af70c2dfSkettenis if (lines < 0)
1127af70c2dfSkettenis return;
1128af70c2dfSkettenis }
11291acd27e7Smillert }
11301acd27e7Smillert }
11311acd27e7Smillert else
11321acd27e7Smillert {
11331acd27e7Smillert /* Print the sorted items, across alphabetically, like ls -x. */
11341acd27e7Smillert for (i = 1; matches[i]; i++)
11351acd27e7Smillert {
11361acd27e7Smillert temp = printable_part (matches[i]);
11371acd27e7Smillert printed_len = print_filename (temp, matches[i]);
11381acd27e7Smillert /* Have we reached the end of this line? */
11391acd27e7Smillert if (matches[i+1])
11401acd27e7Smillert {
11411acd27e7Smillert if (i && (limit > 1) && (i % limit) == 0)
1142af70c2dfSkettenis {
1143af70c2dfSkettenis rl_crlf ();
1144af70c2dfSkettenis lines++;
1145af70c2dfSkettenis if (_rl_page_completions && lines >= _rl_screenheight - 1)
1146af70c2dfSkettenis {
1147af70c2dfSkettenis lines = _rl_internal_pager (lines);
1148af70c2dfSkettenis if (lines < 0)
1149af70c2dfSkettenis return;
1150af70c2dfSkettenis }
1151af70c2dfSkettenis }
11521acd27e7Smillert else
11531acd27e7Smillert for (k = 0; k < max - printed_len; k++)
11541acd27e7Smillert putc (' ', rl_outstream);
11551acd27e7Smillert }
11561acd27e7Smillert }
1157af70c2dfSkettenis rl_crlf ();
11581acd27e7Smillert }
11591acd27e7Smillert }
11601acd27e7Smillert
11611acd27e7Smillert /* Display MATCHES, a list of matching filenames in argv format. This
11621acd27e7Smillert handles the simple case -- a single match -- first. If there is more
11631acd27e7Smillert than one match, we compute the number of strings in the list and the
11641acd27e7Smillert length of the longest string, which will be needed by the display
11651acd27e7Smillert function. If the application wants to handle displaying the list of
11661acd27e7Smillert matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
11671acd27e7Smillert address of a function, and we just call it. If we're handling the
11681acd27e7Smillert display ourselves, we just call rl_display_match_list. We also check
11691acd27e7Smillert that the list of matches doesn't exceed the user-settable threshold,
11701acd27e7Smillert and ask the user if he wants to see the list if there are more matches
11711acd27e7Smillert than RL_COMPLETION_QUERY_ITEMS. */
11721acd27e7Smillert static void
display_matches(matches)11731acd27e7Smillert display_matches (matches)
11741acd27e7Smillert char **matches;
11751acd27e7Smillert {
11761acd27e7Smillert int len, max, i;
11771acd27e7Smillert char *temp;
11781acd27e7Smillert
11791acd27e7Smillert /* Move to the last visible line of a possibly-multiple-line command. */
11801acd27e7Smillert _rl_move_vert (_rl_vis_botlin);
11811acd27e7Smillert
11821acd27e7Smillert /* Handle simple case first. What if there is only one answer? */
11831acd27e7Smillert if (matches[1] == 0)
11841acd27e7Smillert {
11851acd27e7Smillert temp = printable_part (matches[0]);
1186af70c2dfSkettenis rl_crlf ();
11871acd27e7Smillert print_filename (temp, matches[0]);
1188af70c2dfSkettenis rl_crlf ();
11891acd27e7Smillert
11901acd27e7Smillert rl_forced_update_display ();
11911acd27e7Smillert rl_display_fixed = 1;
11921acd27e7Smillert
11931acd27e7Smillert return;
11941acd27e7Smillert }
11951acd27e7Smillert
11961acd27e7Smillert /* There is more than one answer. Find out how many there are,
11971acd27e7Smillert and find the maximum printed length of a single entry. */
11981acd27e7Smillert for (max = 0, i = 1; matches[i]; i++)
11991acd27e7Smillert {
12001acd27e7Smillert temp = printable_part (matches[i]);
12011acd27e7Smillert len = strlen (temp);
12021acd27e7Smillert
12031acd27e7Smillert if (len > max)
12041acd27e7Smillert max = len;
12051acd27e7Smillert }
12061acd27e7Smillert
12071acd27e7Smillert len = i - 1;
12081acd27e7Smillert
12091acd27e7Smillert /* If the caller has defined a display hook, then call that now. */
12101acd27e7Smillert if (rl_completion_display_matches_hook)
12111acd27e7Smillert {
12121acd27e7Smillert (*rl_completion_display_matches_hook) (matches, len, max);
12131acd27e7Smillert return;
12141acd27e7Smillert }
12151acd27e7Smillert
12161acd27e7Smillert /* If there are many items, then ask the user if she really wants to
12171acd27e7Smillert see them all. */
12181acd27e7Smillert if (len >= rl_completion_query_items)
12191acd27e7Smillert {
1220af70c2dfSkettenis rl_crlf ();
12211acd27e7Smillert fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
12221acd27e7Smillert fflush (rl_outstream);
1223af70c2dfSkettenis if (get_y_or_n (0) == 0)
12241acd27e7Smillert {
1225af70c2dfSkettenis rl_crlf ();
12261acd27e7Smillert
12271acd27e7Smillert rl_forced_update_display ();
12281acd27e7Smillert rl_display_fixed = 1;
12291acd27e7Smillert
12301acd27e7Smillert return;
12311acd27e7Smillert }
12321acd27e7Smillert }
12331acd27e7Smillert
12341acd27e7Smillert rl_display_match_list (matches, len, max);
12351acd27e7Smillert
12361acd27e7Smillert rl_forced_update_display ();
12371acd27e7Smillert rl_display_fixed = 1;
12381acd27e7Smillert }
12391acd27e7Smillert
12401acd27e7Smillert static char *
make_quoted_replacement(match,mtype,qc)12411acd27e7Smillert make_quoted_replacement (match, mtype, qc)
12421acd27e7Smillert char *match;
12431acd27e7Smillert int mtype;
12441acd27e7Smillert char *qc; /* Pointer to quoting character, if any */
12451acd27e7Smillert {
12461acd27e7Smillert int should_quote, do_replace;
12471acd27e7Smillert char *replacement;
12481acd27e7Smillert
12491acd27e7Smillert /* If we are doing completion on quoted substrings, and any matches
12501acd27e7Smillert contain any of the completer_word_break_characters, then auto-
12511acd27e7Smillert matically prepend the substring with a quote character (just pick
12521acd27e7Smillert the first one from the list of such) if it does not already begin
12531acd27e7Smillert with a quote string. FIXME: Need to remove any such automatically
12541acd27e7Smillert inserted quote character when it no longer is necessary, such as
12551acd27e7Smillert if we change the string we are completing on and the new set of
12561acd27e7Smillert matches don't require a quoted substring. */
12571acd27e7Smillert replacement = match;
12581acd27e7Smillert
12591acd27e7Smillert should_quote = match && rl_completer_quote_characters &&
12601acd27e7Smillert rl_filename_completion_desired &&
12611acd27e7Smillert rl_filename_quoting_desired;
12621acd27e7Smillert
12631acd27e7Smillert if (should_quote)
12641acd27e7Smillert should_quote = should_quote && (!qc || !*qc ||
12651acd27e7Smillert (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
12661acd27e7Smillert
12671acd27e7Smillert if (should_quote)
12681acd27e7Smillert {
12691acd27e7Smillert /* If there is a single match, see if we need to quote it.
12701acd27e7Smillert This also checks whether the common prefix of several
12711acd27e7Smillert matches needs to be quoted. */
12721acd27e7Smillert should_quote = rl_filename_quote_characters
1273af70c2dfSkettenis ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
12741acd27e7Smillert : 0;
12751acd27e7Smillert
12761acd27e7Smillert do_replace = should_quote ? mtype : NO_MATCH;
12771acd27e7Smillert /* Quote the replacement, since we found an embedded
12781acd27e7Smillert word break character in a potential match. */
12791acd27e7Smillert if (do_replace != NO_MATCH && rl_filename_quoting_function)
12801acd27e7Smillert replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
12811acd27e7Smillert }
12821acd27e7Smillert return (replacement);
12831acd27e7Smillert }
12841acd27e7Smillert
12851acd27e7Smillert static void
insert_match(match,start,mtype,qc)12861acd27e7Smillert insert_match (match, start, mtype, qc)
12871acd27e7Smillert char *match;
12881acd27e7Smillert int start, mtype;
12891acd27e7Smillert char *qc;
12901acd27e7Smillert {
12911acd27e7Smillert char *replacement;
12921acd27e7Smillert char oqc;
12931acd27e7Smillert
12941acd27e7Smillert oqc = qc ? *qc : '\0';
12951acd27e7Smillert replacement = make_quoted_replacement (match, mtype, qc);
12961acd27e7Smillert
12971acd27e7Smillert /* Now insert the match. */
12981acd27e7Smillert if (replacement)
12991acd27e7Smillert {
13001acd27e7Smillert /* Don't double an opening quote character. */
13011acd27e7Smillert if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
13021acd27e7Smillert replacement[0] == *qc)
13031acd27e7Smillert start--;
13041acd27e7Smillert /* If make_quoted_replacement changed the quoting character, remove
13051acd27e7Smillert the opening quote and insert the (fully-quoted) replacement. */
13061acd27e7Smillert else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
13071acd27e7Smillert replacement[0] != oqc)
13081acd27e7Smillert start--;
13091acd27e7Smillert _rl_replace_text (replacement, start, rl_point - 1);
13101acd27e7Smillert if (replacement != match)
13111acd27e7Smillert free (replacement);
13121acd27e7Smillert }
13131acd27e7Smillert }
13141acd27e7Smillert
13151acd27e7Smillert /* Append any necessary closing quote and a separator character to the
13161acd27e7Smillert just-inserted match. If the user has specified that directories
13171acd27e7Smillert should be marked by a trailing `/', append one of those instead. The
13181acd27e7Smillert default trailing character is a space. Returns the number of characters
1319af70c2dfSkettenis appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
1320af70c2dfSkettenis has them) and don't add a suffix for a symlink to a directory. A
1321af70c2dfSkettenis nontrivial match is one that actually adds to the word being completed.
1322af70c2dfSkettenis The variable rl_completion_mark_symlink_dirs controls this behavior
1323af70c2dfSkettenis (it's initially set to the what the user has chosen, indicated by the
1324af70c2dfSkettenis value of _rl_complete_mark_symlink_dirs, but may be modified by an
1325af70c2dfSkettenis application's completion function). */
13261acd27e7Smillert static int
append_to_match(text,delimiter,quote_char,nontrivial_match)1327af70c2dfSkettenis append_to_match (text, delimiter, quote_char, nontrivial_match)
13281acd27e7Smillert char *text;
1329af70c2dfSkettenis int delimiter, quote_char, nontrivial_match;
13301acd27e7Smillert {
13311acd27e7Smillert char temp_string[4], *filename;
1332af70c2dfSkettenis int temp_string_index, s;
13331acd27e7Smillert struct stat finfo;
13341acd27e7Smillert
13351acd27e7Smillert temp_string_index = 0;
13361acd27e7Smillert if (quote_char && rl_point && rl_line_buffer[rl_point - 1] != quote_char)
13371acd27e7Smillert temp_string[temp_string_index++] = quote_char;
13381acd27e7Smillert
13391acd27e7Smillert if (delimiter)
13401acd27e7Smillert temp_string[temp_string_index++] = delimiter;
1341af70c2dfSkettenis else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
13421acd27e7Smillert temp_string[temp_string_index++] = rl_completion_append_character;
13431acd27e7Smillert
13441acd27e7Smillert temp_string[temp_string_index++] = '\0';
13451acd27e7Smillert
13461acd27e7Smillert if (rl_filename_completion_desired)
13471acd27e7Smillert {
13481acd27e7Smillert filename = tilde_expand (text);
1349af70c2dfSkettenis s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
1350af70c2dfSkettenis ? LSTAT (filename, &finfo)
1351af70c2dfSkettenis : stat (filename, &finfo);
1352af70c2dfSkettenis if (s == 0 && S_ISDIR (finfo.st_mode))
13531acd27e7Smillert {
1354af70c2dfSkettenis if (_rl_complete_mark_directories)
1355af70c2dfSkettenis {
1356af70c2dfSkettenis /* This is clumsy. Avoid putting in a double slash if point
1357af70c2dfSkettenis is at the end of the line and the previous character is a
1358af70c2dfSkettenis slash. */
1359af70c2dfSkettenis if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
1360af70c2dfSkettenis ;
1361af70c2dfSkettenis else if (rl_line_buffer[rl_point] != '/')
13621acd27e7Smillert rl_insert_text ("/");
13631acd27e7Smillert }
1364af70c2dfSkettenis }
1365af70c2dfSkettenis #ifdef S_ISLNK
1366af70c2dfSkettenis /* Don't add anything if the filename is a symlink and resolves to a
1367af70c2dfSkettenis directory. */
1368af70c2dfSkettenis else if (s == 0 && S_ISLNK (finfo.st_mode) &&
1369af70c2dfSkettenis stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
1370af70c2dfSkettenis ;
1371af70c2dfSkettenis #endif
13721acd27e7Smillert else
13731acd27e7Smillert {
1374af70c2dfSkettenis if (rl_point == rl_end && temp_string_index)
13751acd27e7Smillert rl_insert_text (temp_string);
13761acd27e7Smillert }
13771acd27e7Smillert free (filename);
13781acd27e7Smillert }
13791acd27e7Smillert else
13801acd27e7Smillert {
1381af70c2dfSkettenis if (rl_point == rl_end && temp_string_index)
13821acd27e7Smillert rl_insert_text (temp_string);
13831acd27e7Smillert }
13841acd27e7Smillert
13851acd27e7Smillert return (temp_string_index);
13861acd27e7Smillert }
13871acd27e7Smillert
13881acd27e7Smillert static void
insert_all_matches(matches,point,qc)13891acd27e7Smillert insert_all_matches (matches, point, qc)
13901acd27e7Smillert char **matches;
13911acd27e7Smillert int point;
13921acd27e7Smillert char *qc;
13931acd27e7Smillert {
13941acd27e7Smillert int i;
13951acd27e7Smillert char *rp;
13961acd27e7Smillert
13971acd27e7Smillert rl_begin_undo_group ();
13981acd27e7Smillert /* remove any opening quote character; make_quoted_replacement will add
13991acd27e7Smillert it back. */
14001acd27e7Smillert if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
14011acd27e7Smillert point--;
14021acd27e7Smillert rl_delete_text (point, rl_point);
14031acd27e7Smillert rl_point = point;
14041acd27e7Smillert
14051acd27e7Smillert if (matches[1])
14061acd27e7Smillert {
14071acd27e7Smillert for (i = 1; matches[i]; i++)
14081acd27e7Smillert {
14091acd27e7Smillert rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
14101acd27e7Smillert rl_insert_text (rp);
14111acd27e7Smillert rl_insert_text (" ");
14121acd27e7Smillert if (rp != matches[i])
14131acd27e7Smillert free (rp);
14141acd27e7Smillert }
14151acd27e7Smillert }
14161acd27e7Smillert else
14171acd27e7Smillert {
14181acd27e7Smillert rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
14191acd27e7Smillert rl_insert_text (rp);
14201acd27e7Smillert rl_insert_text (" ");
14211acd27e7Smillert if (rp != matches[0])
14221acd27e7Smillert free (rp);
14231acd27e7Smillert }
14241acd27e7Smillert rl_end_undo_group ();
14251acd27e7Smillert }
14261acd27e7Smillert
1427af70c2dfSkettenis void
_rl_free_match_list(matches)1428af70c2dfSkettenis _rl_free_match_list (matches)
14291acd27e7Smillert char **matches;
14301acd27e7Smillert {
14311acd27e7Smillert register int i;
14321acd27e7Smillert
1433af70c2dfSkettenis if (matches == 0)
1434af70c2dfSkettenis return;
1435af70c2dfSkettenis
14361acd27e7Smillert for (i = 0; matches[i]; i++)
14371acd27e7Smillert free (matches[i]);
14381acd27e7Smillert free (matches);
14391acd27e7Smillert }
14401acd27e7Smillert
14411acd27e7Smillert /* Complete the word at or before point.
14421acd27e7Smillert WHAT_TO_DO says what to do with the completion.
14431acd27e7Smillert `?' means list the possible completions.
14441acd27e7Smillert TAB means do standard completion.
14451acd27e7Smillert `*' means insert all of the possible completions.
14461acd27e7Smillert `!' means to do standard completion, and list all possible completions if
14471acd27e7Smillert there is more than one. */
14481acd27e7Smillert int
rl_complete_internal(what_to_do)14491acd27e7Smillert rl_complete_internal (what_to_do)
14501acd27e7Smillert int what_to_do;
14511acd27e7Smillert {
14521acd27e7Smillert char **matches;
1453af70c2dfSkettenis rl_compentry_func_t *our_func;
1454af70c2dfSkettenis int start, end, delimiter, found_quote, i, nontrivial_lcd;
14551acd27e7Smillert char *text, *saved_line_buffer;
14561acd27e7Smillert char quote_char;
14571acd27e7Smillert
1458af70c2dfSkettenis RL_SETSTATE(RL_STATE_COMPLETING);
1459af70c2dfSkettenis
1460af70c2dfSkettenis set_completion_defaults (what_to_do);
14611acd27e7Smillert
14621acd27e7Smillert saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
14631acd27e7Smillert our_func = rl_completion_entry_function
14641acd27e7Smillert ? rl_completion_entry_function
1465af70c2dfSkettenis : rl_filename_completion_function;
14661acd27e7Smillert
14671acd27e7Smillert /* We now look backwards for the start of a filename/variable word. */
14681acd27e7Smillert end = rl_point;
14691acd27e7Smillert found_quote = delimiter = 0;
14701acd27e7Smillert quote_char = '\0';
14711acd27e7Smillert
14721acd27e7Smillert if (rl_point)
14731acd27e7Smillert /* This (possibly) changes rl_point. If it returns a non-zero char,
14741acd27e7Smillert we know we have an open quote. */
1475af70c2dfSkettenis quote_char = _rl_find_completion_word (&found_quote, &delimiter);
14761acd27e7Smillert
14771acd27e7Smillert start = rl_point;
14781acd27e7Smillert rl_point = end;
14791acd27e7Smillert
14801acd27e7Smillert text = rl_copy_text (start, end);
14811acd27e7Smillert matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
1482af70c2dfSkettenis /* nontrivial_lcd is set if the common prefix adds something to the word
1483af70c2dfSkettenis being completed. */
1484af70c2dfSkettenis nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
14851acd27e7Smillert free (text);
14861acd27e7Smillert
14871acd27e7Smillert if (matches == 0)
14881acd27e7Smillert {
1489af70c2dfSkettenis rl_ding ();
14901acd27e7Smillert FREE (saved_line_buffer);
1491af70c2dfSkettenis completion_changed_buffer = 0;
1492af70c2dfSkettenis RL_UNSETSTATE(RL_STATE_COMPLETING);
14931acd27e7Smillert return (0);
14941acd27e7Smillert }
14951acd27e7Smillert
14961acd27e7Smillert /* If we are matching filenames, the attempted completion function will
14971acd27e7Smillert have set rl_filename_completion_desired to a non-zero value. The basic
1498af70c2dfSkettenis rl_filename_completion_function does this. */
14991acd27e7Smillert i = rl_filename_completion_desired;
15001acd27e7Smillert
15011acd27e7Smillert if (postprocess_matches (&matches, i) == 0)
15021acd27e7Smillert {
1503af70c2dfSkettenis rl_ding ();
15041acd27e7Smillert FREE (saved_line_buffer);
15051acd27e7Smillert completion_changed_buffer = 0;
1506af70c2dfSkettenis RL_UNSETSTATE(RL_STATE_COMPLETING);
15071acd27e7Smillert return (0);
15081acd27e7Smillert }
15091acd27e7Smillert
15101acd27e7Smillert switch (what_to_do)
15111acd27e7Smillert {
15121acd27e7Smillert case TAB:
15131acd27e7Smillert case '!':
15141acd27e7Smillert /* Insert the first match with proper quoting. */
15151acd27e7Smillert if (*matches[0])
15161acd27e7Smillert insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
15171acd27e7Smillert
15181acd27e7Smillert /* If there are more matches, ring the bell to indicate.
15191acd27e7Smillert If we are in vi mode, Posix.2 says to not ring the bell.
15201acd27e7Smillert If the `show-all-if-ambiguous' variable is set, display
15211acd27e7Smillert all the matches immediately. Otherwise, if this was the
15221acd27e7Smillert only match, and we are hacking files, check the file to
15231acd27e7Smillert see if it was a directory. If so, and the `mark-directories'
15241acd27e7Smillert variable is set, add a '/' to the name. If not, and we
15251acd27e7Smillert are at the end of the line, then add a space. */
15261acd27e7Smillert if (matches[1])
15271acd27e7Smillert {
15281acd27e7Smillert if (what_to_do == '!')
15291acd27e7Smillert {
15301acd27e7Smillert display_matches (matches);
15311acd27e7Smillert break;
15321acd27e7Smillert }
15331acd27e7Smillert else if (rl_editing_mode != vi_mode)
1534af70c2dfSkettenis rl_ding (); /* There are other matches remaining. */
15351acd27e7Smillert }
15361acd27e7Smillert else
1537af70c2dfSkettenis append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
15381acd27e7Smillert
15391acd27e7Smillert break;
15401acd27e7Smillert
15411acd27e7Smillert case '*':
15421acd27e7Smillert insert_all_matches (matches, start, "e_char);
15431acd27e7Smillert break;
15441acd27e7Smillert
15451acd27e7Smillert case '?':
15461acd27e7Smillert display_matches (matches);
15471acd27e7Smillert break;
15481acd27e7Smillert
15491acd27e7Smillert default:
15501acd27e7Smillert fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
1551af70c2dfSkettenis rl_ding ();
15521acd27e7Smillert FREE (saved_line_buffer);
1553af70c2dfSkettenis RL_UNSETSTATE(RL_STATE_COMPLETING);
15541acd27e7Smillert return 1;
15551acd27e7Smillert }
15561acd27e7Smillert
1557af70c2dfSkettenis _rl_free_match_list (matches);
15581acd27e7Smillert
15591acd27e7Smillert /* Check to see if the line has changed through all of this manipulation. */
15601acd27e7Smillert if (saved_line_buffer)
15611acd27e7Smillert {
15621acd27e7Smillert completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
15631acd27e7Smillert free (saved_line_buffer);
15641acd27e7Smillert }
15651acd27e7Smillert
1566af70c2dfSkettenis RL_UNSETSTATE(RL_STATE_COMPLETING);
15671acd27e7Smillert return 0;
15681acd27e7Smillert }
15691acd27e7Smillert
15701acd27e7Smillert /***************************************************************/
15711acd27e7Smillert /* */
15721acd27e7Smillert /* Application-callable completion match generator functions */
15731acd27e7Smillert /* */
15741acd27e7Smillert /***************************************************************/
15751acd27e7Smillert
15761acd27e7Smillert /* Return an array of (char *) which is a list of completions for TEXT.
15771acd27e7Smillert If there are no completions, return a NULL pointer.
15781acd27e7Smillert The first entry in the returned array is the substitution for TEXT.
15791acd27e7Smillert The remaining entries are the possible completions.
15801acd27e7Smillert The array is terminated with a NULL pointer.
15811acd27e7Smillert
15821acd27e7Smillert ENTRY_FUNCTION is a function of two args, and returns a (char *).
15831acd27e7Smillert The first argument is TEXT.
15841acd27e7Smillert The second is a state argument; it should be zero on the first call, and
15851acd27e7Smillert non-zero on subsequent calls. It returns a NULL pointer to the caller
15861acd27e7Smillert when there are no more matches.
15871acd27e7Smillert */
15881acd27e7Smillert char **
rl_completion_matches(text,entry_function)1589af70c2dfSkettenis rl_completion_matches (text, entry_function)
1590af70c2dfSkettenis const char *text;
1591af70c2dfSkettenis rl_compentry_func_t *entry_function;
15921acd27e7Smillert {
15931acd27e7Smillert /* Number of slots in match_list. */
15941acd27e7Smillert int match_list_size;
15951acd27e7Smillert
15961acd27e7Smillert /* The list of matches. */
15971acd27e7Smillert char **match_list;
15981acd27e7Smillert
15991acd27e7Smillert /* Number of matches actually found. */
16001acd27e7Smillert int matches;
16011acd27e7Smillert
16021acd27e7Smillert /* Temporary string binder. */
16031acd27e7Smillert char *string;
16041acd27e7Smillert
16051acd27e7Smillert matches = 0;
16061acd27e7Smillert match_list_size = 10;
16071acd27e7Smillert match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
16081acd27e7Smillert match_list[1] = (char *)NULL;
16091acd27e7Smillert
1610*af1e7b8cSkrw while ((string = (*entry_function) (text, matches)))
16111acd27e7Smillert {
16121acd27e7Smillert if (matches + 1 == match_list_size)
16131acd27e7Smillert match_list = (char **)xrealloc
16141acd27e7Smillert (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
16151acd27e7Smillert
16161acd27e7Smillert match_list[++matches] = string;
16171acd27e7Smillert match_list[matches + 1] = (char *)NULL;
16181acd27e7Smillert }
16191acd27e7Smillert
16201acd27e7Smillert /* If there were any matches, then look through them finding out the
16211acd27e7Smillert lowest common denominator. That then becomes match_list[0]. */
16221acd27e7Smillert if (matches)
16231acd27e7Smillert compute_lcd_of_matches (match_list, matches, text);
16241acd27e7Smillert else /* There were no matches. */
16251acd27e7Smillert {
16261acd27e7Smillert free (match_list);
16271acd27e7Smillert match_list = (char **)NULL;
16281acd27e7Smillert }
16291acd27e7Smillert return (match_list);
16301acd27e7Smillert }
16311acd27e7Smillert
16321acd27e7Smillert /* A completion function for usernames.
16331acd27e7Smillert TEXT contains a partial username preceded by a random
16341acd27e7Smillert character (usually `~'). */
16351acd27e7Smillert char *
rl_username_completion_function(text,state)1636af70c2dfSkettenis rl_username_completion_function (text, state)
1637af70c2dfSkettenis const char *text;
16381acd27e7Smillert int state;
16391acd27e7Smillert {
16401acd27e7Smillert #if defined (__WIN32__) || defined (__OPENNT)
16411acd27e7Smillert return (char *)NULL;
16421acd27e7Smillert #else /* !__WIN32__ && !__OPENNT) */
16431acd27e7Smillert static char *username = (char *)NULL;
16441acd27e7Smillert static struct passwd *entry;
16451acd27e7Smillert static int namelen, first_char, first_char_loc;
16461acd27e7Smillert char *value;
16471acd27e7Smillert
16481acd27e7Smillert if (state == 0)
16491acd27e7Smillert {
16501acd27e7Smillert FREE (username);
16511acd27e7Smillert
16521acd27e7Smillert first_char = *text;
16531acd27e7Smillert first_char_loc = first_char == '~';
16541acd27e7Smillert
16551acd27e7Smillert username = savestring (&text[first_char_loc]);
16561acd27e7Smillert namelen = strlen (username);
16571acd27e7Smillert setpwent ();
16581acd27e7Smillert }
16591acd27e7Smillert
1660*af1e7b8cSkrw while ((entry = getpwent ()))
16611acd27e7Smillert {
16621acd27e7Smillert /* Null usernames should result in all users as possible completions. */
16631acd27e7Smillert if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
16641acd27e7Smillert break;
16651acd27e7Smillert }
16661acd27e7Smillert
16671acd27e7Smillert if (entry == 0)
16681acd27e7Smillert {
16691acd27e7Smillert endpwent ();
16701acd27e7Smillert return ((char *)NULL);
16711acd27e7Smillert }
16721acd27e7Smillert else
16731acd27e7Smillert {
167463bef317Sbeck int len = 2 + strlen(entry->pw_name);
1675af70c2dfSkettenis value = (char *)xmalloc (len);
16761acd27e7Smillert
16771acd27e7Smillert *value = *text;
16781acd27e7Smillert
167963bef317Sbeck strlcpy (value + first_char_loc, entry->pw_name, len - first_char_loc);
16801acd27e7Smillert
16811acd27e7Smillert if (first_char == '~')
16821acd27e7Smillert rl_filename_completion_desired = 1;
16831acd27e7Smillert
16841acd27e7Smillert return (value);
16851acd27e7Smillert }
16861acd27e7Smillert #endif /* !__WIN32__ && !__OPENNT */
16871acd27e7Smillert }
16881acd27e7Smillert
16891acd27e7Smillert /* Okay, now we write the entry_function for filename completion. In the
16901acd27e7Smillert general case. Note that completion in the shell is a little different
16911acd27e7Smillert because of all the pathnames that must be followed when looking up the
16921acd27e7Smillert completion for a command. */
16931acd27e7Smillert char *
rl_filename_completion_function(text,state)1694af70c2dfSkettenis rl_filename_completion_function (text, state)
1695af70c2dfSkettenis const char *text;
16961acd27e7Smillert int state;
16971acd27e7Smillert {
16981acd27e7Smillert static DIR *directory = (DIR *)NULL;
16991acd27e7Smillert static char *filename = (char *)NULL;
17001acd27e7Smillert static char *dirname = (char *)NULL;
17011acd27e7Smillert static char *users_dirname = (char *)NULL;
17021acd27e7Smillert static int filename_len;
17031acd27e7Smillert char *temp;
17041acd27e7Smillert int dirlen;
17051acd27e7Smillert struct dirent *entry;
17061acd27e7Smillert
17071acd27e7Smillert /* If we don't have any state, then do some initialization. */
17081acd27e7Smillert if (state == 0)
17091acd27e7Smillert {
17101acd27e7Smillert /* If we were interrupted before closing the directory or reading
17111acd27e7Smillert all of its contents, close it. */
17121acd27e7Smillert if (directory)
17131acd27e7Smillert {
17141acd27e7Smillert closedir (directory);
17151acd27e7Smillert directory = (DIR *)NULL;
17161acd27e7Smillert }
17171acd27e7Smillert FREE (dirname);
17181acd27e7Smillert FREE (filename);
17191acd27e7Smillert FREE (users_dirname);
17201acd27e7Smillert
17211acd27e7Smillert filename = savestring (text);
172200d4b8aeStedu filename_len = strlen(filename) + 1;
17231acd27e7Smillert if (*text == 0)
17241acd27e7Smillert text = ".";
17251acd27e7Smillert dirname = savestring (text);
17261acd27e7Smillert
17271acd27e7Smillert temp = strrchr (dirname, '/');
17281acd27e7Smillert
17291acd27e7Smillert #if defined (__MSDOS__)
17301acd27e7Smillert /* special hack for //X/... */
1731af70c2dfSkettenis if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
17321acd27e7Smillert temp = strrchr (dirname + 3, '/');
17331acd27e7Smillert #endif
17341acd27e7Smillert
17351acd27e7Smillert if (temp)
17361acd27e7Smillert {
173763bef317Sbeck strlcpy (filename, ++temp, filename_len);
17381acd27e7Smillert *temp = '\0';
17391acd27e7Smillert }
17401acd27e7Smillert #if defined (__MSDOS__)
17411acd27e7Smillert /* searches from current directory on the drive */
1742af70c2dfSkettenis else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
17431acd27e7Smillert {
174463bef317Sbeck /* XXX DOS strlcpy anyone? */
174563bef317Sbeck strlcpy (filename, dirname + 2, filename_len);
17461acd27e7Smillert dirname[2] = '\0';
17471acd27e7Smillert }
17481acd27e7Smillert #endif
17491acd27e7Smillert else
17501acd27e7Smillert {
17511acd27e7Smillert dirname[0] = '.';
17521acd27e7Smillert dirname[1] = '\0';
17531acd27e7Smillert }
17541acd27e7Smillert
17551acd27e7Smillert /* We aren't done yet. We also support the "~user" syntax. */
17561acd27e7Smillert
17571acd27e7Smillert /* Save the version of the directory that the user typed. */
17581acd27e7Smillert users_dirname = savestring (dirname);
17591acd27e7Smillert
17601acd27e7Smillert if (*dirname == '~')
17611acd27e7Smillert {
17621acd27e7Smillert temp = tilde_expand (dirname);
17631acd27e7Smillert free (dirname);
17641acd27e7Smillert dirname = temp;
17651acd27e7Smillert }
17661acd27e7Smillert
1767af70c2dfSkettenis if (rl_directory_rewrite_hook)
1768af70c2dfSkettenis (*rl_directory_rewrite_hook) (&dirname);
1769af70c2dfSkettenis
17701acd27e7Smillert if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
17711acd27e7Smillert {
17721acd27e7Smillert free (users_dirname);
17731acd27e7Smillert users_dirname = savestring (dirname);
17741acd27e7Smillert }
17751acd27e7Smillert
17761acd27e7Smillert directory = opendir (dirname);
17771acd27e7Smillert filename_len = strlen (filename);
17781acd27e7Smillert
17791acd27e7Smillert rl_filename_completion_desired = 1;
17801acd27e7Smillert }
17811acd27e7Smillert
17821acd27e7Smillert /* At this point we should entertain the possibility of hacking wildcarded
17831acd27e7Smillert filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
17841acd27e7Smillert contains globbing characters, then build an array of directories, and
17851acd27e7Smillert then map over that list while completing. */
17861acd27e7Smillert /* *** UNIMPLEMENTED *** */
17871acd27e7Smillert
17881acd27e7Smillert /* Now that we have some state, we can read the directory. */
17891acd27e7Smillert
17901acd27e7Smillert entry = (struct dirent *)NULL;
17911acd27e7Smillert while (directory && (entry = readdir (directory)))
17921acd27e7Smillert {
1793af70c2dfSkettenis /* Special case for no filename. If the user has disabled the
1794af70c2dfSkettenis `match-hidden-files' variable, skip filenames beginning with `.'.
1795af70c2dfSkettenis All other entries except "." and ".." match. */
17961acd27e7Smillert if (filename_len == 0)
17971acd27e7Smillert {
1798af70c2dfSkettenis if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name))
1799af70c2dfSkettenis continue;
1800af70c2dfSkettenis
18011acd27e7Smillert if (entry->d_name[0] != '.' ||
18021acd27e7Smillert (entry->d_name[1] &&
18031acd27e7Smillert (entry->d_name[1] != '.' || entry->d_name[2])))
18041acd27e7Smillert break;
18051acd27e7Smillert }
18061acd27e7Smillert else
18071acd27e7Smillert {
18081acd27e7Smillert /* Otherwise, if these match up to the length of filename, then
18091acd27e7Smillert it is a match. */
18101acd27e7Smillert if (_rl_completion_case_fold)
18111acd27e7Smillert {
18121acd27e7Smillert if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
18131acd27e7Smillert (((int)D_NAMLEN (entry)) >= filename_len) &&
18141acd27e7Smillert (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
18151acd27e7Smillert break;
18161acd27e7Smillert }
18171acd27e7Smillert else
18181acd27e7Smillert {
18191acd27e7Smillert if ((entry->d_name[0] == filename[0]) &&
18201acd27e7Smillert (((int)D_NAMLEN (entry)) >= filename_len) &&
18211acd27e7Smillert (strncmp (filename, entry->d_name, filename_len) == 0))
18221acd27e7Smillert break;
18231acd27e7Smillert }
18241acd27e7Smillert }
18251acd27e7Smillert }
18261acd27e7Smillert
18271acd27e7Smillert if (entry == 0)
18281acd27e7Smillert {
18291acd27e7Smillert if (directory)
18301acd27e7Smillert {
18311acd27e7Smillert closedir (directory);
18321acd27e7Smillert directory = (DIR *)NULL;
18331acd27e7Smillert }
18341acd27e7Smillert if (dirname)
18351acd27e7Smillert {
18361acd27e7Smillert free (dirname);
18371acd27e7Smillert dirname = (char *)NULL;
18381acd27e7Smillert }
18391acd27e7Smillert if (filename)
18401acd27e7Smillert {
18411acd27e7Smillert free (filename);
18421acd27e7Smillert filename = (char *)NULL;
18431acd27e7Smillert }
18441acd27e7Smillert if (users_dirname)
18451acd27e7Smillert {
18461acd27e7Smillert free (users_dirname);
18471acd27e7Smillert users_dirname = (char *)NULL;
18481acd27e7Smillert }
18491acd27e7Smillert
18501acd27e7Smillert return (char *)NULL;
18511acd27e7Smillert }
18521acd27e7Smillert else
18531acd27e7Smillert {
18541acd27e7Smillert /* dirname && (strcmp (dirname, ".") != 0) */
18551acd27e7Smillert if (dirname && (dirname[0] != '.' || dirname[1]))
18561acd27e7Smillert {
185763bef317Sbeck int templen;
18581acd27e7Smillert if (rl_complete_with_tilde_expansion && *users_dirname == '~')
18591acd27e7Smillert {
18601acd27e7Smillert dirlen = strlen (dirname);
186163bef317Sbeck templen = 2 + dirlen + D_NAMLEN (entry);
1862af70c2dfSkettenis temp = (char *)xmalloc (templen);
186363bef317Sbeck strlcpy (temp, dirname, templen);
18641acd27e7Smillert /* Canonicalization cuts off any final slash present. We
18651acd27e7Smillert may need to add it back. */
18661acd27e7Smillert if (dirname[dirlen - 1] != '/')
18671acd27e7Smillert {
18681acd27e7Smillert temp[dirlen++] = '/';
18691acd27e7Smillert temp[dirlen] = '\0';
18701acd27e7Smillert }
18711acd27e7Smillert }
18721acd27e7Smillert else
18731acd27e7Smillert {
18741acd27e7Smillert dirlen = strlen (users_dirname);
1875af70c2dfSkettenis templen = 2 + dirlen + D_NAMLEN (entry);
1876af70c2dfSkettenis temp = (char *)xmalloc (templen);
187763bef317Sbeck strlcpy (temp, users_dirname, templen);
1878af70c2dfSkettenis /* Make sure that temp has a trailing slash here. */
1879af70c2dfSkettenis if (users_dirname[dirlen - 1] != '/')
1880af70c2dfSkettenis {
1881af70c2dfSkettenis temp[dirlen++] = '/';
1882af70c2dfSkettenis temp[dirlen] = '\0';
1883af70c2dfSkettenis }
18841acd27e7Smillert }
18851acd27e7Smillert
188663bef317Sbeck strlcat (temp, entry->d_name, templen);
18871acd27e7Smillert }
18881acd27e7Smillert else
18891acd27e7Smillert temp = savestring (entry->d_name);
18901acd27e7Smillert
18911acd27e7Smillert return (temp);
18921acd27e7Smillert }
18931acd27e7Smillert }
18941acd27e7Smillert
18951acd27e7Smillert /* An initial implementation of a menu completion function a la tcsh. The
18961acd27e7Smillert first time (if the last readline command was not rl_menu_complete), we
18971acd27e7Smillert generate the list of matches. This code is very similar to the code in
18981acd27e7Smillert rl_complete_internal -- there should be a way to combine the two. Then,
18991acd27e7Smillert for each item in the list of matches, we insert the match in an undoable
19001acd27e7Smillert fashion, with the appropriate character appended (this happens on the
19011acd27e7Smillert second and subsequent consecutive calls to rl_menu_complete). When we
19021acd27e7Smillert hit the end of the match list, we restore the original unmatched text,
19031acd27e7Smillert ring the bell, and reset the counter to zero. */
19041acd27e7Smillert int
rl_menu_complete(count,ignore)19051acd27e7Smillert rl_menu_complete (count, ignore)
19061acd27e7Smillert int count, ignore;
19071acd27e7Smillert {
1908af70c2dfSkettenis rl_compentry_func_t *our_func;
19091acd27e7Smillert int matching_filenames, found_quote;
19101acd27e7Smillert
19111acd27e7Smillert static char *orig_text;
19121acd27e7Smillert static char **matches = (char **)0;
19131acd27e7Smillert static int match_list_index = 0;
19141acd27e7Smillert static int match_list_size = 0;
19151acd27e7Smillert static int orig_start, orig_end;
19161acd27e7Smillert static char quote_char;
19171acd27e7Smillert static int delimiter;
19181acd27e7Smillert
19191acd27e7Smillert /* The first time through, we generate the list of matches and set things
19201acd27e7Smillert up to insert them. */
19211acd27e7Smillert if (rl_last_func != rl_menu_complete)
19221acd27e7Smillert {
19231acd27e7Smillert /* Clean up from previous call, if any. */
19241acd27e7Smillert FREE (orig_text);
19251acd27e7Smillert if (matches)
1926af70c2dfSkettenis _rl_free_match_list (matches);
19271acd27e7Smillert
19281acd27e7Smillert match_list_index = match_list_size = 0;
19291acd27e7Smillert matches = (char **)NULL;
19301acd27e7Smillert
19311acd27e7Smillert /* Only the completion entry function can change these. */
1932af70c2dfSkettenis set_completion_defaults ('%');
19331acd27e7Smillert
19341acd27e7Smillert our_func = rl_completion_entry_function
19351acd27e7Smillert ? rl_completion_entry_function
1936af70c2dfSkettenis : rl_filename_completion_function;
19371acd27e7Smillert
19381acd27e7Smillert /* We now look backwards for the start of a filename/variable word. */
19391acd27e7Smillert orig_end = rl_point;
19401acd27e7Smillert found_quote = delimiter = 0;
19411acd27e7Smillert quote_char = '\0';
19421acd27e7Smillert
19431acd27e7Smillert if (rl_point)
19441acd27e7Smillert /* This (possibly) changes rl_point. If it returns a non-zero char,
19451acd27e7Smillert we know we have an open quote. */
1946af70c2dfSkettenis quote_char = _rl_find_completion_word (&found_quote, &delimiter);
19471acd27e7Smillert
19481acd27e7Smillert orig_start = rl_point;
19491acd27e7Smillert rl_point = orig_end;
19501acd27e7Smillert
19511acd27e7Smillert orig_text = rl_copy_text (orig_start, orig_end);
19521acd27e7Smillert matches = gen_completion_matches (orig_text, orig_start, orig_end,
19531acd27e7Smillert our_func, found_quote, quote_char);
19541acd27e7Smillert
19551acd27e7Smillert /* If we are matching filenames, the attempted completion function will
19561acd27e7Smillert have set rl_filename_completion_desired to a non-zero value. The basic
1957af70c2dfSkettenis rl_filename_completion_function does this. */
19581acd27e7Smillert matching_filenames = rl_filename_completion_desired;
1959af70c2dfSkettenis
19601acd27e7Smillert if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
19611acd27e7Smillert {
1962af70c2dfSkettenis rl_ding ();
19631acd27e7Smillert FREE (matches);
19641acd27e7Smillert matches = (char **)0;
19651acd27e7Smillert FREE (orig_text);
19661acd27e7Smillert orig_text = (char *)0;
19671acd27e7Smillert completion_changed_buffer = 0;
19681acd27e7Smillert return (0);
19691acd27e7Smillert }
19701acd27e7Smillert
19711acd27e7Smillert for (match_list_size = 0; matches[match_list_size]; match_list_size++)
19721acd27e7Smillert ;
19731acd27e7Smillert /* matches[0] is lcd if match_list_size > 1, but the circular buffer
19741acd27e7Smillert code below should take care of it. */
19751acd27e7Smillert }
19761acd27e7Smillert
19771acd27e7Smillert /* Now we have the list of matches. Replace the text between
19781acd27e7Smillert rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
19791acd27e7Smillert matches[match_list_index], and add any necessary closing char. */
19801acd27e7Smillert
19811acd27e7Smillert if (matches == 0 || match_list_size == 0)
19821acd27e7Smillert {
1983af70c2dfSkettenis rl_ding ();
19841acd27e7Smillert FREE (matches);
19851acd27e7Smillert matches = (char **)0;
19861acd27e7Smillert completion_changed_buffer = 0;
19871acd27e7Smillert return (0);
19881acd27e7Smillert }
19891acd27e7Smillert
19901acd27e7Smillert match_list_index = (match_list_index + count) % match_list_size;
19911acd27e7Smillert if (match_list_index < 0)
19921acd27e7Smillert match_list_index += match_list_size;
19931acd27e7Smillert
19941acd27e7Smillert if (match_list_index == 0 && match_list_size > 1)
19951acd27e7Smillert {
1996af70c2dfSkettenis rl_ding ();
19971acd27e7Smillert insert_match (orig_text, orig_start, MULT_MATCH, "e_char);
19981acd27e7Smillert }
19991acd27e7Smillert else
20001acd27e7Smillert {
20011acd27e7Smillert insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
2002af70c2dfSkettenis append_to_match (matches[match_list_index], delimiter, quote_char,
2003af70c2dfSkettenis strcmp (orig_text, matches[match_list_index]));
20041acd27e7Smillert }
20051acd27e7Smillert
20061acd27e7Smillert completion_changed_buffer = 1;
20071acd27e7Smillert return (0);
20081acd27e7Smillert }
2009