From 775742150cb96d3ab6d7d76fbaf8942d3caf9e2b Mon Sep 17 00:00:00 2001 From: Arun Prakash Jana Date: Wed, 14 Aug 2019 00:58:33 +0530 Subject: [PATCH] Custom keybinds to run plugins directly --- README.md | 6 ++-- plugins/README.md | 6 ++++ src/nnn.c | 70 +++++++++++++++++++++++++++++++++++++++++------ src/nnn.h | 3 ++ 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7219b6f..f069ff3 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ Here's a video of [`nnn` on Termux (Android)](https://www.youtube.com/watch?v=Ab - and more... - Convenience - Needs minimal configuration + - Plugin keybinds - Select files across dirs; all/range selection - Copy, move, delete, archive, link selection - Batch rename selection or dir entries @@ -216,6 +217,7 @@ Option completion scripts for Bash, Fish and Zsh can be found in respective subd | Example `export` | Description | | --- | --- | | `NNN_BMS='d:~/Documents;D:~/Docs archive/'` | specify bookmarks (max 10) | +| `NNN_PLUG='fzy-open;mocplay;nmount;thumb'` | plugins to run with xN | | `NNN_USE_EDITOR=1` | open text files in `$VISUAL` (else `$EDITOR`, fallback vi) | | `NNN_CONTEXT_COLORS='1234'` | specify per context color [default: '4444' (all blue)] | | `NNN_SSHFS_OPTS='sshfs -o reconnect,idmap=user'` | specify SSHFS options | @@ -286,8 +288,8 @@ Press ? in `nnn` to see the list anytime. ^J du E Extn S Apparent du ^W Random s Size t Time modified MISC - ! ^] Spawn SHELL C Execute entry - R ^V Pick plugin L Lock terminal + ! ^] Shell L Lock C Execute entry + R ^V Pick plugin xN Run plugin N c SSHFS mount u Unmount ^P Prompt ^N Note = Launcher ``` diff --git a/plugins/README.md b/plugins/README.md index 10b7830..2e7d3b0 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -50,6 +50,12 @@ Each script has a _Description_ section which provides more details on what the Use the _pick plugin_ shortcut to visit the plugin directory and execute a plugin. Repeating the same shortcut cancels the operation and puts you back in the original directory. +To run (up to 8) plugins directly with xN: + + export NNN_PLUG='fzy-open;mocplay;ndiff;nmount;viuimg;pdfview' + +With this, plugin `fzy-open` can be run with the keybind x1, `mocplay` can be run with x2 and so on... + #### Contributing plugins Plugins are scripts and all scripting languages should work. However, POSIX-compliant shell scripts runnable in `sh` are preferred. If that's too rudimentary for your use case, use Python, Perl or Ruby. Please keep non-portable commands (like `notify-send`) commented so users from any other OS/DE aren't surprised. diff --git a/src/nnn.c b/src/nnn.c index 017ebe3..ccdda8a 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -120,6 +120,7 @@ #define MSGWAIT '$' #define REGEX_MAX 48 #define BM_MAX 10 +#define PLUGIN_MAX 8 #define ENTRY_INCR 64 /* Number of dir 'entry' structures to allocate per shot */ #define NAMEBUF_INCR 0x800 /* 64 dir entries at once, avg. 32 chars per filename = 64*32B = 2KB */ #define DESCRIPTOR_LEN 32 @@ -200,6 +201,9 @@ typedef struct { char *loc; } bm; +/* Plugins */ +static char *plug[PLUGIN_MAX] = {NULL}; + /* * Settings * NOTE: update default values if changing order @@ -279,6 +283,7 @@ static int xlines, xcols; static uint idle; static uint idletimeout, copybufpos, copybuflen; static char *bmstr; +static char *pluginstr; static char *opener; static char *copier; static char *editor; @@ -2185,6 +2190,32 @@ static char *get_bm_loc(char *buf, int key) return NULL; } +static void parseplugins(void) +{ + int i = 0; + char *nextplug; + char *plugins = getenv("NNN_PLUG"); + + if (!plugins || !*plugins) + return; + + pluginstr = strdup(plugins); + plugins = pluginstr; + nextplug = plugins; + + while (*plugins && i < PLUGIN_MAX) { + if (plugins == nextplug) { + plug[i] = nextplug; + ++i; + } else if (*plugins == ';') { + *plugins = '\0'; + nextplug = plugins + 1; + } + + ++plugins; + } +} + static inline void resetdircolor(int flags) { if (cfg.dircolor && !(flags & DIR_OR_LINK_TO_DIR)) { @@ -2804,7 +2835,7 @@ static void lock_terminal(void) */ static bool show_help(const char *path) { - int i = 0, fd; + int i, fd; const char *start, *end; const char helpstr[] = { "0\n" @@ -2835,8 +2866,8 @@ static bool show_help(const char *path) "b^J du E Extn S Apparent du\n" "b^W Random s Size t Time modified\n" "1MISC\n" - "9! ^] Spawn SHELL C Execute entry\n" - "9R ^V Pick plugin L Lock terminal\n" + "9! ^] Shell L Lock C Execute entry\n" + "9R ^V Pick plugin xN Run plugin N\n" "cc SSHFS mount u Unmount\n" "b^P Prompt ^N Note = Launcher\n"}; @@ -2860,11 +2891,15 @@ static bool show_help(const char *path) if (bookmark[0].loc) { dprintf(fd, "BOOKMARKS\n"); - for (; i < BM_MAX; ++i) - if (bookmark[i].key) - dprintf(fd, " %c: %s\n", (char)bookmark[i].key, bookmark[i].loc); - else - break; + for (i = 0; i < BM_MAX && bookmark[i].key; ++i) + dprintf(fd, " %c: %s\n", (char)bookmark[i].key, bookmark[i].loc); + dprintf(fd, "\n"); + } + + if (plug[0]) { + dprintf(fd, "PLUGIN KEYS\n"); + for (i = 0; i < PLUGIN_MAX && plug[i]; ++i) + dprintf(fd, " %d: %s\n", i + 1, plug[i]); dprintf(fd, "\n"); } @@ -4359,6 +4394,7 @@ nochange: } case SEL_EXEC: // fallthrough case SEL_SHELL: // fallthrough + case SEL_PLUGKEY: // fallthrough case SEL_PLUGIN: // fallthrough case SEL_LAUNCH: // fallthrough case SEL_RUNCMD: @@ -4370,6 +4406,7 @@ nochange: case SEL_SHELL: spawn(shell, NULL, NULL, path, F_CLI); break; + case SEL_PLUGKEY: // fallthrough case SEL_PLUGIN: if (!plugindir) { printwait("plugins dir missing", &presel); @@ -4385,6 +4422,20 @@ nochange: if (!S_ISDIR(sb.st_mode)) break; + if (sel == SEL_PLUGKEY) + { + r = get_input("") - '0'; + if ((r < 1 || r > PLUGIN_MAX) || !plug[r - 1]) + goto nochange; + + mkpath(plugindir, plug[r - 1], newpath); + if (ndents) + spawn(newpath, dents[cur].name, NULL, path, F_NORMAL); + else + spawn(newpath, NULL, NULL, path, F_NORMAL); + break; + } + cfg.runplugin ^= 1; if (!cfg.runplugin && rundir[0]) { /* @@ -4677,6 +4728,7 @@ static void cleanup(void) free(cfgdir); free(initpath); free(bmstr); + free(pluginstr); #ifdef DBGMODE disabledbg(); @@ -4798,6 +4850,8 @@ int main(int argc, char *argv[]) return _FAILURE; } + parseplugins(); + if (arg) { /* Open a bookmark directly */ if (arg[1] || (initpath = get_bm_loc(NULL, *arg)) == NULL) { fprintf(stderr, "%s\n", messages[STR_INVBM_KEY]); diff --git a/src/nnn.h b/src/nnn.h index 262cc4e..7514374 100644 --- a/src/nnn.h +++ b/src/nnn.h @@ -93,6 +93,7 @@ enum action { SEL_HELP, SEL_EXEC, SEL_SHELL, + SEL_PLUGKEY, SEL_PLUGIN, SEL_LAUNCH, SEL_RUNCMD, @@ -240,6 +241,8 @@ static struct key bindings[] = { /* Run command */ { '!', SEL_SHELL }, { CONTROL(']'), SEL_SHELL }, + /* Plugin key */ + { 'x', SEL_PLUGKEY }, /* Run a plugin */ { 'R', SEL_PLUGIN }, { CONTROL('V'), SEL_PLUGIN },