diff --git a/README.md b/README.md index e3166741..bb056a8a 100644 --- a/README.md +++ b/README.md @@ -219,7 +219,7 @@ optional args: -n use version compare to sort -p file selection file (stdout if '-') -s string filters [default: regex] - -S disk usage mode + -S du mode -v show version -h show help ``` diff --git a/src/nnn.c b/src/nnn.c index 89d7ded3..e2565bc0 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -205,8 +205,10 @@ disabledbg() #define CRC8_TABLE_LEN 256 /* Version compare macros */ -/* states: S_N: normal, S_I: comparing integral part, S_F: comparing - fractionnal parts, S_Z: idem but with leading Zeroes only */ +/* + * states: S_N: normal, S_I: comparing integral part, S_F: comparing + * fractionnal parts, S_Z: idem but with leading Zeroes only + */ #define S_N 0x0 #define S_I 0x3 #define S_F 0x6 @@ -471,7 +473,7 @@ static const char * const envs[] = { /* Forward declarations */ static void redraw(char *path); static void spawn(const char *file, const char *arg1, const char *arg2, const char *dir, uchar flag); -static int (*nftw_fn) (const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); +static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); /* Functions */ @@ -480,7 +482,7 @@ static int (*nftw_fn) (const char *fpath, const struct stat *sb, int typeflag, s * https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code */ #if 0 // using a static table -static void crc8init() +static void crc8init(void) { uchar remainder, bit; uint dividend; @@ -511,8 +513,7 @@ static uchar crc8fast(uchar const message[], size_t n) static size_t byte; /* CRC data */ - static const uchar crc8table[CRC8_TABLE_LEN] __attribute__ ((aligned)) = - { + static const uchar crc8table[CRC8_TABLE_LEN] __attribute__ ((aligned)) = { 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, @@ -572,25 +573,27 @@ static void printprompt(const char *str) static int get_input(const char *prompt) { + int r; + if (prompt) printprompt(prompt); cleartimeout(); - int r = getch(); + r = getch(); settimeout(); return r; } -static char confirm_force() +static char confirm_force(void) { int r = get_input("use force? [y/Y]"); + if (r == 'y' || r == 'Y') return 'f'; /* forceful */ - return 'i'; /* interactive */ } /* Increase the limit on open file descriptors, if possible */ -static rlim_t max_openfds() +static rlim_t max_openfds(void) { struct rlimit rl; rlim_t limit = getrlimit(RLIMIT_NOFILE, &rl); @@ -843,8 +846,10 @@ static bool appendfpath(const char *path, const size_t len) } /* Enabling the following will miss files with newlines */ - /* if (copybufpos) - pcopybuf[copybufpos - 1] = '\n'; */ + /* + * if (copybufpos) + * pcopybuf[copybufpos - 1] = '\n'; + */ copybufpos += xstrlcpy(pcopybuf + copybufpos, path, len); @@ -877,7 +882,7 @@ static ssize_t selectiontofd(int fd) return pos; } -static bool showcplist() +static bool showcplist(void) { int fd; ssize_t pos; @@ -906,7 +911,7 @@ static bool showcplist() return TRUE; } -static bool cpsafe() +static bool cpsafe(void) { /* Fail if copy file path not generated */ if (!g_cppath[0]) { @@ -1247,10 +1252,11 @@ static int xstrverscmp(const char * const s1, const char * const s2) p1 = (const uchar *)s1; p2 = (const uchar *)s2; - /* Symbol(s) 0 [1-9] others - Transition (10) 0 (01) d (00) x */ - static const uint8_t next_state[] = - { + /* + * Symbol(s) 0 [1-9] others + * Transition (10) 0 (01) d (00) x + */ + static const uint8_t next_state[] = { /* state x d 0 */ /* S_N */ S_N, S_I, S_Z, /* S_I */ S_N, S_I, S_I, @@ -1258,14 +1264,13 @@ static int xstrverscmp(const char * const s1, const char * const s2) /* S_Z */ S_N, S_F, S_Z }; - static const int8_t result_type[] __attribute__ ((aligned)) = - { + static const int8_t result_type[] __attribute__ ((aligned)) = { /* state x/x x/d x/0 d/x d/d d/0 0/x 0/d 0/0 */ /* S_N */ VCMP, VCMP, VCMP, VCMP, VLEN, VCMP, VCMP, VCMP, VCMP, - /* S_I */ VCMP, -1, -1, +1, VLEN, VLEN, +1, VLEN, VLEN, + /* S_I */ VCMP, -1, -1, 1, VLEN, VLEN, 1, VLEN, VLEN, /* S_F */ VCMP, VCMP, VCMP, VCMP, VCMP, VCMP, VCMP, VCMP, VCMP, - /* S_Z */ VCMP, +1, +1, -1, VCMP, VCMP, -1, VCMP, VCMP + /* S_Z */ VCMP, 1, 1, -1, VCMP, VCMP, -1, VCMP, VCMP }; if (p1 == p2) @@ -1293,10 +1298,10 @@ static int xstrverscmp(const char * const s1, const char * const s2) case VCMP: return diff; case VLEN: - while (xisdigit (*p1++)) - if (!xisdigit (*p2++)) + while (xisdigit(*p1++)) + if (!xisdigit(*p2++)) return 1; - return xisdigit (*p2) ? -1 : diff; + return xisdigit(*p2) ? -1 : diff; default: return state; } @@ -1435,7 +1440,7 @@ static int nextsel(int *presel) /* * Move non-matching entries to the end */ -static int fill(char* fltr, regex_t *re) +static int fill(char *fltr, regex_t *re) { static int count; static struct entry _dent, *pdent1, *pdent2; @@ -1645,7 +1650,7 @@ static char *xreadline(char *prefill, char *prompt) case '\n': // fallthrough case '\r': goto END; - case 127: /* Handle DEL */ // fallthrough + case 127: // fallthrough case '\b': /* rhel25 sends '\b' for backspace */ if (pos > 0) { memmove(buf + pos - 1, buf + pos, (len - pos) << 2); @@ -1784,11 +1789,12 @@ static int xlink(char *suffix, char *path, char *buf, int type) return count; } -static bool parsebmstr() +static bool parsebmstr(void) { int i = 0; char *bms = getenv(env_cfg[NNN_BMS]); char *nextkey = bms; + if (!bms || !*bms) return TRUE; @@ -2209,7 +2215,8 @@ static char *get_output(char *buf, size_t bytes, char *file, char *arg1, char *a return NULL; } -static bool getutil(char *util) { +static bool getutil(char *util) +{ if (!get_output(g_buf, CMD_LEN_MAX, "which", util, NULL, FALSE)) return FALSE; @@ -2267,6 +2274,7 @@ static bool show_stats(char *fpath, char *fname, struct stat *sb) if (len != -1) { struct stat tgtsb; + if (!stat(fpath, &tgtsb) && S_ISDIR(tgtsb.st_mode)) g_buf[len++] = '/'; @@ -2413,39 +2421,39 @@ static bool show_help(char *path) fd = mkstemp(g_tmpfpath); static char helpstr[] = { -"0\n" -"1NAVIGATION\n" - "a↑ k Up PgUp ^U Scroll up\n" - "a↓ j Down PgDn ^D Scroll down\n" - "a← h Parent dir ~ Go HOME\n" - "8↵ → l Open file/dir & Start dir\n" - "4Home g ^A First entry - Last visited dir\n" - "5End G ^E Last entry . Toggle show hidden\n" - "c/ Filter Ins ^T Toggle nav-as-you-type\n" - "cb Pin current dir ^B Go to pinned dir\n" - "7Tab ^I Next context d Toggle detail view\n" - "9, ^/ Leader key N LeadN Go to/create context N\n" - "aEsc Exit prompt ^L Redraw/clear prompt\n" - "b^G Quit and cd q Quit context\n" - "9Q ^Q Quit ? Help, config\n" -"1FILES\n" - "b^O Open with... n Create new/link\n" - "cD File details ^R Rename entry\n" - "9⎵ ^K Select entry r Open dir in vidir\n" - "b^Y Toggle selection y List selection\n" - "cY Select all\n" - "cP Copy selection X Delete selection\n" - "cV Move selection ^X Delete entry\n" - "cf Archive files m M Brief/full media info\n" - "b^F Extract archive F List archive\n" - "ce Edit in EDITOR p Open in PAGER\n" -"1ORDER TOGGLES\n" - "b^J Disk usage S Apparent du\n" - "ct Time modified s Size\n" -"1MISC\n" - "9! ^] Spawn SHELL C Execute entry\n" - "9R ^V Run/pick script L Lock terminal\n" - "b^P Command prompt ^N Take note\n"}; + "0\n" + "1NAVIGATION\n" + "a↑ k Up PgUp ^U Scroll up\n" + "a↓ j Down PgDn ^D Scroll down\n" + "a← h Parent dir ~ Go HOME\n" + "8↵ → l Open file/dir & Start dir\n" + "4Home g ^A First entry - Last visited dir\n" + "5End G ^E Last entry . Toggle show hidden\n" + "c/ Filter Ins ^T Toggle nav-as-you-type\n" + "cb Pin current dir ^B Go to pinned dir\n" + "7Tab ^I Next context d Toggle detail view\n" + "9, ^/ Leader key N LeadN Go to/create context N\n" + "aEsc Exit prompt ^L Redraw/clear prompt\n" + "b^G Quit and cd q Quit context\n" + "9Q ^Q Quit ? Help, config\n" + "1FILES\n" + "b^O Open with... n Create new/link\n" + "cD File details ^R Rename entry\n" + "9⎵ ^K Select entry r Open dir in vidir\n" + "b^Y Toggle selection y List selection\n" + "cY Select all\n" + "cP Copy selection X Delete selection\n" + "cV Move selection ^X Delete entry\n" + "cf Archive files m M Brief/full media info\n" + "b^F Extract archive F List archive\n" + "ce Edit in EDITOR p Open in PAGER\n" + "1ORDER TOGGLES\n" + "b^J Disk usage S Apparent du\n" + "ct Time modified s Size\n" + "1MISC\n" + "9! ^] Spawn SHELL C Execute entry\n" + "9R ^V Run/pick script L Lock terminal\n" + "b^P Command prompt ^N Take note\n"}; if (fd == -1) return FALSE; @@ -2972,9 +2980,8 @@ begin: } #ifdef LINUX_INOTIFY - if (presel != FILTER && inotify_wd == -1) { + if (presel != FILTER && inotify_wd == -1) inotify_wd = inotify_add_watch(inotify_fd, path, INOTIFY_MASK); - } #elif defined(BSD_KQUEUE) if (presel != FILTER && event_fd == -1) { #if defined(O_EVTONLY) @@ -3223,21 +3230,19 @@ nochange: case '4': r = fd - '1'; /* Save the next context id */ if (cfg.curctx == r) { - if (sel == SEL_CYCLE) { - (r == CTX_MAX - 1) ? (r = 0) : ++r; - snprintf(newpath, PATH_MAX, - "Create context %d? [Enter]", r + 1); - fd = get_input(newpath); - if (fd != '\r') - continue; - } else + if (sel != SEL_CYCLE) + continue; + + (r == CTX_MAX - 1) ? (r = 0) : ++r; + snprintf(newpath, PATH_MAX, + "Create context %d? [Enter]", r + 1); + fd = get_input(newpath); + if (fd != '\r') continue; } - #ifdef DIR_LIMITED_COPY g_crc = 0; #endif - /* Save current context */ xstrlcpy(g_ctx[cfg.curctx].c_name, dents[cur].name, NAME_MAX + 1); g_ctx[cfg.curctx].c_cfg = cfg; @@ -3425,7 +3430,8 @@ nochange: copycurname(); goto begin; case SEL_RENAMEALL: - if ((r = getutil(utils[VIDIR]))) + r = getutil(utils[VIDIR]); + if (r) spawn(utils[VIDIR], ".", NULL, path, F_NORMAL); break; case SEL_HELP: @@ -3625,6 +3631,7 @@ nochange: break; char rm_opts[] = "-ir"; + rm_opts[1] = confirm_force(); mkpath(path, dents[cur].name, newpath); @@ -3849,8 +3856,10 @@ nochange: if (S_ISDIR(sb.st_mode)) { cfg.runscript ^= 1; if (!cfg.runscript && rundir[0]) { - /* If toggled, and still in the script dir, - switch to original directory */ + /* + * If toggled, and still in the script dir, + * switch to original directory + */ if (strcmp(path, scriptpath) == 0) { xstrlcpy(path, rundir, PATH_MAX); xstrlcpy(lastname, runfile, NAME_MAX); @@ -3967,6 +3976,7 @@ nochange: case SEL_QUITCTX: if (sel == SEL_QUITCTX) { uint iter = 1; + r = cfg.curctx; while (iter < CTX_MAX) { (r == CTX_MAX - 1) ? (r = 0) : ++r; @@ -4004,7 +4014,7 @@ nochange: static void usage(void) { fprintf(stdout, - "usage: nnn [-b key] [-C] [-e] [-i] [-l] [-n]\n" + "%s: nnn [-b key] [-C] [-e] [-i] [-l] [-n]\n" " [-p file] [-s] [-S] [-v] [-h] [PATH]\n\n" "The missing terminal file manager for X.\n\n" "positional args:\n" @@ -4018,10 +4028,10 @@ static void usage(void) " -n use version compare to sort\n" " -p file selection file (stdout if '-')\n" " -s string filters [default: regex]\n" - " -S disk usage mode\n" + " -S du mode\n" " -v show version\n" " -h show help\n\n" - "v%s\n%s\n", VERSION, GENERAL_INFO); + "v%s\n%s\n", __func__, VERSION, GENERAL_INFO); } int main(int argc, char *argv[]) @@ -4113,10 +4123,10 @@ int main(int argc, char *argv[]) } /* Parse bookmarks string */ - if (!parsebmstr()) { + if (!parsebmstr()) { fprintf(stderr, "%s: malformed\n", env_cfg[NNN_BMS]); return 1; - } + } if (ipath) { /* Open a bookmark directly */ if (ipath[1] || get_bm_loc(*ipath, cwd) == NULL) { @@ -4228,6 +4238,7 @@ int main(int argc, char *argv[]) /* Ignore/handle certain signals */ struct sigaction act; + memset(&act, 0, sizeof(act)); act.sa_sigaction = &sigint_handler; act.sa_flags = SA_SIGINFO;