nnn

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 3d13c7cb41bc3d7edb78b24eefc555636cd343d9
parent 234b60a89797df43592d9a11e88e1aff9ad5d1a8
Author: Arun Prakash Jana <engineerarun@gmail.com>
Date:   Sat, 15 Mar 2025 04:49:16 +0530

Fix #2010: Count from selection file when nselected is 0

Diffstat:
Msrc/nnn.c | 57++++++++++++++++++++++++++++++++++++---------------------
Msrc/nnn.h | 4++--
2 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/src/nnn.c b/src/nnn.c @@ -196,6 +196,8 @@ #define PROMPT ">>> " #undef NEWLINE #define NEWLINE "\n" +#define NEWLINE_CHAR '\n' +#define NUL_CHAR '\0' #define REGEX_MAX 48 #define ENTRY_INCR 64 /* Number of dir 'entry' structures to allocate per shot */ #define NAMEBUF_INCR 0x800 /* 64 dir entries at once, avg. 32 chars per file name = 64*32B = 2KB */ @@ -1569,15 +1571,41 @@ static void xdelay(useconds_t delay) usleep(delay); } +static uint_t entries_in_file(int fd, char *buf, size_t buflen, const char delim) +{ + ssize_t len; + uint_t count = 0; + + while ((len = read(fd, buf, buflen)) > 0) + while (len) + count += (buf[--len] == delim); + + /* For all use cases 0 count is considered as error */ + return ((len < 0) ? 0 : ((delim != NUL_CHAR) ? count : ++count)); +} + static char confirm_force(bool selection, bool use_trash) { char str[300]; + /* Count selection from file when nothing is selected */ + if (selection && (nselected == 0)) { + int fd = open(selpath, O_RDONLY); + + if (fd != -1) { + nselected = entries_in_file(fd, str, 300, NUL_CHAR); + close(fd); + } else { + printwarn(NULL); + return '\0'; + } + } + /* Note: ideally we should use utils[UTIL_RM_RF] instead of the "rm -rf" string */ int r = snprintf(str, 20, "%s", use_trash ? utils[UTIL_GIO_TRASH] + 4 : "rm -rf"); if (selection) - snprintf(str + r, 280, " %d files?", nselected); + snprintf(str + r, 280, " %d file(s)?", nselected); else snprintf(str + r, 280, " '%s'?", pdents[cur].name); @@ -2615,19 +2643,6 @@ static void xrmfromsel(char *path, char *fpath) #endif } -static uint_t lines_in_file(int fd, char *buf, size_t buflen) -{ - ssize_t len; - uint_t count = 0; - - while ((len = read(fd, buf, buflen)) > 0) - while (len) - count += (buf[--len] == '\n'); - - /* For all use cases 0 linecount is considered as error */ - return ((len < 0) ? 0 : count); -} - static bool cpmv_rename(int choice, const char *path) { int fd; @@ -2645,7 +2660,7 @@ static bool cpmv_rename(int choice, const char *path) snprintf(buf, sizeof(buf), "tr '\\0' '\\n' < %s > %s", selpath, g_tmpfpath); spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI); - count = lines_in_file(fd, buf, sizeof(buf)); + count = entries_in_file(fd, buf, sizeof(buf), NEWLINE_CHAR); if (!count) goto finish; } else @@ -2662,7 +2677,7 @@ static bool cpmv_rename(int choice, const char *path) if (fd == -1) goto finish; - lines = lines_in_file(fd, buf, sizeof(buf)); + lines = entries_in_file(fd, buf, sizeof(buf), NEWLINE_CHAR); DPRINTF_U(count); DPRINTF_U(lines); if (!lines || (2 * count != lines)) { @@ -2713,8 +2728,8 @@ static bool cpmvrm_selection(enum action sel, char *path) return FALSE; } break; - default: /* SEL_TRASH, SEL_RM_ONLY */ - if (!rmmulstr(g_buf, trashcmd && sel == SEL_TRASH)) { + default: /* SEL_TRASH, SEL_RM_RF */ + if (!rmmulstr(g_buf, trashcmd && (sel == SEL_TRASH))) { printmsg(messages[MSG_CANCEL]); return FALSE; } @@ -2783,7 +2798,7 @@ static bool batch_rename(void) if (fd2 == -1) goto finish; - lines = lines_in_file(fd2, buf, sizeof(buf)); + lines = entries_in_file(fd2, buf, sizeof(buf), NEWLINE_CHAR); DPRINTF_U(count); DPRINTF_U(lines); if (!lines || (count != lines)) { @@ -7771,9 +7786,9 @@ nochange: case SEL_MV: // fallthrough case SEL_CPMVAS: // fallthrough case SEL_TRASH: // fallthrough - case SEL_RM_ONLY: + case SEL_RM_RF: { - if (sel == SEL_TRASH || sel == SEL_RM_ONLY) { + if ((sel == SEL_TRASH) || (sel == SEL_RM_RF)) { r = get_cur_or_sel(); if (!r) { statusbar(path); diff --git a/src/nnn.h b/src/nnn.h @@ -97,7 +97,7 @@ enum action { SEL_MV, SEL_CPMVAS, SEL_TRASH, - SEL_RM_ONLY, + SEL_RM_RF, SEL_OPENWITH, SEL_NEW, SEL_RENAME, @@ -242,7 +242,7 @@ static struct key bindings[] = { /* Delete from selection buffer */ { 'x', SEL_TRASH }, { CONTROL('X'), SEL_TRASH }, - { 'X', SEL_RM_ONLY }, + { 'X', SEL_RM_RF }, /* Open in a custom application */ { 'o', SEL_OPENWITH }, { CONTROL('O'), SEL_OPENWITH },