diff options
author | Arun Prakash Jana <engineerarun@gmail.com> | 2019-12-29 23:21:18 +0530 |
---|---|---|
committer | Arun Prakash Jana <engineerarun@gmail.com> | 2019-12-29 23:21:18 +0530 |
commit | f90c37cd5e1860e6fd29aa7a767923dcd74039cc (patch) | |
tree | 19ac9c416146dd96b69f577b4a420a630b6f634c /src | |
parent | 146da5911d8273ce302fb70ddf443cb577f9def4 (diff) | |
download | nnn-f90c37cd5e1860e6fd29aa7a767923dcd74039cc.tar.gz |
Automagically handle archives
Diffstat (limited to 'src')
-rw-r--r-- | src/nnn.c | 76 | ||||
-rw-r--r-- | src/nnn.h | 5 |
2 files changed, 47 insertions, 34 deletions
@@ -334,6 +334,7 @@ static kv bookmark[BM_MAX]; static kv plug[PLUGIN_MAX]; static uchar g_tmpfplen; static uchar blk_shift = BLK_SHIFT_512; +static regex_t archive_re; /* Retain old signal handlers */ #ifdef __linux__ @@ -464,6 +465,7 @@ static char * const utils[] = { #define MSG_ARCHIVE_OPTS 34 #define MSG_PLUGIN_KEYS 35 #define MSG_BOOKMARK_KEYS 36 +#define MSG_INVALID_REG 37 static const char * const messages[] = { "no traversal", @@ -500,9 +502,10 @@ static const char * const messages[] = { "'s'shfs / 'r'clone?", "may take a while, try refresh", "app name: ", - "e'x'tract / 'l'ist / 'm'ount?", + "'d'efault, e'x'tract / 'l'ist / 'm'ount?", "plugin keys:", "bookmark keys:", + "invalid regex", }; /* Supported configuration environment variables */ @@ -511,9 +514,10 @@ static const char * const messages[] = { #define NNN_CONTEXT_COLORS 2 #define NNN_IDLE_TIMEOUT 3 #define NNNLVL 4 -#define NNN_PIPE 5 /* strings end here */ -#define NNN_USE_EDITOR 6 /* flags begin here */ -#define NNN_TRASH 7 +#define NNN_PIPE 5 +#define NNN_ARCHIVE 6 /* strings end here */ +#define NNN_USE_EDITOR 7 /* flags begin here */ +#define NNN_TRASH 8 static const char * const env_cfg[] = { "NNN_BMS", @@ -522,6 +526,7 @@ static const char * const env_cfg[] = { "NNN_IDLE_TIMEOUT", "NNNLVL", "NNN_PIPE", + "NNN_ARCHIVE", "NNN_USE_EDITOR", "NNN_TRASH", }; @@ -552,6 +557,7 @@ static char mv[] = "mv -i"; static const char cpmvformatcmd[] = "sed -i 's|^\\(\\(.*/\\)\\(.*\\)$\\)|#\\1\\n\\3|' %s"; static const char cpmvrenamecmd[] = "sed 's|^\\([^#][^/]\\?.*\\)$|%s/\\1|;s|^#\\(/.*\\)$|\\1|' %s | tr '\\n' '\\0' | xargs -0 -n2 sh -c '%s \"$0\" \"$@\" < /dev/tty'"; static const char batchrenamecmd[] = "paste -d'\n' %s %s | sed 'N; /^\\(.*\\)\\n\\1$/!p;d' | tr '\n' '\\0' | xargs -0 -n2 mv 2>/dev/null"; +static const char archive_regex[] ="\\.(bz|bz2|gz|tar|taz|tbz|tbz2|tgz|z|zip)$"; /* Event handling */ #ifdef LINUX_INOTIFY @@ -599,7 +605,7 @@ static int dentfind(const char *fname, int n); static void move_cursor(int target, int ignore_scrolloff); static inline bool getutil(char *util); static size_t mkpath(const char *dir, const char *name, char *out); -static char *xgetenv(const char *name, char *fallback); +static char *xgetenv(const char * const name, char *fallback); static void plugscript(const char *plugin, char *newpath, uchar flags); /* Functions */ @@ -1372,7 +1378,7 @@ static void prompt_run(char *cmd, const char *cur, const char *path) } /* Get program name from env var, else return fallback program */ -static char *xgetenv(const char *name, char *fallback) +static char *xgetenv(const char * const name, char *fallback) { char *value = getenv(name); @@ -2090,7 +2096,7 @@ static int filterentries(char *path, char *lastname) case '=': // fallthrough /* Launch app */ case ']': // fallthorugh /*Prompt key */ case ';': // fallthrough /* Run plugin key */ - case ',': // falltrough /* Pin CWD */ + case ',': // fallthrough /* Pin CWD */ case '?': /* Help and config key, '?' is an invalid regex */ if (len == 1) goto end; @@ -3480,8 +3486,8 @@ static void show_help(const char *path) "cP Copy sel here%-10c^Y Edit sel\n" "cV Move sel here%-10c^V Copy/move sel as\n" "cX Delete sel%-13c^X Delete entry\n" - "cf Archive%-16c^F Archive ops\n" "ce Edit in EDITOR%-10cp Open in PAGER\n" + "ci Archive entry%-0c\n" "1ORDER TOGGLES\n" "cS Disk usage%-14cA Apparent du\n" "cz Size%-20ct Time\n" @@ -4560,6 +4566,28 @@ nochange: continue; } + if (!regexec(&archive_re, dents[cur].name, 0, NULL, 0)) { + r = get_input(messages[MSG_ARCHIVE_OPTS]); + if (r == 'l' || r == 'x') { + mkpath(path, dents[cur].name, newpath); + handle_archive(newpath, path, r); + copycurname(); + goto begin; + } + + fd = FALSE; + if (r == 'm') { + if (!archive_mount(dents[cur].name, path, newpath, &presel)) + fd = MSG_FAILED; + } else if (r != 'd') + fd = MSG_INVALID_KEY; + + if (r != 'd') { + fd ? printwait(messages[fd], &presel) : clearprompt(); + goto nochange; + } + } + if (!sb.st_size) { printwait(messages[MSG_EMPTY_FILE], &presel); goto nochange; @@ -5324,28 +5352,6 @@ nochange: copycurname(); /* Repopulate as directory content may have changed */ goto begin; - case SEL_ARCHIVEOPS: - if (!ndents) - goto nochange; - - r = get_input(messages[MSG_ARCHIVE_OPTS]); - if (r == 'l' || r == 'x') { - mkpath(path, dents[cur].name, newpath); - handle_archive(newpath, path, r); - copycurname(); - goto begin; - } - - if (r != 'm') { - printwait(messages[MSG_INVALID_KEY], &presel); - goto nochange; - } - - if (!archive_mount(dents[cur].name, path, newpath, &presel)) { - printwait(messages[MSG_FAILED], &presel); - goto nochange; - } - // fallthrough case SEL_REMOTE: if (sel == SEL_REMOTE && !remote_mount(newpath, &presel)) goto nochange; @@ -5802,6 +5808,13 @@ int main(int argc, char *argv[]) } } + /* Set archive handling (enveditor used as tmp var) */ + enveditor = getenv(env_cfg[NNN_ARCHIVE]); + if (setfilter(&archive_re, (enveditor ? enveditor : archive_regex))) { + fprintf(stderr, "%s\n", messages[MSG_INVALID_REG]); + return _FAILURE; + } + /* Edit text in EDITOR if opted (and opener is not all-CLI) */ if (!cfg.cliopener && xgetenv_set(env_cfg[NNN_USE_EDITOR])) cfg.useeditor = 1; @@ -5928,6 +5941,9 @@ int main(int argc, char *argv[]) } else if (!cfg.picker && g_selpath) unlink(g_selpath); + /* Free the regex */ + regfree(&archive_re); + /* Free the selection buffer */ free(pselbuf); @@ -87,7 +87,6 @@ enum action { SEL_NEW, SEL_RENAME, SEL_RENAMEMUL, - SEL_ARCHIVEOPS, SEL_REMOTE, SEL_UMOUNT, SEL_HELP, @@ -179,7 +178,7 @@ static struct key bindings[] = { /* File details */ { 'D', SEL_STATS }, /* Create archive */ - { 'f', SEL_ARCHIVE }, + { 'i', SEL_ARCHIVE }, /* Toggle sort by size */ { 'z', SEL_FSIZE }, /* Sort by apparent size including dir contents */ @@ -226,8 +225,6 @@ static struct key bindings[] = { { KEY_F(2), SEL_RENAME }, /* Rename contents of current dir */ { 'r', SEL_RENAMEMUL }, - /* Mount an archive */ - { CONTROL('F'), SEL_ARCHIVEOPS }, /* Connect to server over SSHFS */ { 'c', SEL_REMOTE }, /* Disconnect a SSHFS mount point */ |