Commit 570af4fe 570af4fe08d77f23427cc17fcfa539ad73cb812c by Sergey Poznyakoff

(file_compl,no_compl,msglist_compl)

(msglist_file_compl,dir_compl)
(command_compl,alias_compl,var_compl): New functions for readline
completion support
1 parent 1ee79592
...@@ -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
......