(file_compl,no_compl,msglist_compl)
(msglist_file_compl,dir_compl) (command_compl,alias_compl,var_compl): New functions for readline completion support
Showing
1 changed file
with
311 additions
and
9 deletions
... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
17 | MA 02110-1301 USA */ | 17 | MA 02110-1301 USA */ |
18 | 18 | ||
19 | #include "mail.h" | 19 | #include "mail.h" |
20 | #include <mailutils/folder.h> | ||
20 | 21 | ||
21 | #ifdef WITH_READLINE | 22 | #ifdef WITH_READLINE |
22 | static char **ml_command_completion __P((char *cmd, int start, int end)); | 23 | static char **ml_command_completion __P((char *cmd, int start, int end)); |
... | @@ -226,11 +227,35 @@ ml_reread (const char *prompt, char **text) | ... | @@ -226,11 +227,35 @@ ml_reread (const char *prompt, char **text) |
226 | * readline tab completion | 227 | * readline tab completion |
227 | */ | 228 | */ |
228 | char ** | 229 | char ** |
229 | ml_command_completion (char *cmd, int start ARG_UNUSED, int end ARG_UNUSED) | 230 | ml_command_completion (char *cmd, int start, int end) |
230 | { | 231 | { |
231 | if (start == 0) | 232 | int argc; |
232 | return rl_completion_matches (cmd, ml_command_generator); | 233 | char **argv; |
233 | return NULL; | 234 | char **ret; |
235 | char *p; | ||
236 | |||
237 | for (p = rl_line_buffer; p < rl_line_buffer + start && isspace (*p); p++) | ||
238 | ; | ||
239 | |||
240 | if (argcv_get_n (p, end, NULL, NULL, &argc, &argv)) | ||
241 | return NULL; | ||
242 | rl_completion_append_character = ' '; | ||
243 | |||
244 | if (argc <= 1 && strlen (argv[0]) <= end - start) | ||
245 | { | ||
246 | ret = rl_completion_matches (cmd, ml_command_generator); | ||
247 | rl_attempted_completion_over = 1; | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | const struct mail_command_entry *entry = mail_find_command (argv[0]); | ||
252 | if (entry && entry->command_completion) | ||
253 | ret = entry->command_completion (argc, argv, start == end); | ||
254 | else | ||
255 | ret = NULL; | ||
256 | } | ||
257 | argcv_free (argc, argv); | ||
258 | return ret; | ||
234 | } | 259 | } |
235 | 260 | ||
236 | /* | 261 | /* |
... | @@ -241,25 +266,291 @@ ml_command_generator (const char *text, int state) | ... | @@ -241,25 +266,291 @@ ml_command_generator (const char *text, int state) |
241 | { | 266 | { |
242 | static int i, len; | 267 | static int i, len; |
243 | const char *name; | 268 | const char *name; |
244 | 269 | const struct mail_command *cp; | |
270 | |||
245 | if (!state) | 271 | if (!state) |
246 | { | 272 | { |
247 | i = 0; | 273 | i = 0; |
248 | len = strlen (text); | 274 | len = strlen (text); |
249 | } | 275 | } |
250 | 276 | ||
251 | while ((name = mail_command_table[i].longname)) | 277 | while ((cp = mail_command_name (i))) |
252 | { | 278 | { |
253 | if (strlen (mail_command_table[i].shortname) > strlen(name)) | 279 | name = cp->longname; |
254 | name = mail_command_table[i].shortname; | 280 | if (strlen (cp->shortname) > strlen (name)) |
281 | name = cp->shortname; | ||
255 | i++; | 282 | i++; |
256 | if (strncmp (name, text, len) == 0) | 283 | if (strncmp (name, text, len) == 0) |
257 | return (strdup(name)); | 284 | return strdup (name); |
285 | } | ||
286 | |||
287 | return NULL; | ||
288 | } | ||
289 | |||
290 | void | ||
291 | ml_set_completion_append_character (int c) | ||
292 | { | ||
293 | rl_completion_append_character = c; | ||
294 | } | ||
295 | |||
296 | void | ||
297 | ml_attempted_completion_over () | ||
298 | { | ||
299 | rl_attempted_completion_over = 1; | ||
300 | } | ||
301 | |||
302 | |||
303 | /* Completion functions */ | ||
304 | char ** | ||
305 | no_compl (int argc ARG_UNUSED, char **argv ARG_UNUSED, int ws ARG_UNUSED) | ||
306 | { | ||
307 | ml_attempted_completion_over (); | ||
308 | return NULL; | ||
309 | } | ||
310 | |||
311 | char ** | ||
312 | msglist_compl (int argc, char **argv, int ws) | ||
313 | { | ||
314 | /* FIXME */ | ||
315 | ml_attempted_completion_over (); | ||
316 | return NULL; | ||
317 | } | ||
318 | |||
319 | char ** | ||
320 | msglist_file_compl (int argc, char **argv, int ws ARG_UNUSED) | ||
321 | { | ||
322 | if (argc == 1) | ||
323 | ml_attempted_completion_over (); | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | char ** | ||
328 | command_compl (int argc, char **argv, int ws) | ||
329 | { | ||
330 | ml_set_completion_append_character (0); | ||
331 | if (ws) | ||
332 | return NULL; | ||
333 | return rl_completion_matches (argv[argc-1], ml_command_generator); | ||
334 | } | ||
335 | |||
336 | static char * | ||
337 | file_generator (const char *text, int state, char *path, size_t pathlen, | ||
338 | char repl, | ||
339 | int flags) | ||
340 | { | ||
341 | static struct folder_list list; | ||
342 | static int i; | ||
343 | |||
344 | if (!state) | ||
345 | { | ||
346 | char *wcard; | ||
347 | folder_t folder; | ||
348 | |||
349 | wcard = xmalloc (strlen (text) + 2); | ||
350 | strcat (strcpy (wcard, text), "*"); | ||
351 | |||
352 | folder_create (&folder, path); | ||
353 | folder_list (folder, path, wcard, &list); | ||
354 | free (wcard); | ||
355 | folder_destroy (&folder); | ||
356 | |||
357 | if (list.num == 0) | ||
358 | return NULL; | ||
359 | else if (list.num == 1) | ||
360 | ml_set_completion_append_character (0); | ||
361 | |||
362 | i = 0; | ||
258 | } | 363 | } |
259 | 364 | ||
365 | while (i < list.num) | ||
366 | { | ||
367 | if (list.element[i]->type & flags) | ||
368 | { | ||
369 | char *ret; | ||
370 | if (repl) | ||
371 | { | ||
372 | int len = strlen (list.element[i]->name + pathlen); | ||
373 | ret = xmalloc (len + 2); | ||
374 | ret[0] = repl; | ||
375 | memcpy (ret + 1, list.element[i]->name + pathlen, len); | ||
376 | ret[len+1] = 0; | ||
377 | } | ||
378 | else | ||
379 | ret = xstrdup (list.element[i]->name); | ||
380 | i++; | ||
381 | return ret; | ||
382 | } | ||
383 | i++; | ||
384 | } | ||
385 | |||
386 | folder_list_destroy (&list); | ||
260 | return NULL; | 387 | return NULL; |
261 | } | 388 | } |
262 | 389 | ||
390 | static char * | ||
391 | folder_generator (const char *text, int state) | ||
392 | { | ||
393 | char *ret; | ||
394 | static size_t pathlen; | ||
395 | |||
396 | if (!state) | ||
397 | { | ||
398 | char *path = util_folder_path (""); | ||
399 | if (!path) | ||
400 | return NULL; | ||
401 | |||
402 | pathlen = strlen (path); | ||
403 | ret = file_generator (text, state, path, pathlen, '+', | ||
404 | MU_FOLDER_ATTRIBUTE_ALL); | ||
405 | free (path); | ||
406 | } | ||
407 | else | ||
408 | ret = file_generator (text, state, NULL, pathlen, '+', | ||
409 | MU_FOLDER_ATTRIBUTE_ALL); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | char ** | ||
414 | file_compl (int argc, char **argv, int ws) | ||
415 | { | ||
416 | char *text; | ||
417 | |||
418 | if (ws) | ||
419 | { | ||
420 | ml_set_completion_append_character (0); | ||
421 | ml_attempted_completion_over (); | ||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | text = argv[argc-1]; | ||
426 | switch (text[0]) | ||
427 | { | ||
428 | case '+': | ||
429 | text++; | ||
430 | break; | ||
431 | |||
432 | case '#': | ||
433 | case '&': | ||
434 | ml_attempted_completion_over (); | ||
435 | return NULL; | ||
436 | |||
437 | default: | ||
438 | return NULL; /* Will be expanded by readline itself */ | ||
439 | } | ||
440 | |||
441 | return rl_completion_matches (text, folder_generator); | ||
442 | } | ||
443 | |||
444 | static char * | ||
445 | dir_generator (const char *text, int state) | ||
446 | { | ||
447 | char *ret; | ||
448 | static size_t pathlen; | ||
449 | static int repl; | ||
450 | |||
451 | if (!state) | ||
452 | { | ||
453 | char *path; | ||
454 | switch (text[0]) | ||
455 | { | ||
456 | case '+': | ||
457 | text++; | ||
458 | repl = '+'; | ||
459 | path = util_folder_path (text); | ||
460 | pathlen = strlen (path) - strlen (text); | ||
461 | break; | ||
462 | |||
463 | case '~': | ||
464 | repl = '~'; | ||
465 | if (text[1] == '/') | ||
466 | { | ||
467 | path = mu_get_homedir (); | ||
468 | text += 2; | ||
469 | pathlen = strlen (path); | ||
470 | break; | ||
471 | } | ||
472 | /* else FIXME! */ | ||
473 | |||
474 | default: | ||
475 | path = strdup (text); | ||
476 | pathlen = 0; | ||
477 | repl = 0; | ||
478 | } | ||
479 | |||
480 | ret = file_generator (text, state, path, pathlen, repl, | ||
481 | MU_FOLDER_ATTRIBUTE_DIRECTORY); | ||
482 | free (path); | ||
483 | } | ||
484 | else | ||
485 | ret = file_generator (text, state, NULL, pathlen, repl, | ||
486 | MU_FOLDER_ATTRIBUTE_DIRECTORY); | ||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | char ** | ||
491 | dir_compl (int argc, char **argv, int ws) | ||
492 | { | ||
493 | ml_attempted_completion_over (); | ||
494 | if (ws) | ||
495 | { | ||
496 | ml_set_completion_append_character (0); | ||
497 | return NULL; | ||
498 | } | ||
499 | return rl_completion_matches (argv[argc-1], dir_generator); | ||
500 | } | ||
501 | |||
502 | static char * | ||
503 | alias_generator (const char *text, int state) | ||
504 | { | ||
505 | static alias_iterator_t itr; | ||
506 | const char *p; | ||
507 | |||
508 | if (!state) | ||
509 | p = alias_iterate_first (text, &itr); | ||
510 | else | ||
511 | p = alias_iterate_next (itr); | ||
512 | |||
513 | if (!p) | ||
514 | { | ||
515 | alias_iterate_end (&itr); | ||
516 | return NULL; | ||
517 | } | ||
518 | return strdup (p); | ||
519 | } | ||
520 | |||
521 | char ** | ||
522 | alias_compl (int argc, char **argv, int ws) | ||
523 | { | ||
524 | ml_attempted_completion_over (); | ||
525 | return rl_completion_matches (ws ? "" : argv[argc-1], alias_generator); | ||
526 | } | ||
527 | |||
528 | static char * | ||
529 | var_generator (const char *text, int state) | ||
530 | { | ||
531 | static var_iterator_t itr; | ||
532 | const char *p; | ||
533 | |||
534 | if (!state) | ||
535 | p = var_iterate_first (text, &itr); | ||
536 | else | ||
537 | p = var_iterate_next (itr); | ||
538 | |||
539 | if (!p) | ||
540 | { | ||
541 | var_iterate_end (&itr); | ||
542 | return NULL; | ||
543 | } | ||
544 | return strdup (p); | ||
545 | } | ||
546 | |||
547 | char ** | ||
548 | var_compl (int argc, char **argv, int ws) | ||
549 | { | ||
550 | ml_attempted_completion_over (); | ||
551 | return rl_completion_matches (ws ? "" : argv[argc-1], var_generator); | ||
552 | } | ||
553 | |||
263 | #else | 554 | #else |
264 | 555 | ||
265 | #include <sys/ioctl.h> | 556 | #include <sys/ioctl.h> |
... | @@ -549,5 +840,16 @@ readline (char *prompt) | ... | @@ -549,5 +840,16 @@ readline (char *prompt) |
549 | 840 | ||
550 | return ml_readline_internal (); | 841 | return ml_readline_internal (); |
551 | } | 842 | } |
843 | |||
844 | void | ||
845 | ml_set_completion_append_character (int c ARG_UNUSED) | ||
846 | { | ||
847 | } | ||
848 | |||
849 | void | ||
850 | ml_attempted_completion_over () | ||
851 | { | ||
852 | } | ||
853 | |||
552 | #endif | 854 | #endif |
553 | 855 | ... | ... |
-
Please register or sign in to post a comment