]> Sergey Matveev's repositories - nnn.git/commitdiff
PR #265: Replace dependency on vidir
authorArun Prakash Jana <engineerarun@gmail.com>
Wed, 22 May 2019 13:14:03 +0000 (18:44 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Wed, 22 May 2019 13:14:03 +0000 (18:44 +0530)
Author: @bruce-hill

README.md
src/nnn.c

index a6229f5bcc5f4d549f8ad03d2a91898ab92d25cf..34f2570c8bf8e237c586b5394bde0ad97ec426cb 100644 (file)
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ It runs on Linux, macOS, Raspberry Pi, BSD, Cygwin, Linux subsystem for Windows
   - FreeDesktop compliant trash (needs trash-cli)
   - Plugin repository
   - SSHFS mounts (needs sshfs)
-  - Batch rename (needs vidir)
+  - Batch rename
   - Show copy, move progress on Linux (needs avdcpmv)
   - Per-context directory color (default: blue)
   - Spawn a shell in the current directory
@@ -139,7 +139,6 @@ The following table is a complete list. Some of the utilities may be installed b
 | trash-cli | trash files (default: delete) |
 | mediainfo / exiftool | multimedia file details |
 | atool / bsdtar / patool ([integration](https://github.com/jarun/nnn/wiki/hacking-nnn#integrate-patool)) | create, list and extract archives |
-| vidir (from moreutils) | batch rename dir entries |
 | sshfs, fusermount(3) | mount, unmount remote over SSHFS |
 | vlock (Linux), bashlock (macOS), lock(1) (BSD) | terminal locker |
 | advcpmv (Linux) ([integration](https://github.com/jarun/nnn/wiki/hacking-nnn#show-cp-mv-progress)) | copy, move progress |
index 6236c5311d128fa518c61cf3c1de2b15afe9c3bb..1a106ce7b7ad72b206789b4c23e307f0d5f63446 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -334,10 +334,9 @@ static char g_tmpfpath[TMP_LEN_MAX] __attribute__ ((aligned));
 #define OPENER 2
 #define ATOOL 3
 #define BSDTAR 4
-#define VIDIR 5
-#define LOCKER 6
-#define NLAUNCH 7
-#define UNKNOWN 8
+#define LOCKER 5
+#define NLAUNCH 6
+#define UNKNOWN 7
 
 /* Utilities to open files, run actions */
 static char * const utils[] = {
@@ -352,7 +351,6 @@ static char * const utils[] = {
 #endif
        "atool",
        "bsdtar",
-       "vidir",
 #ifdef __APPLE__
        "bashlock",
 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
@@ -1123,6 +1121,80 @@ static void xrm(char *path)
        }
 }
 
+static void rename_selection(const char *path)
+{
+       const char renamecmd[] = "paste -d'\n' %s %s | xargs -d'\n' -n2 mv 2>/dev/null";
+       char buf[sizeof(renamecmd) + 2 * PATH_MAX];
+       char foriginal[TMP_LEN_MAX] = {0};
+       int fd1 = -1, fd2 = -1, i;
+       ssize_t len, len2;
+
+       if ((fd1 = create_tmp_file()) == -1)
+               return;
+
+       xstrlcpy(foriginal, g_tmpfpath, strlen(g_tmpfpath)+1);
+
+       if ((fd2 = create_tmp_file()) == -1) {
+               unlink(foriginal);
+               close(fd1);
+               return;
+       }
+
+       if (copybufpos > 0) {
+               // Rename selected files with absolute paths:
+               selectiontofd(fd1);
+               if (write(fd1, "\n", 1) < 1)
+                       goto finished_renaming;
+               selectiontofd(fd2);
+               if (write(fd2, "\n", 1) < 1)
+                       goto finished_renaming;
+       } else {
+               // If nothing is selected, use the directory contents with relative paths:
+               for (i = 0; i < ndents; ++i) {
+                       len = strlen(dents[i].name);
+                       if (write(fd1, dents[i].name, len) != len || write(fd1, "\n", 1) != 1)
+                               goto finished_renaming;
+                       if (write(fd2, dents[i].name, len) != len || write(fd2, "\n", 1) != 1)
+                               goto finished_renaming;
+               }
+       }
+
+       close(fd2);
+       fd2 = -1;
+
+       spawn(editor, g_tmpfpath, NULL, path, F_CLI);
+
+       // Check that the number of filenames is unchanged:
+       len = 0, len2 = 0;
+       lseek(fd1, 0, SEEK_SET);
+       while ((i = read(fd1, buf, sizeof(buf))) > 0) {
+               while (i) len += buf[--i] == '\n';
+       }
+       if (i < 0) goto finished_renaming;
+
+       // Reopen file descriptor to get updated contents:
+       if ((fd2 = open(g_tmpfpath, O_RDONLY)) == -1)
+               goto finished_renaming;
+       while ((i = read(fd2, buf, sizeof(buf))) > 0) {
+               while (i) len2 += buf[--i] == '\n';
+       }
+       if (i < 0) goto finished_renaming;
+
+       if (len2 != len) {
+               get_input("Error: wrong number of filenames. Press any key to continue...");
+               goto finished_renaming;
+       }
+
+       snprintf(buf, sizeof(buf), renamecmd, foriginal, g_tmpfpath);
+       spawn("sh", "-c", buf, path, F_NORMAL);
+
+finished_renaming:
+       if (fd2 >= 0) close(fd1);
+       unlink(foriginal);
+       if (fd2 >= 0) close(fd2);
+       unlink(g_tmpfpath);
+}
+
 static void archive_selection(const char *cmd, const char *archive, const char *curpath)
 {
        snprintf(g_buf, CMD_LEN_MAX,
@@ -3619,9 +3691,7 @@ nochange:
                                        copycurname();
                                goto begin;
                        case SEL_RENAMEALL:
-                               r = getutil(utils[VIDIR]);
-                               if (r)
-                                       spawn(utils[VIDIR], ".", NULL, path, F_NORMAL);
+                               rename_selection(path);
                                break;
                        case SEL_HELP:
                                r = show_help(path);