mirror of
https://github.com/jarun/nnn.git
synced 2025-03-18 20:39:45 +00:00
Custom keybinds to run plugins directly
This commit is contained in:
parent
3bd3418ab6
commit
775742150c
4 changed files with 75 additions and 10 deletions
|
@ -113,6 +113,7 @@ Here's a video of [`nnn` on Termux (Android)](https://www.youtube.com/watch?v=Ab
|
||||||
- and more...
|
- and more...
|
||||||
- Convenience
|
- Convenience
|
||||||
- Needs minimal configuration
|
- Needs minimal configuration
|
||||||
|
- Plugin keybinds
|
||||||
- Select files across dirs; all/range selection
|
- Select files across dirs; all/range selection
|
||||||
- Copy, move, delete, archive, link selection
|
- Copy, move, delete, archive, link selection
|
||||||
- Batch rename selection or dir entries
|
- 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 |
|
| Example `export` | Description |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `NNN_BMS='d:~/Documents;D:~/Docs archive/'` | specify bookmarks (max 10) |
|
| `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_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_CONTEXT_COLORS='1234'` | specify per context color [default: '4444' (all blue)] |
|
||||||
| `NNN_SSHFS_OPTS='sshfs -o reconnect,idmap=user'` | specify SSHFS options |
|
| `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
|
^J du E Extn S Apparent du
|
||||||
^W Random s Size t Time modified
|
^W Random s Size t Time modified
|
||||||
MISC
|
MISC
|
||||||
! ^] Spawn SHELL C Execute entry
|
! ^] Shell L Lock C Execute entry
|
||||||
R ^V Pick plugin L Lock terminal
|
R ^V Pick plugin xN Run plugin N
|
||||||
c SSHFS mount u Unmount
|
c SSHFS mount u Unmount
|
||||||
^P Prompt ^N Note = Launcher
|
^P Prompt ^N Note = Launcher
|
||||||
```
|
```
|
||||||
|
|
|
@ -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.
|
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
|
#### 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.
|
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.
|
||||||
|
|
70
src/nnn.c
70
src/nnn.c
|
@ -120,6 +120,7 @@
|
||||||
#define MSGWAIT '$'
|
#define MSGWAIT '$'
|
||||||
#define REGEX_MAX 48
|
#define REGEX_MAX 48
|
||||||
#define BM_MAX 10
|
#define BM_MAX 10
|
||||||
|
#define PLUGIN_MAX 8
|
||||||
#define ENTRY_INCR 64 /* Number of dir 'entry' structures to allocate per shot */
|
#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 NAMEBUF_INCR 0x800 /* 64 dir entries at once, avg. 32 chars per filename = 64*32B = 2KB */
|
||||||
#define DESCRIPTOR_LEN 32
|
#define DESCRIPTOR_LEN 32
|
||||||
|
@ -200,6 +201,9 @@ typedef struct {
|
||||||
char *loc;
|
char *loc;
|
||||||
} bm;
|
} bm;
|
||||||
|
|
||||||
|
/* Plugins */
|
||||||
|
static char *plug[PLUGIN_MAX] = {NULL};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Settings
|
* Settings
|
||||||
* NOTE: update default values if changing order
|
* NOTE: update default values if changing order
|
||||||
|
@ -279,6 +283,7 @@ static int xlines, xcols;
|
||||||
static uint idle;
|
static uint idle;
|
||||||
static uint idletimeout, copybufpos, copybuflen;
|
static uint idletimeout, copybufpos, copybuflen;
|
||||||
static char *bmstr;
|
static char *bmstr;
|
||||||
|
static char *pluginstr;
|
||||||
static char *opener;
|
static char *opener;
|
||||||
static char *copier;
|
static char *copier;
|
||||||
static char *editor;
|
static char *editor;
|
||||||
|
@ -2185,6 +2190,32 @@ static char *get_bm_loc(char *buf, int key)
|
||||||
return NULL;
|
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)
|
static inline void resetdircolor(int flags)
|
||||||
{
|
{
|
||||||
if (cfg.dircolor && !(flags & DIR_OR_LINK_TO_DIR)) {
|
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)
|
static bool show_help(const char *path)
|
||||||
{
|
{
|
||||||
int i = 0, fd;
|
int i, fd;
|
||||||
const char *start, *end;
|
const char *start, *end;
|
||||||
const char helpstr[] = {
|
const char helpstr[] = {
|
||||||
"0\n"
|
"0\n"
|
||||||
|
@ -2835,8 +2866,8 @@ static bool show_help(const char *path)
|
||||||
"b^J du E Extn S Apparent du\n"
|
"b^J du E Extn S Apparent du\n"
|
||||||
"b^W Random s Size t Time modified\n"
|
"b^W Random s Size t Time modified\n"
|
||||||
"1MISC\n"
|
"1MISC\n"
|
||||||
"9! ^] Spawn SHELL C Execute entry\n"
|
"9! ^] Shell L Lock C Execute entry\n"
|
||||||
"9R ^V Pick plugin L Lock terminal\n"
|
"9R ^V Pick plugin xN Run plugin N\n"
|
||||||
"cc SSHFS mount u Unmount\n"
|
"cc SSHFS mount u Unmount\n"
|
||||||
"b^P Prompt ^N Note = Launcher\n"};
|
"b^P Prompt ^N Note = Launcher\n"};
|
||||||
|
|
||||||
|
@ -2860,11 +2891,15 @@ static bool show_help(const char *path)
|
||||||
|
|
||||||
if (bookmark[0].loc) {
|
if (bookmark[0].loc) {
|
||||||
dprintf(fd, "BOOKMARKS\n");
|
dprintf(fd, "BOOKMARKS\n");
|
||||||
for (; i < BM_MAX; ++i)
|
for (i = 0; i < BM_MAX && bookmark[i].key; ++i)
|
||||||
if (bookmark[i].key)
|
dprintf(fd, " %c: %s\n", (char)bookmark[i].key, bookmark[i].loc);
|
||||||
dprintf(fd, " %c: %s\n", (char)bookmark[i].key, bookmark[i].loc);
|
dprintf(fd, "\n");
|
||||||
else
|
}
|
||||||
break;
|
|
||||||
|
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");
|
dprintf(fd, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4359,6 +4394,7 @@ nochange:
|
||||||
}
|
}
|
||||||
case SEL_EXEC: // fallthrough
|
case SEL_EXEC: // fallthrough
|
||||||
case SEL_SHELL: // fallthrough
|
case SEL_SHELL: // fallthrough
|
||||||
|
case SEL_PLUGKEY: // fallthrough
|
||||||
case SEL_PLUGIN: // fallthrough
|
case SEL_PLUGIN: // fallthrough
|
||||||
case SEL_LAUNCH: // fallthrough
|
case SEL_LAUNCH: // fallthrough
|
||||||
case SEL_RUNCMD:
|
case SEL_RUNCMD:
|
||||||
|
@ -4370,6 +4406,7 @@ nochange:
|
||||||
case SEL_SHELL:
|
case SEL_SHELL:
|
||||||
spawn(shell, NULL, NULL, path, F_CLI);
|
spawn(shell, NULL, NULL, path, F_CLI);
|
||||||
break;
|
break;
|
||||||
|
case SEL_PLUGKEY: // fallthrough
|
||||||
case SEL_PLUGIN:
|
case SEL_PLUGIN:
|
||||||
if (!plugindir) {
|
if (!plugindir) {
|
||||||
printwait("plugins dir missing", &presel);
|
printwait("plugins dir missing", &presel);
|
||||||
|
@ -4385,6 +4422,20 @@ nochange:
|
||||||
if (!S_ISDIR(sb.st_mode))
|
if (!S_ISDIR(sb.st_mode))
|
||||||
break;
|
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;
|
cfg.runplugin ^= 1;
|
||||||
if (!cfg.runplugin && rundir[0]) {
|
if (!cfg.runplugin && rundir[0]) {
|
||||||
/*
|
/*
|
||||||
|
@ -4677,6 +4728,7 @@ static void cleanup(void)
|
||||||
free(cfgdir);
|
free(cfgdir);
|
||||||
free(initpath);
|
free(initpath);
|
||||||
free(bmstr);
|
free(bmstr);
|
||||||
|
free(pluginstr);
|
||||||
|
|
||||||
#ifdef DBGMODE
|
#ifdef DBGMODE
|
||||||
disabledbg();
|
disabledbg();
|
||||||
|
@ -4798,6 +4850,8 @@ int main(int argc, char *argv[])
|
||||||
return _FAILURE;
|
return _FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseplugins();
|
||||||
|
|
||||||
if (arg) { /* Open a bookmark directly */
|
if (arg) { /* Open a bookmark directly */
|
||||||
if (arg[1] || (initpath = get_bm_loc(NULL, *arg)) == NULL) {
|
if (arg[1] || (initpath = get_bm_loc(NULL, *arg)) == NULL) {
|
||||||
fprintf(stderr, "%s\n", messages[STR_INVBM_KEY]);
|
fprintf(stderr, "%s\n", messages[STR_INVBM_KEY]);
|
||||||
|
|
|
@ -93,6 +93,7 @@ enum action {
|
||||||
SEL_HELP,
|
SEL_HELP,
|
||||||
SEL_EXEC,
|
SEL_EXEC,
|
||||||
SEL_SHELL,
|
SEL_SHELL,
|
||||||
|
SEL_PLUGKEY,
|
||||||
SEL_PLUGIN,
|
SEL_PLUGIN,
|
||||||
SEL_LAUNCH,
|
SEL_LAUNCH,
|
||||||
SEL_RUNCMD,
|
SEL_RUNCMD,
|
||||||
|
@ -240,6 +241,8 @@ static struct key bindings[] = {
|
||||||
/* Run command */
|
/* Run command */
|
||||||
{ '!', SEL_SHELL },
|
{ '!', SEL_SHELL },
|
||||||
{ CONTROL(']'), SEL_SHELL },
|
{ CONTROL(']'), SEL_SHELL },
|
||||||
|
/* Plugin key */
|
||||||
|
{ 'x', SEL_PLUGKEY },
|
||||||
/* Run a plugin */
|
/* Run a plugin */
|
||||||
{ 'R', SEL_PLUGIN },
|
{ 'R', SEL_PLUGIN },
|
||||||
{ CONTROL('V'), SEL_PLUGIN },
|
{ CONTROL('V'), SEL_PLUGIN },
|
||||||
|
|
Loading…
Add table
Reference in a new issue