diff --git a/doc/ncdu.pod b/doc/ncdu.pod index e72347d14662d7598a5861c6fda14191a1b04949..f5fcc78f9d6cadf0f681c12050dc7e4450258030 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 3a84d9f39b9af7357261ba5682ba6f8b8712710b..4a1ec41719b806ac1e1dce57784d33115bd868b4 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 b9ef0e18fdc691a7d3c3661929b9bcc58518f207..5fb207a20e9a2fe6e3631e7707c43ec14c86b40b 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 fecaa233ef9b74b15eea54cbae163452d584fd7e..b0080cddf83bbf4a724852b465d720de3cdec68a 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 d2470d2e676bff19352ce4977751f87a67a7d433..7a6f2cfe1c8eada36ec029985ae2658bfacbda2d 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;