]> Sergey Matveev's repositories - nnn.git/commitdiff
Add an option to print hovered files to a FIFO (#548)
authorlvgx <l@vgx.fr>
Mon, 4 May 2020 04:05:13 +0000 (06:05 +0200)
committerGitHub <noreply@github.com>
Mon, 4 May 2020 04:05:13 +0000 (09:35 +0530)
* Add an option to print hovered files to a FIFO

This adds an env variable, `NNN_FIFO`, that can be set to a path that
`nnn` will open/create as a FIFO, and where every hovered file's path is
printed. This allows creating external perview/quick open plugins, ...

It can be compiled out with the make variable `O_NOFIFO`.

* Check filename ptr instead of full path (for FIFO)

* Add documentation to use NNN_FIFO in plugins

* Fix path sent to FIFO in empty dirs

Makefile
nnn.1
plugins/README.md
src/nnn.c

index 3c0e08a7ae9e66252c5ca825d0e270b453b66aa6..004c5248a1c5a362e37d1834d2dcb92056a6e334 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,10 @@ ifeq ($(O_NOBATCH),1)
        CPPFLAGS += -DNOBATCH
 endif
 
+ifeq ($(O_NOFIFO),1)
+       CPPFLAGS += -DNOFIFO
+endif
+
 ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1)
        CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw)
        LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs   ncursesw)
diff --git a/nnn.1 b/nnn.1
index 5048bb07a6ea5cb16c1094f96957c6f9939b447a..95e93a64afb87080867f8120a1468741caf01cd6 100644 (file)
--- a/nnn.1
+++ b/nnn.1
@@ -423,6 +423,13 @@ separated by \fI;\fR:
 .Pp
 \fBNNN_SEL:\fR absolute path to custom selection file.
 .Pp
+\fBNNN_FIFO:\fR path of a named pipe to write current file path:
+.Bd -literal
+    export NNN_FIFO='/tmp/nnn.fifo'
+
+    NOTE: If the FIFO file doesn't exist it will be created, but it will never be removed.
+.Ed
+.Pp
 \fBnnn:\fR this is a special variable set to the hovered entry before executing
 a command from the command prompt or spawning a shell.
 .Pp
index e8f8958519b5339c53dce613c11fbc844acaa6c0..40386bb938e5094f5614fbff7d3fa5a8e2b86810 100644 (file)
@@ -190,7 +190,7 @@ Usage examples can be found in the Examples section below.
 There are many plugins provided by `nnn` which can be used as examples. Here are a few simple selected examples.
 
 - Show the git log of changes to the particular file along with the code for a quick and easy review.
-   ```sh
+    ```sh
     #!/usr/bin/env sh
     git log -p -- "$1"
     ```
@@ -220,6 +220,40 @@ There are many plugins provided by `nnn` which can be used as examples. Here are
     printf "%s" "0c$dir" > "$NNN_PIPE"
     ```
 
+#### Get notified on file hover
+
+If `NNN_FIFO` is set, `nnn` will open it and write every hovered files.
+This can be used in plugins, e.g. to implement file previews.
+
+If a `NNN_FIFO` is set globally, each `nnn` instance will write to it, and a process reading from the pipe will get hovered path from every instance, interleaved.
+
+If you want to prevent this and be sure to have a private pipe to one `nnn` instance, you can unlink (remove) the FIFO file.
+If you opened the FIFO before and you have read from it (so that `nnn` have it opened too), you can still read from it while you don't close it.
+But new `nnn` instances will recreate a new FIFO not linked to the previous one.
+
+Don't forget to fork in the background to avoid blocking `nnn`.
+
+Example (send every hovered file to X selection):
+
+```sh
+#!/usr/bin/env sh
+if [ -z "$NNN_FIFO" ] ; then
+       exit 1
+fi
+
+while read FILE ; do
+       if [ -n "$NNN_FIFO" ] ; then
+               # If you want to remove the FIFO,
+               # don't do it before first read,
+               # nnn won't have it opened yet
+               rm "$NNN_FIFO"
+               NNN_FIFO=
+       fi
+       printf "%s" "$FILE" | xsel
+done < "$NNN_FIFO" &
+disown
+```
+
 ## Contributing plugins
 
 1. Add informative sections like _Description_, _Notes_, _Dependencies_, _Shell_, _Author_ etc. in the plugin.
index 19adf93055c47c76cfb5629eabb4a2bbefd9395b..e6463931f21a317e6507e2f23cb217389edeb200 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -330,6 +330,9 @@ static context g_ctx[CTX_MAX] __attribute__ ((aligned));
 
 static int ndents, cur, last, curscroll, last_curscroll, total_dents = ENTRY_INCR;
 static int nselected;
+#ifndef NOFIFO
+static int fifofd = -1;
+#endif
 static uint idletimeout, selbufpos, lastappendpos, selbuflen;
 static ushort xlines, xcols;
 static ushort idle;
@@ -350,6 +353,9 @@ static char *prefixpath;
 static char *plugindir;
 static char *sessiondir;
 static char *pnamebuf, *pselbuf;
+#ifndef NOFIFO
+static char *fifopath;
+#endif
 static ull *ihashbmp;
 static struct entry *dents;
 static blkcnt_t ent_blocks;
@@ -4667,6 +4673,40 @@ static void populate(char *path, char *lastname)
        last_curscroll = -1;
 }
 
+#ifndef NOFIFO
+static void notify_fifo()
+{
+       if (fifofd == -1) {
+               fifofd = open(fifopath, O_WRONLY|O_NONBLOCK);
+               if (fifofd == -1) {
+                       if (errno != ENXIO)
+                               /* Unexpected error, the FIFO file might have been removed */
+                               /* We give up FIFO notification */
+                               fifopath = NULL;
+                       return;
+               }
+       }
+
+       static char *name = NULL;
+
+       if (dents[cur].name == name)
+               return;
+
+       name = dents[cur].name;
+
+       char path[PATH_MAX];
+       size_t len = mkpath(g_ctx[cfg.curctx].c_path, ndents ? name : "", path);
+
+       path[len - 1] = '\n';
+
+       ssize_t ret = write(fifofd, path, len);
+
+       if (ret != (ssize_t)len && !(ret == -1 && (errno == EAGAIN || errno == EPIPE))) {
+               DPRINTF_S(strerror(errno));
+       }
+}
+#endif
+
 static void move_cursor(int target, int ignore_scrolloff)
 {
        int onscreen = xlines - 4; /* Leave top 2 and bottom 2 lines */
@@ -4693,6 +4733,11 @@ static void move_cursor(int target, int ignore_scrolloff)
        }
        curscroll = MIN(curscroll, MIN(cur, ndents - onscreen));
        curscroll = MAX(curscroll, MAX(cur - (onscreen - 1), 0));
+
+#ifndef NOFIFO
+       if (fifopath)
+               notify_fifo();
+#endif
 }
 
 static void handle_screen_move(enum action sel)
@@ -7022,6 +7067,19 @@ int main(int argc, char *argv[])
 
        DPRINTF_S(getenv("PWD"));
 
+#ifndef NOFIFO
+       /* Create fifo */
+       fifopath = getenv("NNN_FIFO");
+       if (fifopath) {
+               if (mkfifo(fifopath, 0600) != 0 && !(errno == EEXIST && access(fifopath, W_OK) == 0)) {
+                       xerror();
+                       return _FAILURE;
+               }
+
+               signal(SIGPIPE, SIG_IGN);
+       }
+#endif
+
 #ifdef LINUX_INOTIFY
        /* Initialize inotify */
        inotify_fd = inotify_init1(IN_NONBLOCK);
@@ -7145,5 +7203,10 @@ int main(int argc, char *argv[])
        haiku_close_nm(haiku_hnd);
 #endif
 
+#ifndef NOFIFO
+       if (fifofd != -1)
+               close(fifofd);
+#endif
+
        return opt;
 }