aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Arun Prakash Jana <engineerarun@gmail.com>2019-11-29 20:58:12 +0530
committerGravatar Arun Prakash Jana <engineerarun@gmail.com>2019-11-29 20:58:12 +0530
commitf9058e1aaab38fd5f31a362382b26d1986933703 (patch)
tree68a4ce59f33a7b0063428f43f0a922e1b3062fcb
parent965499c671a27239ef481f211eef13412e5c81de (diff)
downloadnnn-f9058e1aaab38fd5f31a362382b26d1986933703.tar.gz
Support link creation for hovered file
-rw-r--r--LICENSEbin1472 -> 1024 bytes
-rw-r--r--nnn.112
-rw-r--r--src/nnn.c81
3 files changed, 55 insertions, 38 deletions
diff --git a/LICENSE b/LICENSE
index 65bba60..06d7405 100644
--- a/LICENSE
+++ b/LICENSE
Binary files differ
diff --git a/nnn.1 b/nnn.1
index 870ae5b..7e7f3eb 100644
--- a/nnn.1
+++ b/nnn.1
@@ -154,23 +154,19 @@ auto selects the directory and enters it in this mode.
.Sh SELECTION
There are 3 groups of shortcuts to add files to selection:
.Pp
-(1) add an individual file to selection
+(1) hovered file selection toggle (indicated by '+' symbol on/off)
.br
(2) add a range of files to selection
.br
(3) add all files in the current directory to selection
.Pp
-Selected files are visually indicated by a \fI+\fR before the entries.
-.br
The selection can now be listed, copied, moved, removed, archived or linked.
-.br
+.Pp
Absolute paths of the selected files are copied to the temporary file \fB.selection\fR in the config directory. The path is shown in the help and configuration screen. If \fB$NNN_COPIER\fR is set (see ENVIRONMENT section below) the file paths are also copied to the system clipboard.
.Pp
-Repeat range selection on the same entry to clear selection. It's also possible to edit the current selection.
+To flush the selection without running any operation use the _edit, flush selection_ key. The list is flushed even if unchanged. Use this key to remove a file from selection after you navigate away from its directory.
.Pp
-Deselecting a single file is not implemented because substantial string processing would be required if thousands of files are selected. It would have been trivial if the selection was limited to a single directory (use a flag for each file and select the files with the flag set). However,
-.Nm
-allows selection across directories making it non-trivial to do that. Also, the buffer used to select is a compact one (no byte wasted) so \fBmemmove\fR() would be required to deselect each intermediate file. Considering these, the alternatives were chosen.
+Repeat range selection on the same entry twice to clear selection completely.
.Sh FILE SIZE
The minimum file size unit is byte (B). The rest are K, M, G, T, P, E, Z, Y (powers of 1024), same as the default units in \fIls\fR.
.Sh ENVIRONMENT
diff --git a/src/nnn.c b/src/nnn.c
index ce63afd..72ab596 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -411,10 +411,10 @@ static char * const utils[] = {
#define MSG_FAILED 6
#define MSG_SSN_NAME 7
#define MSG_CP_MV_AS 8
-#define MSG_RENAME_SEL 9
+#define MSG_RENAME_OPTS 9
#define MSG_FORCE_RM 10
#define MSG_CREATE_CTX 11
-#define MSG_ARCHIVE_SEL 12
+#define MSG_CUR_SEL_OPTS 12
#define MSG_NEW_OPTS 13
#define MSG_CLI_MODE 14
#define MSG_OVERWRITE 15
@@ -454,10 +454,10 @@ static const char * const messages[] = {
"failed!",
"session name: ",
"'c'p / 'm'v as?",
- "rename sel?",
+ "'c'urrent dir / 's'election?",
"forcibly remove %s file%s (unrecoverable)?",
- "Create context %d?",
- "archive sel?",
+ "create context %d?",
+ "'c'urrent / 's'election?",
"'f'ile / 'd'ir / 's'ym / 'h'ard?",
"cli mode?",
"overwrite?",
@@ -1516,6 +1516,20 @@ static bool batch_rename(const char *path)
char foriginal[TMP_LEN_MAX] = {0};
char buf[sizeof(batchrenamecmd) + (PATH_MAX << 1)];
+ if (selbufpos) {
+ if (ndents) {
+ i = get_input(messages[MSG_RENAME_OPTS]);
+ if (i == 'c') {
+ selbufpos = 0; /* Clear the selection */
+ dir = TRUE;
+ } else if (i != 's')
+ return ret;
+ }
+ } else if (ndents)
+ dir = TRUE; /* Rename entries in dir */
+ else
+ return ret;
+
fd1 = create_tmp_file();
if (fd1 == -1)
return ret;
@@ -1529,18 +1543,6 @@ static bool batch_rename(const char *path)
return ret;
}
- if (selbufpos) {
- i = get_input(messages[MSG_RENAME_SEL]);
- if (i != 'y' && i != 'Y') {
- if (!ndents)
- return TRUE;
-
- selbufpos = 0; /* Clear the selection */
- dir = TRUE;
- }
- } else
- dir = TRUE; /* Rename entries in dir */
-
if (dir)
for (i = 0; i < ndents; ++i)
appendfpath(dents[i].name, NAME_MAX);
@@ -2344,24 +2346,43 @@ static size_t mkpath(const char *dir, const char *name, char *out)
* Create symbolic/hard link(s) to file(s) in selection list
* Returns the number of links created
*/
-static int xlink(char *suffix, char *path, char *buf, int *presel, int type)
+static int xlink(char *suffix, char *path, char *curfname, char *buf, int *presel, int type)
{
- int count = 0;
+ int count = 0, choice = 's';
char *pbuf = pselbuf, *fname;
size_t pos = 0, len, r;
int (*link_fn)(const char *, const char *) = NULL;
- /* Check if selection is empty */
- if (!selbufpos) {
- printwait(messages[MSG_0_SELECTED], presel);
+ if (selbufpos) {
+ if (ndents) {
+ choice = get_input(messages[MSG_CUR_SEL_OPTS]);
+ if (choice != 'c' && choice != 's')
+ return -1;
+ }
+ } else if (ndents)
+ choice = 'c';
+ else
return -1;
- }
if (type == 's') /* symbolic link */
link_fn = &symlink;
else /* hard link */
link_fn = &link;
+ if (choice == 'c') {
+ char lnpath[PATH_MAX];
+
+ mkpath(path, curfname, buf);
+ r = mkpath(path, curfname, lnpath);
+ xstrlcpy(lnpath + r - 1, suffix, PATH_MAX - r - 1);
+
+ if (!link_fn(buf, lnpath))
+ return 1;
+
+ printwarn(presel);
+ return 0; /* One link created */
+ }
+
while (pos < selbufpos) {
len = strlen(pbuf);
fname = xbasename(pbuf);
@@ -4907,20 +4928,19 @@ nochange:
switch (sel) {
case SEL_ARCHIVE:
- r = get_input(messages[MSG_ARCHIVE_SEL]);
- if (r == 'y' || r == 'Y') {
- endselection(path, newpath);
+ endselection(path, newpath);
+ r = get_input(messages[MSG_CUR_SEL_OPTS]);
+ if (r == 's') {
if (!selsafe()) {
presel = MSGWAIT;
goto nochange;
}
tmp = NULL;
- } else if (!ndents) {
- printwait(messages[MSG_0_FILES], &presel);
+ } else if (!ndents)
goto nochange;
- } else
+ else
tmp = dents[cur].name;
tmp = xreadline(tmp, messages[MSG_ARCHIVE_NAME]);
break;
@@ -5058,7 +5078,8 @@ nochange:
if (tmp[0] == '@' && tmp[1] == '\0')
tmp[0] = '\0';
- r = xlink(tmp, path, newpath, &presel, r);
+ r = xlink(tmp, path, (ndents ? dents[cur].name : NULL),
+ newpath, &presel, r);
close(fd);
if (r <= 0)