Commit 63d1c196 63d1c19652942be6b600a5855880667f16fdb8a3 by Sergey Poznyakoff

Implement pager in mu shell.

* mu/mu.h (mutool_shell_interactive): New extern.
(mutool_open_pager): New proto.
* mu/pop.c (com_list, com_top, com_retr): Use pager.
* mu/shell.c (mutool_shell_interactive, mustrout): New
variables.
(print_comtab, print_help): Print to stream.
(shell_help): Use pager if necessary.
(mutool_open_pager): New function.
(mutool_shell): Create mutool_stream_out and destroy it before
returning.
(all functions): Use mu_stream_printf instead of printf.
1 parent c5cc666d
...@@ -37,5 +37,7 @@ int mutool_acl (int argc, char **argv); ...@@ -37,5 +37,7 @@ int mutool_acl (int argc, char **argv);
37 37
38 extern char *mutool_shell_prompt; 38 extern char *mutool_shell_prompt;
39 extern mu_vartab_t mutool_prompt_vartab; 39 extern mu_vartab_t mutool_prompt_vartab;
40 40 extern int mutool_shell_interactive;
41 extern mu_stream_t mustrout;
41 int mutool_shell (const char *name, struct mutool_command *cmd); 42 int mutool_shell (const char *name, struct mutool_command *cmd);
43 mu_stream_t mutool_open_pager (void);
......
...@@ -244,24 +244,24 @@ com_verbose (int argc, char **argv) ...@@ -244,24 +244,24 @@ com_verbose (int argc, char **argv)
244 { 244 {
245 if (QRY_VERBOSE ()) 245 if (QRY_VERBOSE ())
246 { 246 {
247 printf ("verbose is on"); 247 mu_stream_printf (mustrout, "verbose is on");
248 if (HAS_VERBOSE_MASK ()) 248 if (HAS_VERBOSE_MASK ())
249 { 249 {
250 char *delim = " ("; 250 char *delim = " (";
251 251
252 if (QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE)) 252 if (QRY_VERBOSE_MASK (MU_XSCRIPT_SECURE))
253 { 253 {
254 printf("%ssecure", delim); 254 mu_stream_printf (mustrout, "%ssecure", delim);
255 delim = ", "; 255 delim = ", ";
256 } 256 }
257 if (QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD)) 257 if (QRY_VERBOSE_MASK (MU_XSCRIPT_PAYLOAD))
258 printf("%spayload", delim); 258 mu_stream_printf (mustrout, "%spayload", delim);
259 printf (")"); 259 mu_stream_printf (mustrout, ")");
260 } 260 }
261 printf ("\n"); 261 mu_stream_printf (mustrout, "\n");
262 } 262 }
263 else 263 else
264 printf ("verbose is off\n"); 264 mu_stream_printf (mustrout, "verbose is off\n");
265 } 265 }
266 else 266 else
267 { 267 {
...@@ -346,13 +346,13 @@ com_capa (int argc, char **argv) ...@@ -346,13 +346,13 @@ com_capa (int argc, char **argv)
346 { 346 {
347 case 0: 347 case 0:
348 if (*elt) 348 if (*elt)
349 printf ("%s: %s\n", argv[i], elt); 349 mu_stream_printf (mustrout, "%s: %s\n", argv[i], elt);
350 else 350 else
351 printf ("%s is set\n", argv[i]); 351 mu_stream_printf (mustrout, "%s is set\n", argv[i]);
352 break; 352 break;
353 353
354 case MU_ERR_NOENT: 354 case MU_ERR_NOENT:
355 printf ("%s is not set\n", argv[i]); 355 mu_stream_printf (mustrout, "%s is not set\n", argv[i]);
356 break; 356 break;
357 357
358 default: 358 default:
...@@ -371,7 +371,7 @@ com_capa (int argc, char **argv) ...@@ -371,7 +371,7 @@ com_capa (int argc, char **argv)
371 { 371 {
372 char *capa = NULL; 372 char *capa = NULL;
373 mu_iterator_current (iterator, (void **) &capa); 373 mu_iterator_current (iterator, (void **) &capa);
374 printf ("CAPA: %s\n", capa ? capa : ""); 374 mu_stream_printf (mustrout, "CAPA: %s\n", capa ? capa : "");
375 } 375 }
376 mu_iterator_destroy (&iterator); 376 mu_iterator_destroy (&iterator);
377 } 377 }
...@@ -385,6 +385,7 @@ com_uidl (int argc, char **argv) ...@@ -385,6 +385,7 @@ com_uidl (int argc, char **argv)
385 int status = 0; 385 int status = 0;
386 if (argc == 1) 386 if (argc == 1)
387 { 387 {
388 mu_stream_t out = mutool_open_pager ();
388 mu_iterator_t uidl_iterator = NULL; 389 mu_iterator_t uidl_iterator = NULL;
389 status = mu_pop3_uidl_all (pop3, &uidl_iterator); 390 status = mu_pop3_uidl_all (pop3, &uidl_iterator);
390 if (status == 0) 391 if (status == 0)
...@@ -395,10 +396,11 @@ com_uidl (int argc, char **argv) ...@@ -395,10 +396,11 @@ com_uidl (int argc, char **argv)
395 { 396 {
396 char *uidl = NULL; 397 char *uidl = NULL;
397 mu_iterator_current (uidl_iterator, (void **) &uidl); 398 mu_iterator_current (uidl_iterator, (void **) &uidl);
398 printf ("UIDL: %s\n", uidl ? uidl : ""); 399 mu_stream_printf (out, "UIDL: %s\n", uidl ? uidl : "");
399 } 400 }
400 mu_iterator_destroy (&uidl_iterator); 401 mu_iterator_destroy (&uidl_iterator);
401 } 402 }
403 mu_stream_destroy (&out);
402 } 404 }
403 else 405 else
404 { 406 {
...@@ -406,7 +408,7 @@ com_uidl (int argc, char **argv) ...@@ -406,7 +408,7 @@ com_uidl (int argc, char **argv)
406 unsigned int msgno = strtoul (argv[1], NULL, 10); 408 unsigned int msgno = strtoul (argv[1], NULL, 10);
407 status = mu_pop3_uidl (pop3, msgno, &uidl); 409 status = mu_pop3_uidl (pop3, msgno, &uidl);
408 if (status == 0) 410 if (status == 0)
409 printf ("Msg: %d UIDL: %s\n", msgno, uidl ? uidl : ""); 411 mu_stream_printf (mustrout, "Msg: %d UIDL: %s\n", msgno, uidl ? uidl : "");
410 free (uidl); 412 free (uidl);
411 } 413 }
412 return status; 414 return status;
...@@ -418,6 +420,7 @@ com_list (int argc, char **argv) ...@@ -418,6 +420,7 @@ com_list (int argc, char **argv)
418 int status = 0; 420 int status = 0;
419 if (argc == 1) 421 if (argc == 1)
420 { 422 {
423 mu_stream_t out = mutool_open_pager ();
421 mu_iterator_t list_iterator; 424 mu_iterator_t list_iterator;
422 status = mu_pop3_list_all (pop3, &list_iterator); 425 status = mu_pop3_list_all (pop3, &list_iterator);
423 if (status == 0) 426 if (status == 0)
...@@ -428,9 +431,10 @@ com_list (int argc, char **argv) ...@@ -428,9 +431,10 @@ com_list (int argc, char **argv)
428 { 431 {
429 char *list = NULL; 432 char *list = NULL;
430 mu_iterator_current (list_iterator, (void **) &list); 433 mu_iterator_current (list_iterator, (void **) &list);
431 printf ("LIST: %s\n", (list) ? list : ""); 434 mu_stream_printf (out, "LIST: %s\n", (list) ? list : "");
432 } 435 }
433 mu_iterator_destroy (&list_iterator); 436 mu_iterator_destroy (&list_iterator);
437 mu_stream_destroy (&out);
434 } 438 }
435 } 439 }
436 else 440 else
...@@ -439,7 +443,7 @@ com_list (int argc, char **argv) ...@@ -439,7 +443,7 @@ com_list (int argc, char **argv)
439 unsigned int msgno = strtoul (argv[1], NULL, 10); 443 unsigned int msgno = strtoul (argv[1], NULL, 10);
440 status = mu_pop3_list (pop3, msgno, &size); 444 status = mu_pop3_list (pop3, msgno, &size);
441 if (status == 0) 445 if (status == 0)
442 printf ("Msg: %u Size: %lu\n", msgno, (unsigned long) size); 446 mu_stream_printf (mustrout, "Msg: %u Size: %lu\n", msgno, (unsigned long) size);
443 } 447 }
444 return status; 448 return status;
445 } 449 }
...@@ -506,7 +510,7 @@ com_stat (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) ...@@ -506,7 +510,7 @@ com_stat (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
506 int status = 0; 510 int status = 0;
507 511
508 status = mu_pop3_stat (pop3, &count, &size); 512 status = mu_pop3_stat (pop3, &count, &size);
509 printf ("Mesgs: %lu Size %lu\n", 513 mu_stream_printf (mustrout, "Mesgs: %lu Size %lu\n",
510 (unsigned long) count, (unsigned long) size); 514 (unsigned long) count, (unsigned long) size);
511 return status; 515 return status;
512 } 516 }
...@@ -549,10 +553,9 @@ com_top (int argc, char **argv) ...@@ -549,10 +553,9 @@ com_top (int argc, char **argv)
549 553
550 if (status == 0) 554 if (status == 0)
551 { 555 {
552 size_t n = 0; 556 mu_stream_t out = mutool_open_pager ();
553 char buf[128]; 557 mu_stream_copy (out, stream, 0, NULL);
554 while ((mu_stream_readline (stream, buf, sizeof buf, &n) == 0) && n) 558 mu_stream_destroy (&out);
555 printf ("%s", buf);
556 mu_stream_destroy (&stream); 559 mu_stream_destroy (&stream);
557 } 560 }
558 return status; 561 return status;
...@@ -570,10 +573,9 @@ com_retr (int argc, char **argv) ...@@ -570,10 +573,9 @@ com_retr (int argc, char **argv)
570 573
571 if (status == 0) 574 if (status == 0)
572 { 575 {
573 size_t n = 0; 576 mu_stream_t out = mutool_open_pager ();
574 char buf[128]; 577 mu_stream_copy (out, stream, 0, NULL);
575 while ((mu_stream_readline (stream, buf, sizeof buf, &n) == 0) && n) 578 mu_stream_destroy (&out);
576 printf ("%s", buf);
577 mu_stream_destroy (&stream); 579 mu_stream_destroy (&stream);
578 } 580 }
579 return status; 581 return status;
...@@ -706,11 +708,11 @@ com_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) ...@@ -706,11 +708,11 @@ com_quit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
706 } 708 }
707 else 709 else
708 { 710 {
709 printf ("Try 'exit' to leave %s\n", mu_program_name); 711 mu_stream_printf (mustrout, "Try 'exit' to leave %s\n", mu_program_name);
710 } 712 }
711 } 713 }
712 else 714 else
713 printf ("Try 'exit' to leave %s\n", mu_program_name); 715 mu_stream_printf (mustrout, "Try 'exit' to leave %s\n", mu_program_name);
714 return status; 716 return status;
715 } 717 }
716 718
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
32 32
33 char *mutool_shell_prompt; 33 char *mutool_shell_prompt;
34 mu_vartab_t mutool_prompt_vartab; 34 mu_vartab_t mutool_prompt_vartab;
35 int mutool_shell_interactive;
36 mu_stream_t mustrout;
35 37
36 static char * 38 static char *
37 expand_prompt () 39 expand_prompt ()
...@@ -65,25 +67,25 @@ struct mutool_command default_comtab[] = { ...@@ -65,25 +67,25 @@ struct mutool_command default_comtab[] = {
65 67
66 /* Print a single comtab entry */ 68 /* Print a single comtab entry */
67 static void 69 static void
68 print_comtab (struct mutool_command *tab) 70 print_comtab (mu_stream_t stream, struct mutool_command *tab)
69 { 71 {
70 printf ("%s\t\t%s\n", tab->name, tab->doc); 72 mu_stream_printf (stream, "%s\t\t%s\n", tab->name, tab->doc);
71 } 73 }
72 74
73 /* Print a single comtab entry. 75 /* Print a single comtab entry.
74 FIXME: Way too primitive. Rewrite. */ 76 FIXME: Way too primitive. Rewrite. */
75 int 77 int
76 print_help (struct mutool_command *tab, size_t n) 78 print_help (mu_stream_t stream, struct mutool_command *tab, size_t n)
77 { 79 {
78 if (n) 80 if (n)
79 { 81 {
80 for (; n > 0 && tab->name; tab++, n--) 82 for (; n > 0 && tab->name; tab++, n--)
81 print_comtab (tab); 83 print_comtab (stream, tab);
82 } 84 }
83 else 85 else
84 { 86 {
85 for (; tab->name; tab++) 87 for (; tab->name; tab++)
86 print_comtab (tab); 88 print_comtab (stream, tab);
87 } 89 }
88 return 0; 90 return 0;
89 } 91 }
...@@ -102,16 +104,16 @@ list_commands (struct mutool_command *tab, const char *name) ...@@ -102,16 +104,16 @@ list_commands (struct mutool_command *tab, const char *name)
102 if (printed == 6) 104 if (printed == 6)
103 { 105 {
104 printed = 0; 106 printed = 0;
105 printf ("\n"); 107 mu_stream_printf (mustrout, "\n");
106 } 108 }
107 if (mu_c_strncasecmp (tab->name, name, namelen) == 0) 109 if (mu_c_strncasecmp (tab->name, name, namelen) == 0)
108 { 110 {
109 printf ("%s\t", tab->name); 111 mu_stream_printf (mustrout, "%s\t", tab->name);
110 printed++; 112 printed++;
111 } 113 }
112 } 114 }
113 if (printed && printed < 6) 115 if (printed && printed < 6)
114 printf ("\n"); 116 mu_stream_printf (mustrout, "\n");
115 } 117 }
116 118
117 static struct mutool_command * 119 static struct mutool_command *
...@@ -139,23 +141,28 @@ int ...@@ -139,23 +141,28 @@ int
139 shell_help (int argc, char **argv) 141 shell_help (int argc, char **argv)
140 { 142 {
141 char *name = argv[1]; 143 char *name = argv[1];
144
142 if (name) 145 if (name)
143 { 146 {
144 struct mutool_command *com = find_command (argv[1]); 147 struct mutool_command *com = find_command (argv[1]);
145 148
146 if (com) 149 if (com)
147 print_comtab (com); 150 print_comtab (mustrout, com);
148 else 151 else
149 { 152 {
150 printf ("No commands match `%s'. Possibilties are:\n", name); 153 mu_stream_printf (mustrout,
154 "No commands match `%s'. Possibilties are:\n",
155 name);
151 list_commands (shell_comtab, name); 156 list_commands (shell_comtab, name);
152 } 157 }
153 } 158 }
154 else 159 else
155 { 160 {
156 print_help (shell_comtab, user_command_count); 161 mu_stream_t str = mutool_open_pager ();
157 printf ("\n"); 162 print_help (str, shell_comtab, user_command_count);
158 print_help (shell_comtab + user_command_count, 0); 163 mu_stream_printf (str, "\n");
164 print_help (str, shell_comtab + user_command_count, 0);
165 mu_stream_destroy (&str);
159 } 166 }
160 return 0; 167 return 0;
161 } 168 }
...@@ -173,6 +180,21 @@ shell_prompt (int argc, char **argv) ...@@ -173,6 +180,21 @@ shell_prompt (int argc, char **argv)
173 return 0; 180 return 0;
174 } 181 }
175 182
183 mu_stream_t
184 mutool_open_pager ()
185 {
186 char *pager;
187 if (mutool_shell_interactive && (pager = getenv ("PAGER")) != NULL)
188 {
189 mu_stream_t stream;
190 int rc = mu_prog_stream_create (&stream, pager, MU_STREAM_WRITE);
191 if (rc == 0)
192 return stream;
193 mu_error (_("cannot start pager: %s"), mu_strerror (rc));
194 }
195 mu_stream_ref (mustrout);
196 return mustrout;
197 }
176 198
177 199
178 #ifdef WITH_READLINE 200 #ifdef WITH_READLINE
...@@ -313,7 +335,7 @@ retrieve_history (char *str) ...@@ -313,7 +335,7 @@ retrieve_history (char *str)
313 return 1; 335 return 1;
314 336
315 case 2: 337 case 2:
316 printf ("%s\n", out); 338 mu_stream_printf (mustrout, "%s\n", out);
317 free (out); 339 free (out);
318 return 1; 340 return 1;
319 } 341 }
...@@ -328,7 +350,7 @@ shell_history (int argc, char **argv) ...@@ -328,7 +350,7 @@ shell_history (int argc, char **argv)
328 350
329 hlist = history_list (); 351 hlist = history_list ();
330 for (i = 0; i < history_length; i++) 352 for (i = 0; i < history_length; i++)
331 printf ("%4d) %s\n", i + 1, hlist[i]->line); 353 mu_stream_printf (mustrout, "%4d) %s\n", i + 1, hlist[i]->line);
332 354
333 return 0; 355 return 0;
334 } 356 }
...@@ -345,7 +367,7 @@ readline (char *prompt) ...@@ -345,7 +367,7 @@ readline (char *prompt)
345 367
346 if (prompt) 368 if (prompt)
347 { 369 {
348 printf ("%s", prompt); 370 mu_stream_printf (mustrout, "%s", prompt);
349 fflush (stdout); 371 fflush (stdout);
350 } 372 }
351 if (getline (&buf, &size, stdin) <= 0) 373 if (getline (&buf, &size, stdin) <= 0)
...@@ -440,9 +462,20 @@ shell_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED) ...@@ -440,9 +462,20 @@ shell_exit (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
440 int 462 int
441 mutool_shell (const char *name, struct mutool_command *cmd) 463 mutool_shell (const char *name, struct mutool_command *cmd)
442 { 464 {
465 int rc;
443 size_t n; 466 size_t n;
444 int interactive = isatty (0); 467 char *(*input_line) ();
445 char *(*input_line) () = interactive ? 468
469 rc = mu_stdio_stream_create (&mustrout, MU_STDOUT_FD,
470 MU_STREAM_WRITE);
471 if (rc)
472 {
473 mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", "1", rc);
474 return 1;
475 }
476
477 mutool_shell_interactive = isatty (0);
478 input_line = mutool_shell_interactive ?
446 input_line_interactive : input_line_script; 479 input_line_interactive : input_line_script;
447 480
448 for (n = 0; cmd[n].name; n++) 481 for (n = 0; cmd[n].name; n++)
...@@ -471,7 +504,7 @@ mutool_shell (const char *name, struct mutool_command *cmd) ...@@ -471,7 +504,7 @@ mutool_shell (const char *name, struct mutool_command *cmd)
471 int status; 504 int status;
472 505
473 #ifdef WITH_READLINE 506 #ifdef WITH_READLINE
474 if (interactive) 507 if (mutool_shell_interactive)
475 { 508 {
476 if (retrieve_history (s)) 509 if (retrieve_history (s))
477 continue; 510 continue;
...@@ -486,7 +519,8 @@ mutool_shell (const char *name, struct mutool_command *cmd) ...@@ -486,7 +519,8 @@ mutool_shell (const char *name, struct mutool_command *cmd)
486 519
487 free (line); 520 free (line);
488 } 521 }
489 if (interactive) 522 if (mutool_shell_interactive)
490 finish_readline (); 523 finish_readline ();
524 mu_stream_destroy (&mustrout);
491 return 0; 525 return 0;
492 } 526 }
......