4 Created: July 1995 by Philip Homburg <philip@cs.vu.nl>
13 #include "myhistedit.h"
22 static char **getlist(EditLine
*el
, int *baselen
, int *isdir
);
23 static char **getlist_tilde(char *prefix
);
24 static int vstrcmp(const void *v1
, const void *v2
);
25 static void print_list(char **list
);
26 static int install_extra(EditLine
*el
, char **list
, int baselen
, int isdir
);
28 unsigned char complete(EditLine
*el
, int ch
)
30 struct stackmark mark
;
33 int baselen
, prefix
, isdir
;
35 /* Direct the cursor the the end of the word. */
39 if (lf
->cursor
< lf
->lastchar
&&
40 !isspace((unsigned char)*lf
->cursor
))
42 (*(char **)&lf
->cursor
)++; /* XXX */
49 list
= getlist(el
, &baselen
, &isdir
);
52 prefix
= install_extra(el
, list
, baselen
, isdir
);
62 unsigned char complete_list(EditLine
*el
, int ch
)
64 struct stackmark mark
;
68 list
= getlist(el
, NULL
, NULL
);
83 unsigned char complete_or_list(EditLine
*el
, int ch
)
85 struct stackmark mark
;
88 int baselen
, prefix
, isdir
;
91 list
= getlist(el
, &baselen
, &isdir
);
94 prefix
= install_extra(el
, list
, baselen
, isdir
);
95 if (prefix
== baselen
)
108 unsigned char complete_expand(EditLine
*el
, int ch
)
110 printf("complete_expand\n");
114 static char **getlist(EditLine
*el
, int *baselen
, int *isdir
)
117 const char *begin
, *end
;
118 char *dirnam
, *basenam
;
120 struct arglist arglist
;
122 struct dirent
*dirent
;
125 struct strlist
*slp
, *nslp
;
130 /* Try to find to begin and end of the word that we have to comple. */
132 while (begin
> lf
->buffer
&& !isspace((unsigned char)begin
[-1]))
135 while (end
< lf
->lastchar
&& !isspace((unsigned char)end
[0]))
138 *(const char **)&lf
->cursor
= end
; /* XXX */
140 /* Copy the word to a string */
141 dirnam
= stalloc(end
-begin
+1);
142 strncpy(dirnam
, begin
, end
-begin
);
143 dirnam
[end
-begin
]= '\0';
145 /* Cut the word in two pieces: a path and a (partial) component. */
146 basenam
= strrchr(dirnam
, '/');
150 p
= stalloc(strlen(basenam
) + 1);
157 if (dirnam
[0] == '~')
158 return getlist_tilde(dirnam
);
163 *baselen
= strlen(basenam
);
167 arg
.narg
.text
= dirnam
;
168 arg
.narg
.backquote
= NULL
;
170 arglist
.lastp
= &arglist
.list
;
171 expandarg(&arg
, &arglist
, EXP_TILDE
);
175 dir
= opendir(arglist
.list
->text
);
181 while(dirent
= readdir(dir
))
183 if (strncmp(dirent
->d_name
, basenam
, l
) != 0)
185 if (l
== 0 && dirent
->d_name
[0] == '.')
187 nslp
= stalloc(sizeof(*nslp
));
190 slp
->text
= stalloc(strlen(dirent
->d_name
)+1);
191 strcpy(slp
->text
, dirent
->d_name
);
193 if (n
== 1 && isdir
!= NULL
)
195 /* Try to findout whether this entry is a
196 * file or a directory.
198 p
= stalloc(strlen(arglist
.list
->text
) +
199 strlen(dirent
->d_name
) + 1);
200 strcpy(p
, arglist
.list
->text
);
201 strcat(p
, dirent
->d_name
);
202 if (stat(p
, &sb
) == -1)
203 printf("stat '%s' failed: %s\n",
205 if (stat(p
, &sb
) == 0 && S_ISDIR(sb
.st_mode
))
214 list
= stalloc((n
+1)*sizeof(*list
));
215 for(i
= 0; slp
; i
++, slp
= slp
->next
)
218 error("complete'make_list: i != n");
220 qsort(list
, n
, sizeof(*list
), vstrcmp
);
227 static char **getlist_tilde(char *prefix
)
229 printf("should ~-complete '%s'\n", prefix
);
233 static int vstrcmp(const void *v1
, const void *v2
)
235 return strcmp(*(char **)v1
, *(char **)v2
);
241 static void print_list(char **list
)
246 int start
[MAXCOLS
+1];
249 int e
, i
, j
, l
, n
, o
, cols
, maxw
, width
;
252 /* Count the number of entries. */
253 for (n
= 0; list
[n
]; n
++)
256 error("complete'print_list: n= 0");
258 /* Try to maximize the number of columns */
259 for (cols
= 1; cols
<= MAXCOLS
; cols
++)
265 for(j
= 0; j
<cols
; j
++)
269 /* Number of entries in this column. */
277 l
= strlen(list
[o
+i
]);
289 if (cols
> 1 && width
-SEPWIDTH
>linewidth
)
298 for (j
= 0; j
<cols
; j
++)
300 if (best
.start
[j
]+i
== best
.start
[j
+1])
304 printf("%-*s", best
.width
[j
],
305 list
[best
.start
[j
]+i
]);
309 printf("%s", list
[best
.start
[j
]+i
]);
318 static int install_extra(EditLine
*el
, char **list
, int baselen
, int isdir
)
324 for (lp
= &list
[1]; *lp
; lp
++)
328 if (strncmp(list
[0], *lp
, l
) != 0)
334 if (l
> baselen
|| list
[1] == NULL
)
336 p
= stalloc(l
-baselen
+2);
337 strncpy(p
, list
[0]+baselen
, l
-baselen
);
340 p
[l
-baselen
]= isdir
? '/' : ' ';
341 p
[l
-baselen
+1]= '\0';
346 if (el_insertstr(el
, p
) == -1)
353 * $PchId: complete.c,v 1.2 2006/04/10 14:35:53 philip Exp $