From 44e63ce2e7e3d4c6388ad8bc570fd540963cc0a4 Mon Sep 17 00:00:00 2001
From: Yorhel <git@yorhel.nl>
Date: Mon, 27 Aug 2012 14:17:40 +0200
Subject: [PATCH] Added -u option to change the scan UI

This allows scanning stuff without initializing ncurses. Not too useful
at this point since ncdu will switch to an ncurses environment when it's
done anyway, but this will become more useful when the export-to-file
feature has been implemented.
---
 doc/ncdu.pod     | 11 +++++++
 src/browser.c    |  1 +
 src/dir.h        |  1 +
 src/dir_common.c | 29 +++++++++++++++---
 src/main.c       | 79 ++++++++++++++++++++++++++++++++++--------------
 5 files changed, 94 insertions(+), 27 deletions(-)

diff --git a/doc/ncdu.pod b/doc/ncdu.pod
index e72347d..f5fcc78 100644
--- a/doc/ncdu.pod
+++ b/doc/ncdu.pod
@@ -30,6 +30,17 @@ Quiet mode. While calculating disk space, ncdu will update the screen 10 times
 a second by default, this will be decreased to once every 2 seconds in quiet
 mode. Use this feature to save bandwidth over remote connections.
 
+=item -u I<0,1,2>
+
+Interface used to give feedback on scanning progress. C<0> will prevent any
+output from being displayed before ncdu is done scanning, while C<1> will
+display compact progress information on a single line of output. C<2> presents
+a full-screen ncurses interface while scanning (the default). C<0> and C<1> do
+not initialize ncurses before the directory has been scanned, while C<2> is the
+only interface that provides feedback on recoverable errors. This does not
+affect the interface used when re-scanning a directory from the ncurses
+browser, where the full ncurses interface is always used.
+
 =item -r
 
 Read-only mode. This will disable the built-in file deletion feature.
diff --git a/src/browser.c b/src/browser.c
index 3a84d9f..4a1ec41 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -346,6 +346,7 @@ int browse_key(int ch) {
     /* and other stuff */
     case 'r':
       if(sel != NULL) {
+        dir_ui = 2;
         dir_mem_init(sel->parent);
         dir_scan_init(getpath(sel->parent));
       }
diff --git a/src/dir.h b/src/dir.h
index b9ef0e1..5fb207a 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -122,6 +122,7 @@ void dir_seterr(const char *, ...);
  * call. */
 struct dir *dir_createstruct(const char *);
 
+extern int dir_ui;
 int dir_key(int);
 void dir_draw();
 
diff --git a/src/dir_common.c b/src/dir_common.c
index fecaa23..b0080cd 100644
--- a/src/dir_common.c
+++ b/src/dir_common.c
@@ -27,12 +27,14 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <stdarg.h>
 
 
 char *dir_curpath;   /* Full path of the last seen item. */
 struct dir_output dir_output;
 char *dir_fatalerr; /* Error message on a fatal error. (NULL if there was no fatal error) */
+int dir_ui;         /* User interface to use */
 static char *lasterr; /* Path where the last error occured. */
 static int curpathl; /* Allocated length of dir_curpath */
 static int lasterrl; /* ^ of lasterr */
@@ -171,14 +173,31 @@ static void draw_error(char *cur, char *msg) {
 
 
 void dir_draw() {
-  browse_draw();
-  if(dir_fatalerr)
-    draw_error(dir_curpath, dir_fatalerr);
-  else
-    draw_progress();
+  switch(dir_ui) {
+  case 0:
+    if(dir_fatalerr)
+      fprintf(stderr, "%s.\n", dir_fatalerr);
+    break;
+  case 1:
+    if(dir_fatalerr)
+      fprintf(stderr, "\r%s.\n", dir_fatalerr);
+    else
+      fprintf(stderr, "\r%-55s %8ld files /%s",
+        cropstr(dir_curpath, 55), dir_output.items, formatsize(dir_output.size));
+    break;
+  case 2:
+    browse_draw();
+    if(dir_fatalerr)
+      draw_error(dir_curpath, dir_fatalerr);
+    else
+      draw_progress();
+    break;
+  }
 }
 
 
+/* This function can't be called unless dir_ui == 2
+ * (Doesn't really matter either way). */
 int dir_key(int ch) {
   if(dir_fatalerr)
     return 1;
diff --git a/src/main.c b/src/main.c
index d2470d2..7a6f2cf 100644
--- a/src/main.c
+++ b/src/main.c
@@ -26,6 +26,7 @@
 #include "global.h"
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <errno.h>
 
@@ -39,6 +40,7 @@ int read_only = 0;
 long update_delay = 100;
 
 static int min_rows = 17, min_cols = 60;
+static int ncurses_init = 0;
 static long lastupdate = 999;
 
 
@@ -61,7 +63,6 @@ int input_handle(int wait) {
   int ch;
   struct timeval tv;
 
-  nodelay(stdscr, wait?1:0);
   if(wait != 1)
     screen_draw();
   else {
@@ -72,6 +73,12 @@ int input_handle(int wait) {
       lastupdate = tv.tv_usec;
     }
   }
+
+  /* No actual input handling is done if ncurses hasn't been initialized yet. */
+  if(!ncurses_init)
+    return wait == 0 ? 1 : 0;
+
+  nodelay(stdscr, wait?1:0);
   while((ch = getch()) != ERR) {
     if(ch == KEY_RESIZE) {
       if(ncresize(min_rows, min_cols))
@@ -97,18 +104,24 @@ int input_handle(int wait) {
 static char *argv_parse(int argc, char **argv) {
   int i, j, len;
   char *dir = NULL;
+  dir_ui = 2;
 
   /* read from commandline */
   for(i=1; i<argc; i++) {
     if(argv[i][0] == '-') {
-     /* flags requiring arguments */
-      if(argv[i][1] == 'X' || !strcmp(argv[i], "--exclude-from") || !strcmp(argv[i], "--exclude")
-          || argv[i][1] == 'e' || argv[i][1] == 'l') {
+      /* flags requiring arguments */
+      if(!strcmp(argv[i], "-X") || !strcmp(argv[i], "-u") || !strcmp(argv[i], "--exclude-from") || !strcmp(argv[i], "--exclude")) {
         if(i+1 >= argc) {
           printf("Option %s requires an argument\n", argv[i]);
           exit(1);
-        }
-        else if(strcmp(argv[i], "--exclude") == 0)
+        } else if(strcmp(argv[i], "-u") == 0) {
+          i++;
+          if(!(argv[i][0] == '0' || argv[i][0] == '1' || argv[i][0] == '2') || argv[i][1] != 0) {
+            printf("Option -u expects either 0, 1 or 2 as argument.\n");
+            exit(1);
+          }
+          dir_ui = argv[i][0]-'0';
+        } else if(strcmp(argv[i], "--exclude") == 0)
           exclude_add(argv[++i]);
         else if(exclude_addfile(argv[++i])) {
           printf("Can't open %s: %s\n", argv[i], strerror(errno));
@@ -116,7 +129,7 @@ static char *argv_parse(int argc, char **argv) {
         }
         continue;
       }
-     /* small flags */
+      /* short flags */
       len = strlen(argv[i]);
       for(j=1; j<len; j++)
         switch(argv[i][j]) {
@@ -125,18 +138,19 @@ static char *argv_parse(int argc, char **argv) {
           case 'q': update_delay = 2000;     break;
           case '?':
           case 'h':
-            printf("ncdu [-hqvx] [--exclude PATTERN] [-X FILE] directory\n\n");
+            printf("ncdu <options> <directory>\n\n");
             printf("  -h                         This help message\n");
             printf("  -q                         Quiet mode, refresh interval 2 seconds\n");
             printf("  -v                         Print version\n");
             printf("  -x                         Same filesystem\n");
             printf("  -r                         Read only\n");
+            printf("  -u <0-2>                   UI to use when scanning (0=minimal,2=verbose)\n");
             printf("  --exclude PATTERN          Exclude files that match PATTERN\n");
             printf("  -X, --exclude-from FILE    Exclude files that match any pattern in FILE\n");
             exit(0);
           case 'v':
             printf("ncdu %s\n", PACKAGE_VERSION);
-            exit(0);  
+            exit(0);
           default:
             printf("Unknown option: -%c\nSee '%s -h' for more information.\n", argv[i][j], argv[0]);
             exit(1);
@@ -148,6 +162,21 @@ static char *argv_parse(int argc, char **argv) {
 }
 
 
+/* Initializes ncurses only when not done yet. */
+static void init_nc() {
+  if(ncurses_init)
+    return;
+  ncurses_init = 1;
+  initscr();
+  cbreak();
+  noecho();
+  curs_set(0);
+  keypad(stdscr, TRUE);
+  if(ncresize(min_rows, min_cols))
+    min_rows = min_cols = 0;
+}
+
+
 /* main program */
 int main(int argc, char **argv) {
   char *dir;
@@ -160,26 +189,32 @@ int main(int argc, char **argv) {
   dir_mem_init(NULL);
   dir_scan_init(dir);
 
-  initscr();
-  cbreak();
-  noecho();
-  curs_set(0);
-  keypad(stdscr, TRUE);
-  if(ncresize(min_rows, min_cols))
-    min_rows = min_cols = 0;
+  if(dir_ui == 2)
+    init_nc();
 
   while(1) {
-    if(pstate == ST_CALC && dir_scan_process())
-      break;
-    else if(pstate == ST_DEL)
+    /* We may need to initialize/clean up the screen when switching from the
+     * (sometimes non-ncurses) CALC state to something else. */
+    if(pstate != ST_CALC) {
+      if(dir_ui == 1)
+        fputc('\n', stderr);
+      init_nc();
+    }
+
+    if(pstate == ST_CALC) {
+      if(dir_scan_process())
+        break;
+    } else if(pstate == ST_DEL)
       delete_process();
     else if(input_handle(0))
       break;
   }
 
-  erase();
-  refresh();
-  endwin();
+  if(ncurses_init) {
+    erase();
+    refresh();
+    endwin();
+  }
   exclude_clear();
 
   return 0;
-- 
GitLab