]> Sergey Matveev's repositories - nnn.git/commitdiff
Support link creation for hovered file
authorArun Prakash Jana <engineerarun@gmail.com>
Fri, 29 Nov 2019 15:28:12 +0000 (20:58 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Fri, 29 Nov 2019 15:28:12 +0000 (20:58 +0530)
LICENSE
nnn.1
src/nnn.c

diff --git a/LICENSE b/LICENSE
index 65bba60715eab0cfe49a854813a7b9e690fab4b1..06d7405020018ddf3cacee90fd4af10487da3d20 100644 (file)
Binary files a/LICENSE and b/LICENSE differ
diff --git a/nnn.1 b/nnn.1
index 870ae5bc8cd17b2ab5f525cfb1201b17f333fa49..7e7f3eb2939c1c9ead2c7b60c73533e5273f56c8 100644 (file)
--- 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
index ce63afdbaf6d8f4bbd7d52ff2c60dd9e84d0462e..72ab596d3c07c0b051991eed3d7db7f6eb80d6bd 100644 (file)
--- 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)