From: Arun Prakash Jana <engineerarun@gmail.com>
Date: Sun, 19 May 2019 15:59:29 +0000 (+0530)
Subject: Support bsdtar
X-Git-Tag: v2.5~15
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5f6ceb2f43794bc6d4c31567624e46b7686202d6;p=nnn.git

Support bsdtar
---

diff --git a/README.md b/README.md
index 047d977f..a6229f5b 100644
--- a/README.md
+++ b/README.md
@@ -92,7 +92,7 @@ It runs on Linux, macOS, Raspberry Pi, BSD, Cygwin, Linux subsystem for Windows
   - Subtree search to open or edit files (using plugin)
 - Mimes
   - Open with desktop opener or specify a custom app
-  - Create, list, extract archive (needs (p)atool)
+  - Create, list, extract archive (needs (p)atool/bsdtar)
   - Option to open all text files in EDITOR
 - Information
   - Detailed file information
@@ -138,7 +138,7 @@ The following table is a complete list. Some of the utilities may be installed b
 | file, coreutils (cp, mv, rm), findutils (xargs) | detect type, copy, move and remove files |
 | trash-cli | trash files (default: delete) |
 | mediainfo / exiftool | multimedia file details |
-| atool / patool ([integration](https://github.com/jarun/nnn/wiki/hacking-nnn#integrate-patool)) | create, list and extract archives |
+| 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 |
diff --git a/src/nnn.c b/src/nnn.c
index f2741b60..38dc3b1c 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -333,7 +333,7 @@ static char g_tmpfpath[TMP_LEN_MAX] __attribute__ ((aligned));
 #define EXIFTOOL 1
 #define OPENER 2
 #define ATOOL 3
-#define APACK 4
+#define BSDTAR 4
 #define VIDIR 5
 #define LOCKER 6
 #define NLAUNCH 7
@@ -351,7 +351,7 @@ static char * const utils[] = {
 	"xdg-open",
 #endif
 	"atool",
-	"apack",
+	"bsdtar",
 	"vidir",
 #ifdef __APPLE__
 	"bashlock",
@@ -375,6 +375,7 @@ static char mv[] = "mvg -gi";
 #define STR_DATE_ID 2
 #define STR_TMPFILE 3
 #define NONE_SELECTED 4
+#define UTIL_MISSING 5
 
 static const char * const messages[] = {
 	"no traversal",
@@ -382,6 +383,7 @@ static const char * const messages[] = {
 	"%F %T %z",
 	"/.nnnXXXXXX",
 	"empty selection",
+	"utility missing",
 };
 
 /* Supported configuration environment variables */
@@ -1121,7 +1123,7 @@ static void xrm(char *path)
 	}
 }
 
-static void archive_selection(const char *archive, const char *curpath)
+static void archive_selection(const char *cmd, const char *archive, const char *curpath)
 {
 	snprintf(g_buf, CMD_LEN_MAX,
 #ifdef __linux__
@@ -1129,7 +1131,7 @@ static void archive_selection(const char *archive, const char *curpath)
 #else
 		 "cat %s | xargs -0 -o %s %s",
 #endif
-		 g_cppath, utils[APACK], archive);
+		 g_cppath, cmd, archive);
 	spawn("sh", "-c", g_buf, curpath, F_NORMAL);
 }
 
@@ -2379,16 +2381,27 @@ static bool show_mediainfo(const char *fpath, const char *arg)
 	return TRUE;
 }
 
-static bool handle_archive(char *fpath, char *arg, const char *dir)
+/* Extracts or lists archive */
+static bool handle_archive(char *fpath, const char *dir, char op)
 {
-	if (!getutil(utils[ATOOL]))
+	char larg[] = "-tf";
+	char xarg[] = "-xf";
+	char *util;
+
+	if (getutil(utils[ATOOL])) {
+		util = utils[ATOOL];
+		larg[1] = op;
+		larg[2] = xarg[2] = '\0';
+	} else if (getutil(utils[BSDTAR]))
+		util = utils[BSDTAR];
+	else
 		return FALSE;
 
-	if (arg[1] == 'x')
-		spawn(utils[ATOOL], arg, fpath, dir, F_NORMAL);
-	else {
+	if (op == 'x') { // extract
+		spawn(util, xarg, fpath, dir, F_NORMAL);
+	} else { // list
 		exitcurses();
-		get_output(NULL, 0, utils[ATOOL], arg, fpath, TRUE);
+		get_output(NULL, 0, util, larg, fpath, TRUE);
 		refresh();
 	}
 
@@ -2895,7 +2908,7 @@ static void move_cursor(int target, int ignore_scrolloff)
 	cur = target;
 	if (!ignore_scrolloff) {
 		scrolloff = MIN(SCROLLOFF, onscreen >> 1);
-		/* 
+		/*
 		 * When ignore_scrolloff is 1, the cursor can jump into the scrolloff
 		 * margin area, but when ignore_scrolloff is 0, act like a boa
 		 * constrictor and squeeze the cursor towards the middle region of the
@@ -3596,10 +3609,10 @@ nochange:
 				setdirwatch();
 				goto nochange;
 			case SEL_ARCHIVELS:
-				r = handle_archive(newpath, "-l", path);
+				r = handle_archive(newpath, path, 'l');
 				break;
 			case SEL_EXTRACT:
-				r = handle_archive(newpath, "-x", path);
+				r = handle_archive(newpath, path, 'x');
 				break;
 			case SEL_REDRAW:
 				if (ndents)
@@ -3638,7 +3651,7 @@ nochange:
 			}
 
 			if (!r) {
-				printwait("utility missing", &presel);
+				printwait(messages[UTIL_MISSING], &presel);
 				goto nochange;
 			}
 
@@ -3879,16 +3892,21 @@ nochange:
 
 			switch (sel) {
 			case SEL_ARCHIVE:
-				/* newpath is used as temporary buffer */
-				if (!getutil(utils[APACK])) {
-					printwait("utility missing", &presel);
+			{
+				char cmd[] = "bsdtar -cf";
+
+				if (getutil(utils[ATOOL]))
+					xstrlcpy(cmd, "atool -qa", 10);
+				else if (!getutil(utils[BSDTAR])) {
+					printwait(messages[UTIL_MISSING], &presel);
 					goto nochange;
 				}
 
-				(r == 'y' || r == 'Y') ? archive_selection(tmp, path)
-						       : spawn(utils[APACK], tmp, dents[cur].name,
-							       path, F_NORMAL);
+				(r == 'y' || r == 'Y') ? archive_selection(cmd, tmp, path)
+						       : spawn(cmd, tmp, dents[cur].name,
+							       path, F_NORMAL | F_MULTI);
 				break;
+			}
 			case SEL_OPENWITH:
 				mkpath(path, dents[cur].name, newpath);
 				spawn(tmp, newpath, NULL, path, r);