]> Sergey Matveev's repositories - nnn.git/commitdiff
Custom keybinds to run plugins directly
authorArun Prakash Jana <engineerarun@gmail.com>
Tue, 13 Aug 2019 19:28:33 +0000 (00:58 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Tue, 13 Aug 2019 20:08:30 +0000 (01:38 +0530)
README.md
plugins/README.md
src/nnn.c
src/nnn.h

index 7219b6f54a4a400f41f0b9991ee79c3c79007236..f069ff3801dfd29b5d32bccb987c1acff694553a 100644 (file)
--- 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 <kbd>xN</kbd> |
 | `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 <kbd>?</kbd> 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
 ```
index 10b7830a46872d5950baced7d4899ebbdb14a9f2..2e7d3b076a1db644408df6d4f3600e6fea3810bb 100644 (file)
@@ -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 <kbd>xN</kbd>:
+
+    export NNN_PLUG='fzy-open;mocplay;ndiff;nmount;viuimg;pdfview'
+
+With this, plugin `fzy-open` can be run with the keybind <kbd>x1</kbd>, `mocplay` can be run with <kbd>x2</kbd> 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.
index 017ebe3eb437713637af83d04de064984b1e16ab..ccdda8ab001acff5862ed754c8bfd4d44b34cee8 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
 #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]);
index 262cc4e578f194ffeb3898accf104a41a5c56b42..75143741cb944319bf2ffff115a257ee4732bfd8 100644 (file)
--- 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 },