]> Sergey Matveev's repositories - nnn.git/commitdiff
Plugin mimelist: support reading file list from (cmd as) plugin
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 3 May 2020 09:25:33 +0000 (14:55 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 3 May 2020 09:25:33 +0000 (14:55 +0530)
plugins/.nnn-plugin-helper
plugins/README.md
plugins/autojump
plugins/fzz
plugins/mimelist [new file with mode: 0755]
src/nnn.c

index 06b3bcbe9fc1a3313fe32f412635d3787e7c821a..0f74fc740f72d4734b831b12fbf5b254348e382a 100644 (file)
@@ -29,7 +29,7 @@ nnn_cd () {
         read -r context
     fi
 
-    printf "%s" "${context:-0}$dir" > "$NNN_PIPE"
+    printf "%s" "${context:-0}c$dir" > "$NNN_PIPE"
 }
 
 cmd_exists () {
index 9cafd3e3f8a6466cbc3cc988cbdca25ebb28fd11..b16ef9ee1892be1c44a4e46ab9f82d776cfa4255 100644 (file)
@@ -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 |
 | launch | GUI application launcher | sh | fzf/fzy |
 | 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/) |
 | 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 |
@@ -163,8 +164,14 @@ Drop the plugin in `${XDG_CONFIG_HOME:-$HOME/.config}/nnn/plugins` and make it e
 #### Controlling `nnn`'s 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 plugin should write a single string in the format `<number><path>` without a newline at the end. For example, `1/etc`.
-The number indicates the context to change the active directory of (0 is used to indicate the current context).
+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 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.
 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: "
     read -r dir
 
-    printf "%s" "0$dir" > "$NNN_PIPE"
+    printf "%s" "0c$dir" > "$NNN_PIPE"
     ```
 
 ## Contributing plugins
index ef39dd91d78bc30851dcd1badc385aeaa3adb8f4..db221f370f8c7cbf1b00b0d5692003f2186fa895 100755 (executable)
@@ -13,7 +13,7 @@ if which autojump >/dev/null 2>&1; then
     printf "jump to: "
     read -r dir
     odir="$(autojump "$dir")"
-    printf "%s" "0$odir" > "$NNN_PIPE"
+    printf "%s" "0c$odir" > "$NNN_PIPE"
 else
     printf "autojump missing"
     read -r _
index fa432c100bdb1c49a2d13ecba8e80e0d35e2f7bb..5b40269829398f607ff401d9185c273ef39a2238 100755 (executable)
@@ -25,4 +25,4 @@ else
     exit 1
 fi
 
-printf "%s" "0$sel" > "$NNN_PIPE"
+printf "%s" "0c$sel" > "$NNN_PIPE"
diff --git a/plugins/mimelist b/plugins/mimelist
new file mode 100755 (executable)
index 0000000..0ec7c0f
--- /dev/null
@@ -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"
index 59dacd2e1a2c4ad7b28761d64fb8e0a80572b04a..277673ac9b0363afd7c51f6685aae50e06d4f0a4 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -514,8 +514,9 @@ static char * const utils[] = {
 #define MSG_RM_TMP 40
 #define MSG_NOCHNAGE 41
 #define MSG_CANCEL 42
+#define MSG_0_ENTRIES 43
 #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
 
 static const char * const messages[] = {
@@ -562,6 +563,7 @@ static const char * const messages[] = {
        "unchanged",
        "cancelled",
        "first file (\')/char?",
+       "0 entries",
 #ifndef DIR_LIMITED_SELECTION
        "dir changed, range sel off", /* Must be the last entry */
 #endif
@@ -691,6 +693,7 @@ static inline bool getutil(char *util);
 static size_t mkpath(const char *dir, const char *name, char *out);
 static char *xgetenv(const char *name, char *fallback);
 static bool plugscript(const char *plugin, const char *path, uchar flags);
+static char *load_input(int fd, char *path);
 
 /* Functions */
 
@@ -4218,11 +4221,72 @@ static bool plctrl_init(void)
        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)
 {
        int fd;
-       size_t len;
-
        if (!(g_states & STATE_PLUGIN_INIT)) {
                plctrl_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);
        }
 
-       len = read(fd, g_buf, PATH_MAX);
-       g_buf[len] = '\0';
-       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;
-               }
-       }
+       readpipe(fd, path, lastname, lastdir);
 
+       close(fd);
        return TRUE;
 }
 
@@ -6318,7 +6364,7 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
        struct stat sb;
        char *slash, *tmp;
        ssize_t len = xstrlen(prefix);
-       char *tmpdir = malloc(sizeof(char) * (PATH_MAX + TMP_LEN_MAX));
+       char *tmpdir = malloc(PATH_MAX);
 
        if (!tmpdir) {
                DPRINTF_S(strerror(errno));
@@ -6377,7 +6423,7 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
        return tmpdir;
 }
 
-static char *load_input()
+static char *load_input(int fd, char *path)
 {
        /* 512 KiB chunk size */
        ssize_t i, chunk_count = 1, chunk = 512 * 1024, entries = 0;
@@ -6392,13 +6438,16 @@ static char *load_input()
                return NULL;
        }
 
-       if (!getcwd(cwd, PATH_MAX)) {
-               free(input);
-               return NULL;
-       }
+       if (!path) {
+               if (!getcwd(cwd, PATH_MAX)) {
+                       free(input);
+                       return NULL;
+               }
+       } else
+               xstrsncpy(cwd, path, PATH_MAX);
 
        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) {
                        DPRINTF_S(strerror(errno));
                        goto malloc_1;
@@ -6461,7 +6510,11 @@ static char *load_input()
        DPRINTF_D(chunk_count);
 
        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;
        }
 
@@ -6842,7 +6895,7 @@ int main(int argc, char *argv[])
        /* Check if we are in path list mode */
        if (!isatty(STDIN_FILENO)) {
                /* This is the same as listpath */
-               initpath = load_input();
+               initpath = load_input(STDIN_FILENO, NULL);
                if (!initpath)
                        return _FAILURE;
 
@@ -7054,8 +7107,7 @@ int main(int argc, char *argv[])
                unlink(selpath);
 
        /* Remove tmp dir in list mode */
-       if (listpath)
-               spawn("rm -rf", initpath, NULL, NULL, F_NOTRACE | F_MULTI);
+       rmlistpath();
 
        /* Free the regex */
 #ifdef PCRE