]> Sergey Matveev's repositories - nnn.git/commitdiff
Support link creation
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 20 Jan 2019 11:29:55 +0000 (16:59 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 20 Jan 2019 11:29:55 +0000 (16:59 +0530)
README.md
nnn.1
src/nnn.c

index 0d121f9faa87f0d83ef4d4af4161f119e9cf9235..d714e88c730128ebe6e96fc1ff2c9b3d40abbeb2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -96,6 +96,7 @@ It runs on Linux, macOS, Raspberry Pi, BSD, Cygwin, Linux subsystem for Windows
   - Create, rename files and directories
   - Select files across directories
   - Copy, move, delete selection
+  - Create sym/hard link(s) to selection
   - Transfer files using lftp
   - Batch rename/move/delete (needs vidir)
   - Show directories in custom color (default: blue)
@@ -226,7 +227,7 @@ Press <kbd>?</kbd> in `nnn` to see the list anytime.
              ^G  Quit and cd         q  Quit context
           Q, ^Q  Quit                ?  Help, config
  FILES
-             ^O  Open with...        n  Create new
+             ^O  Open with...        n  Create new/link
               D  File details       ^R  Rename entry
           ⎵, ^K  Copy entry path     r  Open dir in vidir
           Y, ^Y  Toggle selection    y  List selection
diff --git a/nnn.1 b/nnn.1
index c5a16471cf4cee4fd7ffc9301ea570b41c2103ec..b7f2ca5208bc9ccc481c190b93ab0b111d08d949 100644 (file)
--- a/nnn.1
+++ b/nnn.1
@@ -89,7 +89,7 @@ FILES
 .It Ic ^O
 Open with an application (takes 1 combined argument)
 .It Ic n
-Create a new file or directory
+Create a new file, directory or link(s) to selection
 .It Ic D
 Show entry details
 .It Ic ^R
index 74272123350cfd7cc30d27bd34676e2a8acc96af..90c4ceee49b86a72ea046cb4ad7452e31e020981 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -1469,7 +1469,6 @@ END:
        clearprompt();
 
        buf[len] = '\0';
-       DPRINTF_S(buf);
        wcstombs(g_buf + ((NAME_MAX + 1) << 2), buf, NAME_MAX);
        return g_buf + ((NAME_MAX + 1) << 2);
 }
@@ -1496,6 +1495,42 @@ static size_t mkpath(char *dir, char *name, char *out, size_t n)
        return (xstrlcpy(out + len, name, n - len) + len);
 }
 
+/* Create symbolic/hard link(s) to file(s) in selection list */
+static int xlink(char *suffix, char *path, char *buf, int type)
+{
+       int count = 0;
+       char *pbuf = pcopybuf, *fname;
+       ssize_t pos = 0, len, r;
+       int (*link_fn)(const char *, const char *) = NULL;
+
+       /* Check if selection is empty */
+       if (!copybufpos)
+               return 0;
+
+       if (type == 's') /* symbolic link */
+               link_fn = &symlink;
+       else if (type == 'h') /* hard link */
+               link_fn = &link;
+       else
+               return -1;
+
+       while (pos < copybufpos) {
+               len = strlen(pbuf);
+               fname = xbasename(pbuf);
+               r = mkpath(path, fname, buf, PATH_MAX);
+               xstrlcpy(buf + r - 1, suffix, PATH_MAX - r - 1);
+
+               r = link_fn(pbuf, buf);
+               if (!r)
+                       ++count;
+
+               pos += len + 1;
+               pbuf += len + 1;
+       }
+
+       return count;
+}
+
 static bool parsebmstr()
 {
        int i = 0;
@@ -2105,7 +2140,7 @@ static bool show_help(char *path)
             "d^G  Quit and cd         q  Quit context\n"
          "aQ, ^Q  Quit                ?  Help, config\n"
 "1FILES\n"
-            "d^O  Open with...        n  Create new\n"
+            "d^O  Open with...        n  Create new/link\n"
              "eD  File details       ^R  Rename entry\n"
          "a⎵, ^K  Copy entry path     r  Open dir in vidir\n"
          "aY, ^Y  Toggle selection    y  List selection\n"
@@ -3334,7 +3369,7 @@ nochange:
                                tmp = xreadline(NULL, "open with: ");
                                break;
                        case SEL_NEW:
-                               tmp = xreadline(NULL, "name: ");
+                               tmp = xreadline(NULL, "name/link suffix: ");
                                break;
                        default: /* SEL_RENAME */
                                tmp = xreadline(dents[cur].name, "");
@@ -3426,12 +3461,26 @@ nochange:
                                }
                        } else {
                                /* Check if it's a dir or file */
-                               r = get_input("press 'f'(ile) or 'd'(ir)");
+                               r = get_input("create 'f'(ile) / 'd'(ir) / 's'(ym) / 'h'(ard)?");
                                if (r == 'f') {
                                        r = openat(fd, tmp, O_CREAT, 0666);
                                        close(r);
                                } else if (r == 'd') {
                                        r = mkdirat(fd, tmp, 0777);
+                               } else if (r == 's' || r == 'h') {
+                                       r = xlink(tmp, path, newpath, r);
+                                       close(fd);
+
+                                       if (r <= 0) {
+                                               printmsg("none created");
+                                               goto nochange;
+                                       }
+
+                                       if (cfg.filtermode)
+                                               presel = FILTER;
+                                       if (ndents)
+                                               copycurname();
+                                       goto begin;
                                } else {
                                        close(fd);
                                        break;