mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Plugin mimelist: support reading file list from (cmd as) plugin
This commit is contained in:
parent
e8e87f6ba2
commit
eee5057da5
|
@ -29,7 +29,7 @@ nnn_cd () {
|
||||||
read -r context
|
read -r context
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "%s" "${context:-0}$dir" > "$NNN_PIPE"
|
printf "%s" "${context:-0}c$dir" > "$NNN_PIPE"
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_exists () {
|
cmd_exists () {
|
||||||
|
|
|
@ -47,6 +47,7 @@ Plugins are installed to `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins`.
|
||||||
| kdeconnect | Send selected files to an Android device | sh | kdeconnect-cli |
|
| kdeconnect | Send selected files to an Android device | sh | kdeconnect-cli |
|
||||||
| launch | GUI application launcher | sh | fzf/fzy |
|
| launch | GUI application launcher | sh | fzf/fzy |
|
||||||
| mediainf | Show media information | sh | mediainfo |
|
| mediainf | Show media information | sh | mediainfo |
|
||||||
|
| mimelist | List files by mime in subtree | sh | fd/find |
|
||||||
| moclyrics | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) |
|
| moclyrics | Show lyrics of the track playing in moc | sh | [ddgr](https://github.com/jarun/ddgr), [moc](http://moc.daper.net/) |
|
||||||
| mocplay | Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) |
|
| mocplay | Append (and/or play) selection/dir/file in moc | sh | [moc](http://moc.daper.net/) |
|
||||||
| mp3conv | Extract audio from multimedia as mp3 | sh | ffmpeg |
|
| mp3conv | Extract audio from multimedia as mp3 | sh | ffmpeg |
|
||||||
|
@ -163,8 +164,14 @@ Drop the plugin in `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins` and make it e
|
||||||
#### Controlling `nnn`'s active directory
|
#### Controlling `nnn`'s active directory
|
||||||
`nnn` provides a mechanism for plugins to control its active directory.
|
`nnn` provides a mechanism for plugins to control its active directory.
|
||||||
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
|
The way to do so is by writing to the pipe pointed by the environment variable `NNN_PIPE`.
|
||||||
The plugin should write a single string in the format `<number><path>` without a newline at the end. For example, `1/etc`.
|
The plugin should write a single string in the format `<context number><char><path>` without a newline at the end. For example, `1c/etc`.
|
||||||
The number indicates the context to change the active directory of (0 is used to indicate the current context).
|
The context number indicates the context to change the active directory of (0 is used to indicate the current context).
|
||||||
|
The `<char>` indicates the operation type.
|
||||||
|
|
||||||
|
: Char : Operation :
|
||||||
|
|:---:| --- |
|
||||||
|
| c | cd |
|
||||||
|
| l | list files in list mode |
|
||||||
|
|
||||||
For convenience, we provided a helper script named `.nnn-plugin-helper` and a function named `nnn_cd` to ease this process. `nnn_cd` receives the path to change to as the first argument, and the context as an optional second argument.
|
For convenience, we provided a helper script named `.nnn-plugin-helper` and a function named `nnn_cd` to ease this process. `nnn_cd` receives the path to change to as the first argument, and the context as an optional second argument.
|
||||||
If a context is not provided, it is asked for explicitly. To skip this and choose the current context, set the `CUR_CTX` variable in `.nnn-plugin-helper` to `1`.
|
If a context is not provided, it is asked for explicitly. To skip this and choose the current context, set the `CUR_CTX` variable in `.nnn-plugin-helper` to `1`.
|
||||||
|
@ -201,7 +208,7 @@ There are many plugins provided by `nnn` which can be used as examples. Here are
|
||||||
printf "cd to: "
|
printf "cd to: "
|
||||||
read -r dir
|
read -r dir
|
||||||
|
|
||||||
printf "%s" "0$dir" > "$NNN_PIPE"
|
printf "%s" "0c$dir" > "$NNN_PIPE"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributing plugins
|
## Contributing plugins
|
||||||
|
|
|
@ -13,7 +13,7 @@ if which autojump >/dev/null 2>&1; then
|
||||||
printf "jump to: "
|
printf "jump to: "
|
||||||
read -r dir
|
read -r dir
|
||||||
odir="$(autojump "$dir")"
|
odir="$(autojump "$dir")"
|
||||||
printf "%s" "0$odir" > "$NNN_PIPE"
|
printf "%s" "0c$odir" > "$NNN_PIPE"
|
||||||
else
|
else
|
||||||
printf "autojump missing"
|
printf "autojump missing"
|
||||||
read -r _
|
read -r _
|
||||||
|
|
|
@ -25,4 +25,4 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
printf "%s" "0$sel" > "$NNN_PIPE"
|
printf "%s" "0c$sel" > "$NNN_PIPE"
|
||||||
|
|
21
plugins/mimelist
Executable file
21
plugins/mimelist
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Description: Run fd/find in subtree and list files by mime type in current context
|
||||||
|
# Requires: fd/find
|
||||||
|
#
|
||||||
|
# Shell: POSIX compliant
|
||||||
|
# Author: Arun Prakash jana
|
||||||
|
|
||||||
|
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||||
|
|
||||||
|
if [ "$(cmd_exists fd)" -eq "0" ]; then
|
||||||
|
fd=fd
|
||||||
|
else
|
||||||
|
fd=find
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "mime: "
|
||||||
|
read -r mime
|
||||||
|
|
||||||
|
printf "%s" "0l" > "$NNN_PIPE"
|
||||||
|
$fd | file -if- | grep "$mime" | awk -F: '{printf "%s\0", $1}' > "$NNN_PIPE"
|
120
src/nnn.c
120
src/nnn.c
|
@ -514,8 +514,9 @@ static char * const utils[] = {
|
||||||
#define MSG_RM_TMP 40
|
#define MSG_RM_TMP 40
|
||||||
#define MSG_NOCHNAGE 41
|
#define MSG_NOCHNAGE 41
|
||||||
#define MSG_CANCEL 42
|
#define MSG_CANCEL 42
|
||||||
|
#define MSG_0_ENTRIES 43
|
||||||
#ifndef DIR_LIMITED_SELECTION
|
#ifndef DIR_LIMITED_SELECTION
|
||||||
#define MSG_DIR_CHANGED 43 /* Must be the last entry */
|
#define MSG_DIR_CHANGED 44 /* Must be the last entry */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char * const messages[] = {
|
static const char * const messages[] = {
|
||||||
|
@ -562,6 +563,7 @@ static const char * const messages[] = {
|
||||||
"unchanged",
|
"unchanged",
|
||||||
"cancelled",
|
"cancelled",
|
||||||
"first file (\')/char?",
|
"first file (\')/char?",
|
||||||
|
"0 entries",
|
||||||
#ifndef DIR_LIMITED_SELECTION
|
#ifndef DIR_LIMITED_SELECTION
|
||||||
"dir changed, range sel off", /* Must be the last entry */
|
"dir changed, range sel off", /* Must be the last entry */
|
||||||
#endif
|
#endif
|
||||||
|
@ -691,6 +693,7 @@ static inline bool getutil(char *util);
|
||||||
static size_t mkpath(const char *dir, const char *name, char *out);
|
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 *name, char *fallback);
|
||||||
static bool plugscript(const char *plugin, const char *path, uchar flags);
|
static bool plugscript(const char *plugin, const char *path, uchar flags);
|
||||||
|
static char *load_input(int fd, char *path);
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
|
|
||||||
|
@ -4218,11 +4221,72 @@ static bool plctrl_init(void)
|
||||||
return _SUCCESS;
|
return _SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void rmlistpath()
|
||||||
|
{
|
||||||
|
if (listpath) {
|
||||||
|
DPRINTF_S(__FUNCTION__);
|
||||||
|
DPRINTF_S(initpath);
|
||||||
|
spawn("rm -rf", initpath, NULL, NULL, F_NOTRACE | F_MULTI);
|
||||||
|
listpath = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void readpipe(int fd, char **path, char **lastname, char **lastdir)
|
||||||
|
{
|
||||||
|
char *nextpath = NULL;
|
||||||
|
ssize_t len = read(fd, g_buf, 1);
|
||||||
|
|
||||||
|
if (len != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char ctx = g_buf[0] - '0';
|
||||||
|
|
||||||
|
if (ctx > CTX_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
len = read(fd, g_buf, 1);
|
||||||
|
if (len != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char op = g_buf[0];
|
||||||
|
|
||||||
|
if (op == 'c') {
|
||||||
|
len = read(fd, g_buf, PATH_MAX);
|
||||||
|
if (len <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nextpath = g_buf;
|
||||||
|
} else if (op == 'l') {
|
||||||
|
/* Remove last list mode path, if any */
|
||||||
|
rmlistpath();
|
||||||
|
|
||||||
|
nextpath = load_input(fd, *path);
|
||||||
|
if (nextpath) {
|
||||||
|
free(initpath);
|
||||||
|
initpath = nextpath;
|
||||||
|
DPRINTF_S(initpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextpath) {
|
||||||
|
if (ctx == 0 || ctx == cfg.curctx + 1) {
|
||||||
|
xstrsncpy(*lastdir, *path, PATH_MAX);
|
||||||
|
xstrsncpy(*path, nextpath, PATH_MAX);
|
||||||
|
} else {
|
||||||
|
int r = ctx - 1;
|
||||||
|
|
||||||
|
g_ctx[r].c_cfg.ctxactive = 0;
|
||||||
|
savecurctx(&cfg, nextpath, dents[cur].name, r);
|
||||||
|
*path = g_ctx[r].c_path;
|
||||||
|
*lastdir = g_ctx[r].c_last;
|
||||||
|
*lastname = g_ctx[r].c_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool run_selected_plugin(char **path, const char *file, char *runfile, char **lastname, char **lastdir)
|
static bool run_selected_plugin(char **path, const char *file, char *runfile, char **lastname, char **lastdir)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (!(g_states & STATE_PLUGIN_INIT)) {
|
if (!(g_states & STATE_PLUGIN_INIT)) {
|
||||||
plctrl_init();
|
plctrl_init();
|
||||||
g_states |= STATE_PLUGIN_INIT;
|
g_states |= STATE_PLUGIN_INIT;
|
||||||
|
@ -4248,27 +4312,9 @@ static bool run_selected_plugin(char **path, const char *file, char *runfile, ch
|
||||||
spawn(g_buf, NULL, *path, *path, F_NORMAL);
|
spawn(g_buf, NULL, *path, *path, F_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read(fd, g_buf, PATH_MAX);
|
readpipe(fd, path, lastname, lastdir);
|
||||||
g_buf[len] = '\0';
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (len > 1) {
|
|
||||||
int ctx = g_buf[0] - '0';
|
|
||||||
|
|
||||||
if (ctx == 0 || ctx == cfg.curctx + 1) {
|
|
||||||
xstrsncpy(*lastdir, *path, PATH_MAX);
|
|
||||||
xstrsncpy(*path, g_buf + 1, PATH_MAX);
|
|
||||||
} else if (ctx >= 1 && ctx <= CTX_MAX) {
|
|
||||||
int r = ctx - 1;
|
|
||||||
|
|
||||||
g_ctx[r].c_cfg.ctxactive = 0;
|
|
||||||
savecurctx(&cfg, g_buf + 1, dents[cur].name, r);
|
|
||||||
*path = g_ctx[r].c_path;
|
|
||||||
*lastdir = g_ctx[r].c_last;
|
|
||||||
*lastname = g_ctx[r].c_name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6318,7 +6364,7 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
char *slash, *tmp;
|
char *slash, *tmp;
|
||||||
ssize_t len = xstrlen(prefix);
|
ssize_t len = xstrlen(prefix);
|
||||||
char *tmpdir = malloc(sizeof(char) * (PATH_MAX + TMP_LEN_MAX));
|
char *tmpdir = malloc(PATH_MAX);
|
||||||
|
|
||||||
if (!tmpdir) {
|
if (!tmpdir) {
|
||||||
DPRINTF_S(strerror(errno));
|
DPRINTF_S(strerror(errno));
|
||||||
|
@ -6377,7 +6423,7 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
|
||||||
return tmpdir;
|
return tmpdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *load_input()
|
static char *load_input(int fd, char *path)
|
||||||
{
|
{
|
||||||
/* 512 KiB chunk size */
|
/* 512 KiB chunk size */
|
||||||
ssize_t i, chunk_count = 1, chunk = 512 * 1024, entries = 0;
|
ssize_t i, chunk_count = 1, chunk = 512 * 1024, entries = 0;
|
||||||
|
@ -6392,13 +6438,16 @@ static char *load_input()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getcwd(cwd, PATH_MAX)) {
|
if (!path) {
|
||||||
free(input);
|
if (!getcwd(cwd, PATH_MAX)) {
|
||||||
return NULL;
|
free(input);
|
||||||
}
|
return NULL;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
xstrsncpy(cwd, path, PATH_MAX);
|
||||||
|
|
||||||
while (chunk_count < 512) {
|
while (chunk_count < 512) {
|
||||||
input_read = read(STDIN_FILENO, input + total_read, chunk);
|
input_read = read(fd, input + total_read, chunk);
|
||||||
if (input_read < 0) {
|
if (input_read < 0) {
|
||||||
DPRINTF_S(strerror(errno));
|
DPRINTF_S(strerror(errno));
|
||||||
goto malloc_1;
|
goto malloc_1;
|
||||||
|
@ -6461,7 +6510,11 @@ static char *load_input()
|
||||||
DPRINTF_D(chunk_count);
|
DPRINTF_D(chunk_count);
|
||||||
|
|
||||||
if (!entries) {
|
if (!entries) {
|
||||||
fprintf(stderr, "0 entries\n");
|
if (g_states & STATE_PLUGIN_INIT) {
|
||||||
|
printmsg(messages[MSG_0_ENTRIES]);
|
||||||
|
xdelay(XDELAY_INTERVAL_MS);
|
||||||
|
} else
|
||||||
|
fprintf(stderr, "%s\n", messages[MSG_0_ENTRIES]);
|
||||||
goto malloc_1;
|
goto malloc_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6842,7 +6895,7 @@ int main(int argc, char *argv[])
|
||||||
/* Check if we are in path list mode */
|
/* Check if we are in path list mode */
|
||||||
if (!isatty(STDIN_FILENO)) {
|
if (!isatty(STDIN_FILENO)) {
|
||||||
/* This is the same as listpath */
|
/* This is the same as listpath */
|
||||||
initpath = load_input();
|
initpath = load_input(STDIN_FILENO, NULL);
|
||||||
if (!initpath)
|
if (!initpath)
|
||||||
return _FAILURE;
|
return _FAILURE;
|
||||||
|
|
||||||
|
@ -7054,8 +7107,7 @@ int main(int argc, char *argv[])
|
||||||
unlink(selpath);
|
unlink(selpath);
|
||||||
|
|
||||||
/* Remove tmp dir in list mode */
|
/* Remove tmp dir in list mode */
|
||||||
if (listpath)
|
rmlistpath();
|
||||||
spawn("rm -rf", initpath, NULL, NULL, F_NOTRACE | F_MULTI);
|
|
||||||
|
|
||||||
/* Free the regex */
|
/* Free the regex */
|
||||||
#ifdef PCRE
|
#ifdef PCRE
|
||||||
|
|
Loading…
Reference in a new issue