mirror of
https://github.com/jarun/nnn.git
synced 2024-11-27 21:31:30 +00:00
Plugins!
This commit is contained in:
parent
12ce9451ee
commit
5cf3471716
29
README.md
29
README.md
|
@ -27,7 +27,7 @@
|
|||
|
||||
`nnn` works seamlessly with your DE and favourite GUI utilities. It runs on Linux, macOS, Raspberry Pi, BSD, Cygwin, Linux subsystem for Windows and Termux on Android.
|
||||
|
||||
Have as many scripts as you want to extend the power of `nnn`! Pick from the [scripts repository](https://github.com/jarun/nnn/tree/master/user-scripts) or add your own.
|
||||
Have as many scripts as you want to extend the power of `nnn`! Pick from the available [plugins](https://github.com/jarun/nnn/tree/master/plugins) or add your own.
|
||||
|
||||
[Quickstart](#quickstart) and see how `nnn` simplifies long desktop sessions. When you are ready for more, start [hacking `nnn`](https://github.com/jarun/nnn/wiki/hacking-nnn).
|
||||
|
||||
|
@ -60,7 +60,7 @@ Have as many scripts as you want to extend the power of `nnn`! Pick from the [sc
|
|||
- [File indicators](#file-indicators)
|
||||
- [Configuration](#configuration)
|
||||
- [Help](#help)
|
||||
- [User scripts](#user-scripts)
|
||||
- [Plugins](#plugins)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Tmux configuration](#tmux-configuration)
|
||||
- [BSD terminal issue](#bsd-terminal-issue)
|
||||
|
@ -102,13 +102,12 @@ Have as many scripts as you want to extend the power of `nnn`! Pick from the [sc
|
|||
- Copy, move, delete, archive, link selection
|
||||
- FreeDesktop compliant trash (needs trash-cli)
|
||||
- Show copy, move progress on Linux (needs avdcpmv)
|
||||
- Script to view directory and file diff for selection
|
||||
- Plugin repository
|
||||
- Transfer files using lftp
|
||||
- Batch rename (needs vidir)
|
||||
- Per-context directory color (default: blue)
|
||||
- Spawn a shell in the current directory
|
||||
- Launch applications, run a command
|
||||
- Repository of custom scripts
|
||||
- Run current file as executable
|
||||
- Change directory at exit (*easy* shell integration)
|
||||
- Edit file in EDITOR or open in PAGER
|
||||
|
@ -143,7 +142,7 @@ Have as many scripts as you want to extend the power of `nnn`! Pick from the [sc
|
|||
| advcpmv (Linux) ([integration](https://github.com/jarun/nnn/wiki/hacking-nnn#show-cp-mv-progress)) | copy, move progress |
|
||||
| $EDITOR (overridden by $VISUAL, if defined) | edit files (fallback vi) |
|
||||
| $PAGER (less, most) | page through files (fallback less) |
|
||||
| $SHELL | spawn a shell, run script (fallback sh) |
|
||||
| $SHELL | spawn a shell, run some commands (fallback sh) |
|
||||
|
||||
#### From a package manager
|
||||
|
||||
|
@ -199,7 +198,7 @@ Option completion scripts for Bash, Fish and Zsh can be found in respective subd
|
|||
5. To use `nnn` as a GUI app launcher with fuzzy selection menu, drop [`nlaunch`](https://github.com/jarun/nnn/blob/master/scripts/nlaunch/nlaunch) somewhere in your `$PATH`. Note that the launcher requires fzy.
|
||||
6. Don't memorize keys. Arrows, <kbd>/</kbd> and <kbd>q</kbd> suffice. Press <kbd>?</kbd> for help on keyboard shortcuts anytime.
|
||||
|
||||
- For additional functionality [setup custom scripts](#user-scripts).
|
||||
- For additional functionality [setup plugins](#plugins).
|
||||
- Visit the wiki page [hacking `nnn`](https://github.com/jarun/nnn/wiki/hacking-nnn) for many more specific use cases.
|
||||
- To set `nnn` as the default file manager, follow these [instructions](https://github.com/jarun/nnn/wiki/nnn-as-default-file-manager).
|
||||
|
||||
|
@ -264,7 +263,7 @@ Press <kbd>?</kbd> in `nnn` to see the list anytime.
|
|||
^W Random s Size t Time modified
|
||||
MISC
|
||||
! ^] Spawn SHELL C Execute entry
|
||||
R ^V Run script L Lock terminal
|
||||
R ^V Pick plugin L Lock terminal
|
||||
^P Prompt ^N Note = Launcher
|
||||
```
|
||||
|
||||
|
@ -379,8 +378,8 @@ The following indicators are used in the detail view:
|
|||
| `NNN_OPENER_DETACH=1` | do not block when invoking file opener |
|
||||
| `NNN_CONTEXT_COLORS='1234'` | specify per context color [default: '4444' (all blue)] |
|
||||
| `NNN_IDLE_TIMEOUT=300` | idle seconds before locking terminal [default: disabled] |
|
||||
| `NNN_COPIER='copier.sh'` | system clipboard copier script [default: none] |
|
||||
| `NNN_SCRIPT_DIR=/home/user/scripts` | absolute path to script dir |
|
||||
| `NNN_COPIER='/path/to/copier.sh'` | system clipboard copier script [default: none] |
|
||||
| `NNN_PLUGIN_DIR=/home/user/nnn-plugins` | absolute path to plugins dir |
|
||||
| `NNN_NOTE=/home/user/Dropbox/Public/notes` | path to note file [default: none] |
|
||||
| `NNN_TMPFILE=/tmp/nnn` | file to write current open dir path to for cd on quit |
|
||||
| `NNN_USE_EDITOR=1` | Open text files in `$EDITOR` (`$VISUAL`, if defined; fallback vi) |
|
||||
|
@ -396,17 +395,17 @@ The following indicators are used in the detail view:
|
|||
$ man nnn
|
||||
To lookup keyboard shortcuts at runtime, press <kbd>?</kbd>.
|
||||
|
||||
#### USER SCRIPTS
|
||||
#### PLUGINS
|
||||
|
||||
`nnn` can invoke custom scripts in the current directory (`$PWD` for the script) with the currently selected file name as the argument.
|
||||
`nnn` can invoke plugins in the current directory (`$PWD` for the plugin) with the currently selected file name as the argument.
|
||||
|
||||
Copy the scripts of your interest from the [user-scripts](https://github.com/jarun/nnn/tree/master/user-scripts) directory and let `nnn` know the location:
|
||||
Copy the plugins of your interest from the [plugins](https://github.com/jarun/nnn/tree/master/plugins) directory and let `nnn` know the location:
|
||||
|
||||
export NNN_SCRIPT_DIR=/absolute/path/to/scripts_dir
|
||||
export NNN_PLUGIN_DIR=/absolute/path/to/plugins_dir
|
||||
|
||||
Use the run script shortcut to jump to the script directory and pick a script. 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 pick a plugin. Repeating the same shortcut cancels the operation and puts you back in the original directory.
|
||||
|
||||
If you have an interesting script feel free to raise a PR.
|
||||
If you have an interesting plugin feel free to raise a PR.
|
||||
|
||||
#### TROUBLESHOOTING
|
||||
|
||||
|
|
4
nnn.1
4
nnn.1
|
@ -174,9 +174,9 @@ when dealing with the !, e and p commands respectively. A single combination to
|
|||
The path is shown in the help and configuration screen.
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_SCRIPT_DIR:\fR \fIabsolute\fR path to script directory. Selected script is invoked with currently selected file name as argument 1.
|
||||
\fBNNN_PLUGIN_DIR:\fR \fIabsolute\fR path to plugin directory. Selected plugin is invoked with currently selected file name as argument 1.
|
||||
.Bd -literal
|
||||
export NNN_SCRIPT_DIR=/absolute/path/to/scripts_dir
|
||||
export NNN_PLUGIN_DIR=/absolute/path/to/plugins_dir
|
||||
.Ed
|
||||
.Pp
|
||||
\fBNNN_NOTE:\fR \fIabsolute\fR path to a note file.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
| Script (a-z) | Lang | Deps | Description |
|
||||
| Plugin (a-z) | Lang | Deps | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| copier | sh | OS-specific | Copy selection to clipboard |
|
||||
| edit | sh | fzy | Fuzzy find a file in directory subtree and edit in vim |
|
||||
| fzy | sh | fzy | Fuzzy find a file in directory subtree and open using xdg-open |
|
||||
| hexview | sh | xxd, $PAGER | view a file in hex |
|
||||
|
@ -16,15 +15,15 @@
|
|||
| transfer | sh | curl | Upload current file to transfer.sh |
|
||||
| upgrade | sh | wget | Upgrade to latest nnn version manually on Debian 9 Stretch |
|
||||
|
||||
### File access from scripts
|
||||
### File access from plugins
|
||||
|
||||
The design is flexible so a script can access:
|
||||
- all files in the directory (`nnn` switches to the dir where the script is to be run so the dir is `$PWD` for the script)
|
||||
- the currently highlighted file (the file name is passed as the first argument to a script)
|
||||
- the current selection (by reading the file .nnncp, see the script `copier`)
|
||||
The design is flexible so a plugin can access:
|
||||
- all files in the directory (`nnn` switches to the dir where the plugin is to be run so the dir is `$PWD` for the plugin)
|
||||
- the currently highlighted file (the file name is passed as the argument to a plugin)
|
||||
- the current selection (by reading the file .nnncp, see the plugin `ndiff`)
|
||||
|
||||
### Contributing scripts
|
||||
### Contributing plugins
|
||||
|
||||
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.
|
||||
|
||||
The scripts should be executable. Please add an entry in the table above.
|
||||
The plugins should be executable. Please add an entry in the table above.
|
50
src/nnn.c
50
src/nnn.c
|
@ -217,8 +217,8 @@ typedef struct {
|
|||
uint autoselect : 1; /* Auto-select dir in nav-as-you-type mode */
|
||||
uint metaviewer : 1; /* Index of metadata viewer in utils[] */
|
||||
uint useeditor : 1; /* Use VISUAL to open text files */
|
||||
uint runscript : 1; /* Choose script to run mode */
|
||||
uint runctx : 2; /* The context in which script is to be run */
|
||||
uint runplugin : 1; /* Choose plugin mode */
|
||||
uint runctx : 2; /* The context in which plugin is to be run */
|
||||
uint restrict0b : 1; /* Restrict 0-byte file opening */
|
||||
uint filter_re : 1; /* Use regex filters */
|
||||
uint wild : 1; /* Do not sort entries on dir load */
|
||||
|
@ -257,7 +257,7 @@ static settings cfg = {
|
|||
1, /* autoselect */
|
||||
0, /* metaviewer */
|
||||
0, /* useeditor */
|
||||
0, /* runscript */
|
||||
0, /* runplugin */
|
||||
0, /* runctx */
|
||||
0, /* restrict0b */
|
||||
1, /* filter_re */
|
||||
|
@ -385,7 +385,7 @@ static const char * const messages[] = {
|
|||
#define NNN_CONTEXT_COLORS 2
|
||||
#define NNN_IDLE_TIMEOUT 3
|
||||
#define NNN_COPIER 4
|
||||
#define NNN_SCRIPT_DIR 5
|
||||
#define NNN_PLUGIN_DIR 5
|
||||
#define NNN_NOTE 6
|
||||
#define NNN_TMPFILE 7
|
||||
#define NNNLVL 8 /* strings end here */
|
||||
|
@ -405,7 +405,7 @@ static const char * const env_cfg[] = {
|
|||
"NNN_CONTEXT_COLORS",
|
||||
"NNN_IDLE_TIMEOUT",
|
||||
"NNN_COPIER",
|
||||
"NNN_SCRIPT_DIR",
|
||||
"NNN_PLUGIN_DIR",
|
||||
"NNN_NOTE",
|
||||
"NNN_TMPFILE",
|
||||
"NNNLVL",
|
||||
|
@ -2158,7 +2158,7 @@ static void savecurctx(settings *curcfg, char *path, char *curname, int r /* nex
|
|||
xstrlcpy(g_ctx[r].c_name, curname, NAME_MAX + 1);
|
||||
g_ctx[r].c_fltr[0] = g_ctx[r].c_fltr[1] = '\0';
|
||||
g_ctx[r].c_cfg = cfg;
|
||||
g_ctx[r].c_cfg.runscript = 0;
|
||||
g_ctx[r].c_cfg.runplugin = 0;
|
||||
}
|
||||
|
||||
cfg.curctx = r;
|
||||
|
@ -2386,7 +2386,7 @@ static bool show_help(const char *path)
|
|||
"b^W Random s Size t Time modified\n"
|
||||
"1MISC\n"
|
||||
"9! ^] Spawn SHELL C Execute entry\n"
|
||||
"9R ^V Run script L Lock terminal\n"
|
||||
"9R ^V Pick plugin L Lock terminal\n"
|
||||
"b^P Prompt ^N Note = Launcher\n"};
|
||||
|
||||
if (g_tmpfpath[0])
|
||||
|
@ -2845,7 +2845,7 @@ static void browse(char *ipath)
|
|||
struct stat sb;
|
||||
char *path, *lastdir, *lastname;
|
||||
char *dir, *tmp;
|
||||
char *scriptpath = getenv(env_cfg[NNN_SCRIPT_DIR]);
|
||||
char *pluginpath = getenv(env_cfg[NNN_PLUGIN_DIR]);
|
||||
|
||||
atexit(dentfree);
|
||||
|
||||
|
@ -3002,11 +3002,11 @@ nochange:
|
|||
if (cfg.nonavopen && sel == SEL_NAV_IN)
|
||||
continue;
|
||||
|
||||
/* Handle script selection mode */
|
||||
if (cfg.runscript) {
|
||||
if (!scriptpath || (cfg.runctx != cfg.curctx)
|
||||
/* Must be in script directory to select script */
|
||||
|| (strcmp(path, scriptpath) != 0))
|
||||
/* Handle plugin selection mode */
|
||||
if (cfg.runplugin) {
|
||||
if (!pluginpath || (cfg.runctx != cfg.curctx)
|
||||
/* Must be in plugin directory to select plugin */
|
||||
|| (strcmp(path, pluginpath) != 0))
|
||||
continue;
|
||||
|
||||
mkpath(path, dents[cur].name, newpath);
|
||||
|
@ -3019,7 +3019,7 @@ nochange:
|
|||
} else
|
||||
spawn(newpath, NULL, NULL, path, F_NORMAL);
|
||||
rundir[0] = '\0';
|
||||
cfg.runscript = 0;
|
||||
cfg.runplugin = 0;
|
||||
setdirwatch();
|
||||
goto begin;
|
||||
}
|
||||
|
@ -3739,7 +3739,7 @@ nochange:
|
|||
}
|
||||
case SEL_EXEC: // fallthrough
|
||||
case SEL_SHELL: // fallthrough
|
||||
case SEL_SCRIPT: // fallthrough
|
||||
case SEL_PLUGIN: // fallthrough
|
||||
case SEL_LAUNCH: // fallthrough
|
||||
case SEL_RUNCMD:
|
||||
switch (sel) {
|
||||
|
@ -3766,13 +3766,13 @@ nochange:
|
|||
case SEL_SHELL:
|
||||
spawn(shell, NULL, NULL, path, F_CLI);
|
||||
break;
|
||||
case SEL_SCRIPT:
|
||||
if (!scriptpath) {
|
||||
printwait("set NNN_SCRIPT_DIR", &presel);
|
||||
case SEL_PLUGIN:
|
||||
if (!pluginpath) {
|
||||
printwait("set NNN_PLUGIN_DIR", &presel);
|
||||
goto nochange;
|
||||
}
|
||||
|
||||
if (stat(scriptpath, &sb) == -1) {
|
||||
if (stat(pluginpath, &sb) == -1) {
|
||||
printwarn();
|
||||
goto nochange;
|
||||
}
|
||||
|
@ -3781,13 +3781,13 @@ nochange:
|
|||
if (!S_ISDIR(sb.st_mode))
|
||||
break;
|
||||
|
||||
cfg.runscript ^= 1;
|
||||
if (!cfg.runscript && rundir[0]) {
|
||||
cfg.runplugin ^= 1;
|
||||
if (!cfg.runplugin && rundir[0]) {
|
||||
/*
|
||||
* If toggled, and still in the script dir,
|
||||
* If toggled, and still in the plugin dir,
|
||||
* switch to original directory
|
||||
*/
|
||||
if (strcmp(path, scriptpath) == 0) {
|
||||
if (strcmp(path, pluginpath) == 0) {
|
||||
xstrlcpy(path, rundir, PATH_MAX);
|
||||
xstrlcpy(lastname, runfile, NAME_MAX);
|
||||
rundir[0] = runfile[0] = '\0';
|
||||
|
@ -3798,11 +3798,11 @@ nochange:
|
|||
}
|
||||
|
||||
/* Check if directory is accessible */
|
||||
if (!xdiraccess(scriptpath))
|
||||
if (!xdiraccess(pluginpath))
|
||||
goto nochange;
|
||||
|
||||
xstrlcpy(rundir, path, PATH_MAX);
|
||||
xstrlcpy(path, scriptpath, PATH_MAX);
|
||||
xstrlcpy(path, pluginpath, PATH_MAX);
|
||||
if (ndents)
|
||||
xstrlcpy(runfile, dents[cur].name, NAME_MAX);
|
||||
cfg.runctx = cfg.curctx;
|
||||
|
|
|
@ -88,7 +88,7 @@ enum action {
|
|||
SEL_HELP,
|
||||
SEL_EXEC,
|
||||
SEL_SHELL,
|
||||
SEL_SCRIPT,
|
||||
SEL_PLUGIN,
|
||||
SEL_LAUNCH,
|
||||
SEL_RUNCMD,
|
||||
SEL_RUNEDIT,
|
||||
|
@ -225,9 +225,9 @@ static struct key bindings[] = {
|
|||
/* Run command */
|
||||
{ '!', SEL_SHELL },
|
||||
{ CONTROL(']'), SEL_SHELL },
|
||||
/* Run a custom script */
|
||||
{ 'R', SEL_SCRIPT },
|
||||
{ CONTROL('V'), SEL_SCRIPT },
|
||||
/* Run a plugin */
|
||||
{ 'R', SEL_PLUGIN },
|
||||
{ CONTROL('V'), SEL_PLUGIN },
|
||||
/* Launcher */
|
||||
{ '=', SEL_LAUNCH },
|
||||
/* Run a command */
|
||||
|
|
Loading…
Reference in a new issue