mail: Implement folder completion in "save"
* mail/mailline.c (file_compl_internal): New function (from file_compl); (file_compl): Call file_compl_internal. (msglist_file_compl): Call file_compl_internal.
Showing
1 changed file
with
155 additions
and
37 deletions
... | @@ -121,7 +121,7 @@ ml_readline_internal () | ... | @@ -121,7 +121,7 @@ ml_readline_internal () |
121 | char *buf = NULL; | 121 | char *buf = NULL; |
122 | size_t size = 0, n; | 122 | size_t size = 0, n; |
123 | int rc; | 123 | int rc; |
124 | 124 | ||
125 | rc = mu_stream_getline (mu_strin, &buf, &size, &n); | 125 | rc = mu_stream_getline (mu_strin, &buf, &size, &n); |
126 | if (rc) | 126 | if (rc) |
127 | { | 127 | { |
... | @@ -200,7 +200,7 @@ ml_command_completion (char *cmd, int start, int end) | ... | @@ -200,7 +200,7 @@ ml_command_completion (char *cmd, int start, int end) |
200 | char **ret; | 200 | char **ret; |
201 | char *p; | 201 | char *p; |
202 | struct mu_wordsplit ws; | 202 | struct mu_wordsplit ws; |
203 | 203 | ||
204 | for (p = rl_line_buffer; p < rl_line_buffer + start && mu_isblank (*p); p++) | 204 | for (p = rl_line_buffer; p < rl_line_buffer + start && mu_isblank (*p); p++) |
205 | ; | 205 | ; |
206 | 206 | ||
... | @@ -211,7 +211,7 @@ ml_command_completion (char *cmd, int start, int end) | ... | @@ -211,7 +211,7 @@ ml_command_completion (char *cmd, int start, int end) |
211 | return NULL; | 211 | return NULL; |
212 | } | 212 | } |
213 | rl_completion_append_character = ' '; | 213 | rl_completion_append_character = ' '; |
214 | 214 | ||
215 | if (ws.ws_wordc == 0 || | 215 | if (ws.ws_wordc == 0 || |
216 | (ws.ws_wordc == 1 && strlen (ws.ws_wordv[0]) <= end - start)) | 216 | (ws.ws_wordc == 1 && strlen (ws.ws_wordv[0]) <= end - start)) |
217 | { | 217 | { |
... | @@ -241,7 +241,7 @@ ml_command_generator (const char *text, int state) | ... | @@ -241,7 +241,7 @@ ml_command_generator (const char *text, int state) |
241 | static int i, len; | 241 | static int i, len; |
242 | const char *name; | 242 | const char *name; |
243 | const struct mail_command *cp; | 243 | const struct mail_command *cp; |
244 | 244 | ||
245 | if (!state) | 245 | if (!state) |
246 | { | 246 | { |
247 | i = 0; | 247 | i = 0; |
... | @@ -291,14 +291,6 @@ msglist_compl (int argc, char **argv, int ws) | ... | @@ -291,14 +291,6 @@ msglist_compl (int argc, char **argv, int ws) |
291 | } | 291 | } |
292 | 292 | ||
293 | char ** | 293 | char ** |
294 | msglist_file_compl (int argc, char **argv, int ws MU_ARG_UNUSED) | ||
295 | { | ||
296 | if (argc == 1) | ||
297 | ml_attempted_completion_over (); | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | char ** | ||
302 | command_compl (int argc, char **argv, int ws) | 294 | command_compl (int argc, char **argv, int ws) |
303 | { | 295 | { |
304 | ml_set_completion_append_character (0); | 296 | ml_set_completion_append_character (0); |
... | @@ -313,24 +305,24 @@ command_compl (int argc, char **argv, int ws) | ... | @@ -313,24 +305,24 @@ command_compl (int argc, char **argv, int ws) |
313 | 305 | ||
314 | Select only those files that match given FLAGS (MU_FOLDER_ATTRIBUTE_* | 306 | Select only those files that match given FLAGS (MU_FOLDER_ATTRIBUTE_* |
315 | constants). | 307 | constants). |
316 | 308 | ||
317 | STATE is 0 for the first call, 1 otherwise. | 309 | STATE is 0 for the first call, 1 otherwise. |
318 | */ | 310 | */ |
319 | static char * | 311 | static char * |
320 | file_generator (const char *text, int state, | 312 | file_generator (const char *text, int state, |
321 | char *path, size_t pathlen, | 313 | char *path, size_t pathlen, |
322 | char repl, | 314 | char repl, |
323 | int flags) | 315 | int flags) |
324 | { | 316 | { |
325 | static mu_list_t list; | 317 | static mu_list_t list; |
326 | static mu_iterator_t itr; | 318 | static mu_iterator_t itr; |
327 | 319 | ||
328 | if (!state) | 320 | if (!state) |
329 | { | 321 | { |
330 | char *wcard; | 322 | char *wcard; |
331 | mu_folder_t folder; | 323 | mu_folder_t folder; |
332 | size_t count; | 324 | size_t count; |
333 | 325 | ||
334 | wcard = xmalloc (strlen (text) + 2); | 326 | wcard = xmalloc (strlen (text) + 2); |
335 | strcat (strcpy (wcard, text), "*"); | 327 | strcat (strcpy (wcard, text), "*"); |
336 | 328 | ||
... | @@ -339,7 +331,7 @@ file_generator (const char *text, int state, | ... | @@ -339,7 +331,7 @@ file_generator (const char *text, int state, |
339 | free (wcard); | 331 | free (wcard); |
340 | return NULL; | 332 | return NULL; |
341 | } | 333 | } |
342 | 334 | ||
343 | mu_folder_list (folder, path, wcard, 1, &list); | 335 | mu_folder_list (folder, path, wcard, 1, &list); |
344 | free (wcard); | 336 | free (wcard); |
345 | mu_folder_destroy (&folder); | 337 | mu_folder_destroy (&folder); |
... | @@ -351,7 +343,7 @@ file_generator (const char *text, int state, | ... | @@ -351,7 +343,7 @@ file_generator (const char *text, int state, |
351 | } | 343 | } |
352 | else if (count == 1) | 344 | else if (count == 1) |
353 | ml_set_completion_append_character (0); | 345 | ml_set_completion_append_character (0); |
354 | 346 | ||
355 | if (mu_list_get_iterator (list, &itr)) | 347 | if (mu_list_get_iterator (list, &itr)) |
356 | { | 348 | { |
357 | mu_list_destroy (&list); | 349 | mu_list_destroy (&list); |
... | @@ -372,7 +364,7 @@ file_generator (const char *text, int state, | ... | @@ -372,7 +364,7 @@ file_generator (const char *text, int state, |
372 | { | 364 | { |
373 | size_t len = strlen (resp->name + pathlen); | 365 | size_t len = strlen (resp->name + pathlen); |
374 | char *ptr; | 366 | char *ptr; |
375 | 367 | ||
376 | ret = xmalloc (len + (repl ? 1 : 0) + 1); | 368 | ret = xmalloc (len + (repl ? 1 : 0) + 1); |
377 | ptr = ret; | 369 | ptr = ret; |
378 | if (repl) | 370 | if (repl) |
... | @@ -395,13 +387,13 @@ folder_generator (const char *text, int state) | ... | @@ -395,13 +387,13 @@ folder_generator (const char *text, int state) |
395 | { | 387 | { |
396 | char *ret; | 388 | char *ret; |
397 | static size_t pathlen; | 389 | static size_t pathlen; |
398 | 390 | ||
399 | if (!state) | 391 | if (!state) |
400 | { | 392 | { |
401 | char *path = util_folder_path (""); | 393 | char *path = util_folder_path (""); |
402 | if (!path) | 394 | if (!path) |
403 | return NULL; | 395 | return NULL; |
404 | 396 | ||
405 | pathlen = strlen (path); | 397 | pathlen = strlen (path); |
406 | ret = file_generator (text, state, path, pathlen, '+', | 398 | ret = file_generator (text, state, path, pathlen, '+', |
407 | MU_FOLDER_ATTRIBUTE_ALL); | 399 | MU_FOLDER_ATTRIBUTE_ALL); |
... | @@ -413,8 +405,102 @@ folder_generator (const char *text, int state) | ... | @@ -413,8 +405,102 @@ folder_generator (const char *text, int state) |
413 | return ret; | 405 | return ret; |
414 | } | 406 | } |
415 | 407 | ||
416 | char ** | 408 | static char * |
417 | file_compl (int argc, char **argv, int ws) | 409 | msgtype_generator (const char *text, int state) |
410 | { | ||
411 | static char types[] = "dnorTtu"; | ||
412 | static int i; | ||
413 | char *s; | ||
414 | |||
415 | if (!state) | ||
416 | { | ||
417 | if (text[1]) | ||
418 | return NULL; | ||
419 | i = 0; | ||
420 | } | ||
421 | if (!types[i]) | ||
422 | return NULL; | ||
423 | s = malloc (2); | ||
424 | if (s) | ||
425 | { | ||
426 | s[0] = types[i++]; | ||
427 | s[1] = 0; | ||
428 | } | ||
429 | return s; | ||
430 | } | ||
431 | |||
432 | static char * | ||
433 | header_generator (const char *text, int state) | ||
434 | { | ||
435 | static int i, len; | ||
436 | char *hdr; | ||
437 | char *hdrlist[] = { | ||
438 | MU_HEADER_RETURN_PATH, | ||
439 | MU_HEADER_RECEIVED, | ||
440 | MU_HEADER_DATE, | ||
441 | MU_HEADER_DCC, | ||
442 | MU_HEADER_FROM, | ||
443 | MU_HEADER_SENDER, | ||
444 | MU_HEADER_RESENT_FROM, | ||
445 | MU_HEADER_SUBJECT, | ||
446 | MU_HEADER_RESENT_SENDER, | ||
447 | MU_HEADER_TO, | ||
448 | MU_HEADER_RESENT_TO, | ||
449 | MU_HEADER_CC, | ||
450 | MU_HEADER_RESENT_CC, | ||
451 | MU_HEADER_BCC, | ||
452 | MU_HEADER_RESENT_BCC, | ||
453 | MU_HEADER_REPLY_TO, | ||
454 | MU_HEADER_RESENT_REPLY_TO, | ||
455 | MU_HEADER_MESSAGE_ID, | ||
456 | MU_HEADER_RESENT_MESSAGE_ID, | ||
457 | MU_HEADER_IN_REPLY_TO, | ||
458 | MU_HEADER_REFERENCE, | ||
459 | MU_HEADER_REFERENCES, | ||
460 | MU_HEADER_ENCRYPTED, | ||
461 | MU_HEADER_PRECEDENCE, | ||
462 | MU_HEADER_STATUS, | ||
463 | MU_HEADER_CONTENT_LENGTH, | ||
464 | MU_HEADER_CONTENT_LANGUAGE, | ||
465 | MU_HEADER_CONTENT_TRANSFER_ENCODING, | ||
466 | MU_HEADER_CONTENT_ID, | ||
467 | MU_HEADER_CONTENT_TYPE, | ||
468 | MU_HEADER_CONTENT_DESCRIPTION, | ||
469 | MU_HEADER_CONTENT_DISPOSITION, | ||
470 | MU_HEADER_CONTENT_MD5, | ||
471 | MU_HEADER_CONTENT_LOCATION, | ||
472 | MU_HEADER_MIME_VERSION, | ||
473 | MU_HEADER_X_MAILER, | ||
474 | MU_HEADER_X_UIDL, | ||
475 | MU_HEADER_X_UID, | ||
476 | MU_HEADER_X_IMAPBASE, | ||
477 | MU_HEADER_ENV_SENDER, | ||
478 | MU_HEADER_ENV_DATE, | ||
479 | MU_HEADER_FCC, | ||
480 | MU_HEADER_DELIVERY_DATE, | ||
481 | MU_HEADER_ENVELOPE_TO, | ||
482 | MU_HEADER_X_EXPIRE_TIMESTAMP, | ||
483 | NULL | ||
484 | }; | ||
485 | |||
486 | if (!state) | ||
487 | { | ||
488 | i = 0; | ||
489 | len = strlen (text); | ||
490 | } | ||
491 | |||
492 | while ((hdr = hdrlist[i])) | ||
493 | { | ||
494 | i++; | ||
495 | if (mu_c_strncasecmp (hdr, text, len) == 0) | ||
496 | return strdup (hdr); | ||
497 | } | ||
498 | |||
499 | return NULL; | ||
500 | } | ||
501 | |||
502 | static char ** | ||
503 | file_compl_internal (int argc, char **argv, int ws, int msglist) | ||
418 | { | 504 | { |
419 | char *text; | 505 | char *text; |
420 | 506 | ||
... | @@ -424,26 +510,59 @@ file_compl (int argc, char **argv, int ws) | ... | @@ -424,26 +510,59 @@ file_compl (int argc, char **argv, int ws) |
424 | ml_attempted_completion_over (); | 510 | ml_attempted_completion_over (); |
425 | return NULL; | 511 | return NULL; |
426 | } | 512 | } |
427 | 513 | ||
428 | text = argv[argc-1]; | 514 | text = argv[argc-1]; |
515 | |||
516 | if (msglist) | ||
517 | { | ||
518 | if (text[0] == ':') | ||
519 | { | ||
520 | ml_set_completion_append_character (' '); | ||
521 | return rl_completion_matches (text, msgtype_generator); | ||
522 | } | ||
523 | else if (mu_isalpha (text[0])) | ||
524 | { | ||
525 | ml_set_completion_append_character (':'); | ||
526 | return rl_completion_matches (text, header_generator); | ||
527 | } | ||
528 | else if (mu_isdigit (text[0])) | ||
529 | { | ||
530 | ml_attempted_completion_over (); | ||
531 | return NULL; | ||
532 | } | ||
533 | } | ||
534 | |||
429 | switch (text[0]) | 535 | switch (text[0]) |
430 | { | 536 | { |
431 | case '+': | 537 | case '+': |
432 | text++; | 538 | text++; |
433 | break; | 539 | break; |
434 | 540 | ||
541 | case '%': | ||
435 | case '#': | 542 | case '#': |
436 | case '&': | 543 | case '&': |
437 | ml_attempted_completion_over (); | 544 | ml_attempted_completion_over (); |
438 | return NULL; | 545 | return NULL; |
439 | 546 | ||
440 | default: | 547 | default: |
441 | return NULL; /* Will be expanded by readline itself */ | 548 | return NULL; /* Will be expanded by readline itself */ |
442 | } | 549 | } |
443 | 550 | ||
444 | return rl_completion_matches (text, folder_generator); | 551 | return rl_completion_matches (text, folder_generator); |
445 | } | 552 | } |
446 | 553 | ||
554 | char ** | ||
555 | file_compl (int argc, char **argv, int ws) | ||
556 | { | ||
557 | return file_compl_internal (argc, argv, ws, 0); | ||
558 | } | ||
559 | |||
560 | char ** | ||
561 | msglist_file_compl (int argc, char **argv, int ws) | ||
562 | { | ||
563 | return file_compl_internal (argc, argv, ws, 1); | ||
564 | } | ||
565 | |||
447 | static char * | 566 | static char * |
448 | dir_generator (const char *text, int state) | 567 | dir_generator (const char *text, int state) |
449 | { | 568 | { |
... | @@ -479,13 +598,13 @@ dir_generator (const char *text, int state) | ... | @@ -479,13 +598,13 @@ dir_generator (const char *text, int state) |
479 | pathlen = 0; | 598 | pathlen = 0; |
480 | repl = 0; | 599 | repl = 0; |
481 | break; | 600 | break; |
482 | 601 | ||
483 | default: | 602 | default: |
484 | path = strdup ("./"); | 603 | path = strdup ("./"); |
485 | pathlen = 2; | 604 | pathlen = 2; |
486 | repl = 0; | 605 | repl = 0; |
487 | } | 606 | } |
488 | 607 | ||
489 | ret = file_generator (text, state, path, pathlen, repl, | 608 | ret = file_generator (text, state, path, pathlen, repl, |
490 | MU_FOLDER_ATTRIBUTE_DIRECTORY); | 609 | MU_FOLDER_ATTRIBUTE_DIRECTORY); |
491 | free (path); | 610 | free (path); |
... | @@ -513,7 +632,7 @@ alias_generator (const char *text, int state) | ... | @@ -513,7 +632,7 @@ alias_generator (const char *text, int state) |
513 | { | 632 | { |
514 | static alias_iterator_t itr; | 633 | static alias_iterator_t itr; |
515 | const char *p; | 634 | const char *p; |
516 | 635 | ||
517 | if (!state) | 636 | if (!state) |
518 | p = alias_iterate_first (text, &itr); | 637 | p = alias_iterate_first (text, &itr); |
519 | else | 638 | else |
... | @@ -557,7 +676,7 @@ exec_generator (const char *text, int state) | ... | @@ -557,7 +676,7 @@ exec_generator (const char *text, int state) |
557 | static size_t dsize; | 676 | static size_t dsize; |
558 | static DIR *dp; | 677 | static DIR *dp; |
559 | struct dirent *ent; | 678 | struct dirent *ent; |
560 | 679 | ||
561 | if (!state) | 680 | if (!state) |
562 | { | 681 | { |
563 | var = getenv ("PATH"); | 682 | var = getenv ("PATH"); |
... | @@ -580,13 +699,13 @@ exec_generator (const char *text, int state) | ... | @@ -580,13 +699,13 @@ exec_generator (const char *text, int state) |
580 | break; | 699 | break; |
581 | else | 700 | else |
582 | var++; | 701 | var++; |
583 | 702 | ||
584 | p = strchr (var, ':'); | 703 | p = strchr (var, ':'); |
585 | if (!p) | 704 | if (!p) |
586 | len = strlen (var) + 1; | 705 | len = strlen (var) + 1; |
587 | else | 706 | else |
588 | len = p - var + 1; | 707 | len = p - var + 1; |
589 | 708 | ||
590 | if (dsize == 0) | 709 | if (dsize == 0) |
591 | { | 710 | { |
592 | dir = malloc (len); | 711 | dir = malloc (len); |
... | @@ -597,13 +716,13 @@ exec_generator (const char *text, int state) | ... | @@ -597,13 +716,13 @@ exec_generator (const char *text, int state) |
597 | dir = realloc (dir, len); | 716 | dir = realloc (dir, len); |
598 | dsize = len; | 717 | dsize = len; |
599 | } | 718 | } |
600 | 719 | ||
601 | if (!dir) | 720 | if (!dir) |
602 | return NULL; | 721 | return NULL; |
603 | memcpy (dir, var, len - 1); | 722 | memcpy (dir, var, len - 1); |
604 | dir[len - 1] = 0; | 723 | dir[len - 1] = 0; |
605 | var += len - 1; | 724 | var += len - 1; |
606 | 725 | ||
607 | dp = opendir (dir); | 726 | dp = opendir (dir); |
608 | if (!dp) | 727 | if (!dp) |
609 | continue; | 728 | continue; |
... | @@ -614,13 +733,13 @@ exec_generator (const char *text, int state) | ... | @@ -614,13 +733,13 @@ exec_generator (const char *text, int state) |
614 | char *name = mkfilename (dir, ent->d_name); | 733 | char *name = mkfilename (dir, ent->d_name); |
615 | if (name) | 734 | if (name) |
616 | { | 735 | { |
617 | int rc = access (name, X_OK); | 736 | int rc = access (name, X_OK); |
618 | if (rc == 0) | 737 | if (rc == 0) |
619 | { | 738 | { |
620 | struct stat st; | 739 | struct stat st; |
621 | rc = !(stat (name, &st) == 0 && S_ISREG (st.st_mode)); | 740 | rc = !(stat (name, &st) == 0 && S_ISREG (st.st_mode)); |
622 | } | 741 | } |
623 | 742 | ||
624 | free (name); | 743 | free (name); |
625 | if (rc == 0 | 744 | if (rc == 0 |
626 | && strlen (ent->d_name) >= prefix_len | 745 | && strlen (ent->d_name) >= prefix_len |
... | @@ -944,4 +1063,3 @@ ml_attempted_completion_over () | ... | @@ -944,4 +1063,3 @@ ml_attempted_completion_over () |
944 | } | 1063 | } |
945 | 1064 | ||
946 | #endif | 1065 | #endif |
947 | ... | ... |
-
Please register or sign in to post a comment