README.md | 4 +++- nnn.1 | 5 ++++- src/nnn.c | 71 ++++++++++++++++++++++++++++++++++++++--------------- diff --git a/README.md b/README.md index 3dbc27f173032720054a902244da9be1e6df67ba..bfba745b528554ccb765eb131573db17d2bdb736 100644 --- a/README.md +++ b/README.md @@ -318,7 +318,9 @@ - press ^Y (or Y) to enter selection mode. In this mode it's possible to - cherry-pick individual files one by one by pressing ^K on each entry (works across directories and contexts); or, - navigate to another file in the same directory to select a range of files -- press ^Y (or Y) _again_ to copy the paths and exit the selection mode +- press ^Y again to save the selection and exit selection mode. + +Selected files are visually indicated by a `+`. The files in the list can now be copied (P), moved (V) or removed (X). diff --git a/nnn.1 b/nnn.1 index 8bed5b1bc1850a15d5756912bba9ed4f8ce78eca..8617a4d45510a9d3c2af48adb8ac9a2f967bb0ba 100644 --- a/nnn.1 +++ b/nnn.1 @@ -265,7 +265,10 @@ (1) cherry-pick individual files one by one by pressing ^K on each entry (works across directories and contexts); or, .br (2) navigate to another file in the same directory to select a range of files. .Pp -Pressing \fI^Y\fR again saves the selection to the list and exits the selection mode. +Press \fI^Y\fR again to save the selection and exit selection mode. +.Pp +Selected files are visually indicated by a \fB+\fR. +.br The files in the list can now be copied, moved or removed using respective keyboard shortcuts. .Pp To list the selected files press \fIy\fR. diff --git a/src/nnn.c b/src/nnn.c index 4e208d6e938868cf1df5cec96ab3f32c989a8462..8951eb7085c6ed9caaf48c42a1133e1c3a09a0d4 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -184,11 +184,14 @@ #define NAMEBUF_INCR 0x800 /* 64 dir entries at once, avg. 32 chars per filename = 64*32B = 2KB */ #define DESCRIPTOR_LEN 32 #define _ALIGNMENT 0x10 /* 16-byte alignment */ #define _ALIGNMENT_MASK 0xF -#define DIR_OR_LINK_TO_DIR 0x1 #define HOME_LEN_MAX 64 #define CTX_MAX 4 #define DOT_FILTER_LEN 7 #define ASCII_MAX 128 + +/* Entry flags */ +#define DIR_OR_LINK_TO_DIR 0x1 +#define FILE_COPIED 0x10 /* Macros to define process spawn behaviour as flags */ #define F_NONE 0x00 /* no flag set */ @@ -907,6 +910,17 @@ return FALSE; } return TRUE; +} + +/* Reset copy indicators */ +static void resetcpind() +{ + int r = 0; + + /* Reset copy indicators */ + for (; r < ndents; ++r) + if (dents[r].flags & FILE_COPIED) + dents[r].flags &= ~FILE_COPIED; } /* Initialize curses mode */ @@ -1977,7 +1991,7 @@ } static void printent_long(const struct entry *ent, int sel, uint namecols) { - char timebuf[18], permbuf[4]; + char timebuf[18], permbuf[4], cp = ' '; /* Timestamp */ strftime(timebuf, 18, "%F %R", localtime(&ent->t)); @@ -1985,6 +1999,10 @@ /* Permissions */ snprintf(permbuf, 4, "%d%d%d", (ent->mode >> 6) & 7, (ent->mode >> 3) & 7, ent->mode & 7); + /* Add copy indicator */ + if (ent->flags & FILE_COPIED) + cp = '+'; + /* Trim escape chars from name */ const char *pname = unescape(ent->name, namecols); @@ -1997,39 +2015,39 @@ switch (ent->mode & S_IFMT) { case S_IFREG: if (ent->mode & 0100) - printw(" %-16.16s 0%s %8.8s* %s*\n", timebuf, permbuf, + printw("%c%-16.16s 0%s %8.8s* %s*\n", cp, timebuf, permbuf, coolsize(cfg.blkorder ? ent->blocks << BLK_SHIFT : ent->size), pname); else - printw(" %-16.16s 0%s %8.8s %s\n", timebuf, permbuf, + printw("%c%-16.16s 0%s %8.8s %s\n", cp, timebuf, permbuf, coolsize(cfg.blkorder ? ent->blocks << BLK_SHIFT : ent->size), pname); break; case S_IFDIR: if (cfg.blkorder) - printw(" %-16.16s 0%s %8.8s/ %s/\n", - timebuf, permbuf, coolsize(ent->blocks << BLK_SHIFT), pname); + printw("%c%-16.16s 0%s %8.8s/ %s/\n", + cp, timebuf, permbuf, coolsize(ent->blocks << BLK_SHIFT), pname); else - printw(" %-16.16s 0%s / %s/\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s / %s/\n", cp, timebuf, permbuf, pname); break; case S_IFLNK: if (ent->flags & DIR_OR_LINK_TO_DIR) - printw(" %-16.16s 0%s @/ %s@\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s @/ %s@\n", cp, timebuf, permbuf, pname); else - printw(" %-16.16s 0%s @ %s@\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s @ %s@\n", cp, timebuf, permbuf, pname); break; case S_IFSOCK: - printw(" %-16.16s 0%s = %s=\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s = %s=\n", cp, timebuf, permbuf, pname); break; case S_IFIFO: - printw(" %-16.16s 0%s | %s|\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s | %s|\n", cp, timebuf, permbuf, pname); break; case S_IFBLK: - printw(" %-16.16s 0%s b %s\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s b %s\n", cp, timebuf, permbuf, pname); break; case S_IFCHR: - printw(" %-16.16s 0%s c %s\n", timebuf, permbuf, pname); + printw("%c%-16.16s 0%s c %s\n", cp, timebuf, permbuf, pname); break; default: - printw(" %-16.16s 0%s %8.8s? %s?\n", timebuf, permbuf, + printw("%c%-16.16s 0%s %8.8s? %s?\n", cp, timebuf, permbuf, coolsize(cfg.blkorder ? ent->blocks << BLK_SHIFT : ent->size), pname); break; } @@ -2609,6 +2627,7 @@ /* Copy other fields */ dentp->mode = sb.st_mode; dentp->t = sb.st_mtime; dentp->size = sb.st_size; + dentp->flags = 0; if (cfg.blkorder) { if (S_ISDIR(sb.st_mode)) { @@ -2646,8 +2665,6 @@ } if (S_ISDIR(sb.st_mode)) dentp->flags |= DIR_OR_LINK_TO_DIR; - else if (dentp->flags & DIR_OR_LINK_TO_DIR) - dentp->flags &= ~DIR_OR_LINK_TO_DIR; ++n; } @@ -3463,8 +3480,13 @@ ++ncp; } else { r = mkpath(path, dents[cur].name, newpath); - /* Keep the copy buf in sync */ - copybufpos = 0; + + if (copybufpos) { + resetcpind(); + + /* Keep the copy buf in sync */ + copybufpos = 0; + } appendfpath(newpath, r); writecp(newpath, r - 1); /* Truncate NULL from end */ @@ -3472,14 +3494,20 @@ if (copier) spawn(copier, NULL, NULL, NULL, F_NOTRACE); } + dents[cur].flags |= FILE_COPIED; + printmsg(newpath); goto nochange; case SEL_COPYMUL: cfg.copymode ^= 1; if (cfg.copymode) { + if (copybufpos) { + resetcpind(); + writecp(NULL, 0); + copybufpos = 0; + } g_crc = crc8fast((uchar *)dents, ndents * sizeof(struct entry)); copystartid = cur; - copybufpos = 0; ncp = 0; printmsg("selection on"); DPRINTF_S("selection on"); @@ -3516,10 +3544,13 @@ copyendid = ndents - 1; } if ((!ncp && copystartid < copyendid) || sel == SEL_COPYALL) { - for (r = copystartid; r <= copyendid; ++r) + for (r = copystartid; r <= copyendid; ++r) { if (!appendfpath(newpath, mkpath(path, dents[r].name, newpath))) goto nochange; + + dents[r].flags |= FILE_COPIED; + } mvprintw(LINES - 1, 0, "%d files selected\n", copyendid - copystartid + 1);