]> Sergey Matveev's repositories - nnn.git/commitdiff
Support archive "extract to..."
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 13 Jun 2021 08:43:39 +0000 (14:13 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 13 Jun 2021 09:08:37 +0000 (14:38 +0530)
README.md
src/nnn.c

index cd1d9ea029009f63980d4053151f95d0644ab7a4..2f9a057ac878359c9c7a6d3c544effd9f9d4cf31 100644 (file)
--- a/README.md
+++ b/README.md
@@ -84,7 +84,7 @@ It runs smoothly on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw)
   - File-specific colors (or minimal _dirs in context color_)
   - Icons (customize and compile-in)
   - Plugin for image, video and audio thumbnails
-  - Create, list, extract, mount (FUSE based) archives
+  - Create, list, extract (to), mount (FUSE based) archives
   - Option to open all text files in `$EDITOR`
 - Information
   - Detailed file information
index fde166cf7c8612a418e9896d2fe1b89d2e58d714..1080d84af5e64a670c28748d31162782ed1c4720 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -4187,76 +4187,6 @@ static size_t get_fs_info(const char *path, bool type)
        return (size_t)svb.f_bavail << ffs((int)(svb.f_frsize >> 1));
 }
 
-/* List or extract archive */
-static void handle_archive(char *fpath, char op)
-{
-       char arg[] = "-tvf"; /* options for tar/bsdtar to list files */
-       char *util;
-
-       if (getutil(utils[UTIL_ATOOL])) {
-               util = utils[UTIL_ATOOL];
-               arg[1] = op;
-               arg[2] = '\0';
-       } else if (getutil(utils[UTIL_BSDTAR])) {
-               util = utils[UTIL_BSDTAR];
-               if (op == 'x')
-                       arg[1] = op;
-       } else if (is_suffix(fpath, ".zip")) {
-               util = utils[UTIL_UNZIP];
-               arg[1] = (op == 'l') ? 'v' /* verbose listing */ : '\0';
-               arg[2] = '\0';
-       } else {
-               util = utils[UTIL_TAR];
-               if (op == 'x')
-                       arg[1] = op;
-       }
-
-       if (op == 'x') /* extract */
-               spawn(util, arg, fpath, NULL, F_NORMAL);
-       else /* list */
-               get_output(util, arg, fpath, NULL, TRUE, TRUE);
-}
-
-static char *visit_parent(char *path, char *newpath, int *presel)
-{
-       char *dir;
-
-       /* There is no going back */
-       if (istopdir(path)) {
-               /* Continue in type-to-nav mode, if enabled */
-               if (cfg.filtermode && presel)
-                       *presel = FILTER;
-               return NULL;
-       }
-
-       /* Use a copy as xdirname() may change the string passed */
-       if (newpath)
-               xstrsncpy(newpath, path, PATH_MAX);
-       else
-               newpath = path;
-
-       dir = xdirname(newpath);
-       if (chdir(dir) == -1) {
-               printwarn(presel);
-               return NULL;
-       }
-
-       return dir;
-}
-
-static void valid_parent(char *path, char *lastname)
-{
-       /* Save history */
-       xstrsncpy(lastname, xbasename(path), NAME_MAX + 1);
-
-       while (!istopdir(path))
-               if (visit_parent(path, NULL, NULL))
-                       break;
-
-       printwarn(NULL);
-       xdelay(XDELAY_INTERVAL_MS);
-}
-
 /* Create non-existent parents and a file or dir */
 static bool xmktree(char *path, bool dir)
 {
@@ -4324,6 +4254,95 @@ next:
        return TRUE;
 }
 
+/* List or extract archive */
+static bool handle_archive(char *fpath, char op)
+{
+       char arg[] = "-tvf"; /* options for tar/bsdtar to list files */
+       char *util, *outdir;
+       bool x_to = FALSE;
+
+       if (op == 'x') {
+               outdir = xreadline(NULL, messages[MSG_NEW_PATH]);
+               if (outdir && *outdir && !(*outdir == '.' && outdir[1] == '\0')) {
+                       if (!xmktree(outdir, TRUE) || (chdir(outdir) == -1)) {
+                               printwarn(NULL);
+                               return FALSE;
+                       }
+                       x_to = TRUE;
+               }
+       }
+
+       if (getutil(utils[UTIL_ATOOL])) {
+               util = utils[UTIL_ATOOL];
+               arg[1] = op;
+               arg[2] = '\0';
+       } else if (getutil(utils[UTIL_BSDTAR])) {
+               util = utils[UTIL_BSDTAR];
+               if (op == 'x')
+                       arg[1] = op;
+       } else if (is_suffix(fpath, ".zip")) {
+               util = utils[UTIL_UNZIP];
+               arg[1] = (op == 'l') ? 'v' /* verbose listing */ : '\0';
+               arg[2] = '\0';
+       } else {
+               util = utils[UTIL_TAR];
+               if (op == 'x')
+                       arg[1] = op;
+       }
+
+       if (op == 'x') /* extract */
+               spawn(util, arg, fpath, NULL, F_NORMAL | F_MULTI);
+       else /* list */
+               get_output(util, arg, fpath, NULL, TRUE, TRUE);
+
+       if (x_to && (chdir(xdirname(fpath)) == -1)) {
+               printwarn(NULL);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static char *visit_parent(char *path, char *newpath, int *presel)
+{
+       char *dir;
+
+       /* There is no going back */
+       if (istopdir(path)) {
+               /* Continue in type-to-nav mode, if enabled */
+               if (cfg.filtermode && presel)
+                       *presel = FILTER;
+               return NULL;
+       }
+
+       /* Use a copy as xdirname() may change the string passed */
+       if (newpath)
+               xstrsncpy(newpath, path, PATH_MAX);
+       else
+               newpath = path;
+
+       dir = xdirname(newpath);
+       if (chdir(dir) == -1) {
+               printwarn(presel);
+               return NULL;
+       }
+
+       return dir;
+}
+
+static void valid_parent(char *path, char *lastname)
+{
+       /* Save history */
+       xstrsncpy(lastname, xbasename(path), NAME_MAX + 1);
+
+       while (!istopdir(path))
+               if (visit_parent(path, NULL, NULL))
+                       break;
+
+       printwarn(NULL);
+       xdelay(XDELAY_INTERVAL_MS);
+}
+
 static bool archive_mount(char *newpath)
 {
        char *str = "install archivemount";
@@ -6491,7 +6510,10 @@ nochange:
                                r = get_input(messages[MSG_ARCHIVE_OPTS]);
                                if (r == 'l' || r == 'x') {
                                        mkpath(path, pent->name, newpath);
-                                       handle_archive(newpath, r);
+                                       if (!handle_archive(newpath, r)) {
+                                               presel = MSGWAIT;
+                                               goto nochange;
+                                       }
                                        if (r == 'l') {
                                                statusbar(path);
                                                goto nochange;