1 | /* bracecomp.c -- Complete a filename with the possible completions enclosed
|
---|
2 | in csh-style braces such that the list of completions is available to the
|
---|
3 | shell. */
|
---|
4 |
|
---|
5 | /* Original version by tromey@cns.caltech.edu, Fri Feb 7 1992. */
|
---|
6 |
|
---|
7 | /* Copyright (C) 1993 Free Software Foundation, Inc.
|
---|
8 |
|
---|
9 | This file is part of GNU Bash, the Bourne Again SHell.
|
---|
10 |
|
---|
11 | Bash is free software; you can redistribute it and/or modify it under
|
---|
12 | the terms of the GNU General Public License as published by the Free
|
---|
13 | Software Foundation; either version 2, or (at your option) any later
|
---|
14 | version.
|
---|
15 |
|
---|
16 | Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
---|
17 | WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
---|
18 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
---|
19 | for more details.
|
---|
20 |
|
---|
21 | You should have received a copy of the GNU General Public License along
|
---|
22 | with Bash; see the file COPYING. If not, write to the Free Software
|
---|
23 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
---|
24 |
|
---|
25 | #include "config.h"
|
---|
26 | #if defined (BRACE_EXPANSION) && defined (READLINE)
|
---|
27 |
|
---|
28 | #include <stdio.h>
|
---|
29 |
|
---|
30 | #if defined (HAVE_UNISTD_H)
|
---|
31 | # ifdef _MINIX
|
---|
32 | # include <sys/types.h>
|
---|
33 | # endif
|
---|
34 | # include <unistd.h>
|
---|
35 | #endif
|
---|
36 |
|
---|
37 | #include "bashansi.h"
|
---|
38 |
|
---|
39 | #include "shell.h"
|
---|
40 | #include <readline/readline.h>
|
---|
41 |
|
---|
42 | /* Find greatest common prefix of two strings. */
|
---|
43 | static int
|
---|
44 | string_gcd (s1, s2)
|
---|
45 | char *s1, *s2;
|
---|
46 | {
|
---|
47 | register int i;
|
---|
48 |
|
---|
49 | if (s1 == NULL || s2 == NULL)
|
---|
50 | return (0);
|
---|
51 |
|
---|
52 | for (i = 0; *s1 && *s2; ++s1, ++s2, ++i)
|
---|
53 | {
|
---|
54 | if (*s1 != *s2)
|
---|
55 | break;
|
---|
56 | }
|
---|
57 |
|
---|
58 | return (i);
|
---|
59 | }
|
---|
60 |
|
---|
61 | static char *
|
---|
62 | really_munge_braces (array, real_start, real_end, gcd_zero)
|
---|
63 | char **array;
|
---|
64 | int real_start, real_end, gcd_zero;
|
---|
65 | {
|
---|
66 | int start, end, gcd;
|
---|
67 | char *result, *subterm, *x;
|
---|
68 | int result_size, flag, tlen;
|
---|
69 |
|
---|
70 | flag = 0;
|
---|
71 |
|
---|
72 | if (real_start == real_end)
|
---|
73 | {
|
---|
74 | x = array[real_start] ? sh_backslash_quote (array[real_start] + gcd_zero)
|
---|
75 | : sh_backslash_quote (array[0]);
|
---|
76 | return x;
|
---|
77 | }
|
---|
78 |
|
---|
79 | result = (char *)xmalloc (result_size = 16);
|
---|
80 | *result = '\0';
|
---|
81 |
|
---|
82 | for (start = real_start; start < real_end; start = end + 1)
|
---|
83 | {
|
---|
84 | gcd = strlen (array[start]);
|
---|
85 | for (end = start + 1; end < real_end; end++)
|
---|
86 | {
|
---|
87 | int temp;
|
---|
88 |
|
---|
89 | temp = string_gcd (array[start], array[end]);
|
---|
90 |
|
---|
91 | if (temp <= gcd_zero)
|
---|
92 | break;
|
---|
93 |
|
---|
94 | gcd = temp;
|
---|
95 | }
|
---|
96 | end--;
|
---|
97 |
|
---|
98 | if (gcd_zero == 0 && start == real_start && end != (real_end - 1))
|
---|
99 | {
|
---|
100 | /* In this case, add in a leading '{', because we are at
|
---|
101 | top level, and there isn't a consistent prefix. */
|
---|
102 | result_size += 1;
|
---|
103 | result = (char *)xrealloc (result, result_size);
|
---|
104 | result[0] = '{'; result[1] = '\0';
|
---|
105 | flag++;
|
---|
106 | }
|
---|
107 |
|
---|
108 | /* Make sure we backslash quote every substring we insert into the
|
---|
109 | resultant brace expression. This is so the default filename
|
---|
110 | quoting function won't inappropriately quote the braces. */
|
---|
111 | if (start == end)
|
---|
112 | {
|
---|
113 | x = savestring (array[start] + gcd_zero);
|
---|
114 | subterm = sh_backslash_quote (x);
|
---|
115 | free (x);
|
---|
116 | }
|
---|
117 | else
|
---|
118 | {
|
---|
119 | /* If there is more than one element in the subarray,
|
---|
120 | insert the (quoted) prefix and an opening brace. */
|
---|
121 | tlen = gcd - gcd_zero;
|
---|
122 | x = (char *)xmalloc (tlen + 1);
|
---|
123 | strncpy (x, array[start] + gcd_zero, tlen);
|
---|
124 | x[tlen] = '\0';
|
---|
125 | subterm = sh_backslash_quote (x);
|
---|
126 | free (x);
|
---|
127 | result_size += strlen (subterm) + 1;
|
---|
128 | result = (char *)xrealloc (result, result_size);
|
---|
129 | strcat (result, subterm);
|
---|
130 | free (subterm);
|
---|
131 | strcat (result, "{");
|
---|
132 | subterm = really_munge_braces (array, start, end + 1, gcd);
|
---|
133 | subterm[strlen (subterm) - 1] = '}';
|
---|
134 | }
|
---|
135 |
|
---|
136 | result_size += strlen (subterm) + 1;
|
---|
137 | result = (char *)xrealloc (result, result_size);
|
---|
138 | strcat (result, subterm);
|
---|
139 | strcat (result, ",");
|
---|
140 | free (subterm);
|
---|
141 | }
|
---|
142 |
|
---|
143 | if (gcd_zero == 0)
|
---|
144 | result[strlen (result) - 1] = flag ? '}' : '\0';
|
---|
145 | return (result);
|
---|
146 | }
|
---|
147 |
|
---|
148 | static int
|
---|
149 | hack_braces_completion (names)
|
---|
150 | char **names;
|
---|
151 | {
|
---|
152 | register int i;
|
---|
153 | char *temp;
|
---|
154 |
|
---|
155 | temp = really_munge_braces (names, 1, strvec_len (names), 0);
|
---|
156 |
|
---|
157 | for (i = 0; names[i]; ++i)
|
---|
158 | {
|
---|
159 | free (names[i]);
|
---|
160 | names[i] = NULL;
|
---|
161 | }
|
---|
162 | names[0] = temp;
|
---|
163 | return 0;
|
---|
164 | }
|
---|
165 |
|
---|
166 | /* We handle quoting ourselves within hack_braces_completion, so we turn off
|
---|
167 | rl_filename_quoting_desired and rl_filename_quoting_function. */
|
---|
168 | int
|
---|
169 | bash_brace_completion (count, ignore)
|
---|
170 | int count, ignore;
|
---|
171 | {
|
---|
172 | rl_compignore_func_t *orig_ignore_func;
|
---|
173 | rl_compentry_func_t *orig_entry_func;
|
---|
174 | rl_quote_func_t *orig_quoting_func;
|
---|
175 | rl_completion_func_t *orig_attempt_func;
|
---|
176 | int orig_quoting_desired, r;
|
---|
177 |
|
---|
178 | orig_ignore_func = rl_ignore_some_completions_function;
|
---|
179 | orig_attempt_func = rl_attempted_completion_function;
|
---|
180 | orig_entry_func = rl_completion_entry_function;
|
---|
181 | orig_quoting_func = rl_filename_quoting_function;
|
---|
182 | orig_quoting_desired = rl_filename_quoting_desired;
|
---|
183 |
|
---|
184 | rl_completion_entry_function = rl_filename_completion_function;
|
---|
185 | rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
---|
186 | rl_ignore_some_completions_function = hack_braces_completion;
|
---|
187 | rl_filename_quoting_function = (rl_quote_func_t *)NULL;
|
---|
188 | rl_filename_quoting_desired = 0;
|
---|
189 |
|
---|
190 | r = rl_complete_internal (TAB);
|
---|
191 |
|
---|
192 | rl_ignore_some_completions_function = orig_ignore_func;
|
---|
193 | rl_attempted_completion_function = orig_attempt_func;
|
---|
194 | rl_completion_entry_function = orig_entry_func;
|
---|
195 | rl_filename_quoting_function = orig_quoting_func;
|
---|
196 | rl_filename_quoting_desired = orig_quoting_desired;
|
---|
197 |
|
---|
198 | return r;
|
---|
199 | }
|
---|
200 | #endif /* BRACE_EXPANSION && READLINE */
|
---|