From: Luuk van Baal <luukvbaal@gmail.com>
Date: Wed, 22 Sep 2021 02:13:57 +0000 (+0200)
Subject: Add restorepreview patch
X-Git-Tag: v4.3~7^2
X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=d96a7bc2b7d36453aa7685f70ca582667a624335;p=nnn.git

Add restorepreview patch
---

diff --git a/Makefile b/Makefile
index 869a47ce..c6edbfa3 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,7 @@ O_MATCHFLTR := 0  # allow filters without matches
 # User patches
 O_GITSTATUS := 0 # add git status to detail view
 O_NAMEFIRST := 0 # print file name first, add uid and guid to detail view
+O_RESTOREPREVIEW := 0 # add preview pipe to close and restore preview pane
 
 # convert targets to flags for backwards compatibility
 ifneq ($(filter debug,$(MAKECMDGOALS)),)
@@ -152,6 +153,7 @@ LOGO64X64 = misc/logo/logo-64x64.png
 
 GITSTATUS = patches/gitstatus
 NAMEFIRST = patches/namefirst
+RESTOREPREVIEW = patches/restorepreview
 
 # test if we are on Mac OS X and get X.Y.Z OS version with system binary /usr/bin/sw_vers
 MACOS_VERSION := $(strip $(shell command -v sw_vers >/dev/null && [ "`sw_vers -productName`" = "Mac OS X" ] && sw_vers -productVersion))
@@ -280,6 +282,9 @@ endif
 else ifeq ($(strip $(O_GITSTATUS)),1)
 	patch --forward --strip=1 --input=$(GITSTATUS)/mainline.diff
 endif
+ifeq ($(strip $(O_RESTOREPREVIEW)),1)
+	patch --forward --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
+endif
 
 postpatch:
 ifeq ($(strip $(O_NAMEFIRST)),1)
@@ -290,6 +295,9 @@ endif
 else ifeq ($(strip $(O_GITSTATUS)),1)
 	patch --reverse --strip=1 --input=$(GITSTATUS)/mainline.diff
 endif
+ifeq ($(strip $(O_RESTOREPREVIEW)),1)
+	patch --reverse --strip=1 --input=$(RESTOREPREVIEW)/mainline.diff
+endif
 
 skip: ;
 
diff --git a/patches/README.md b/patches/README.md
index d0eae2f8..4f3952f6 100644
--- a/patches/README.md
+++ b/patches/README.md
@@ -9,6 +9,7 @@ The patches will be adapted on each release when necessary (v4.1 onwards). Each
 | --- | --- | --- |
 | gitstatus | Add git status column to the detail view. Provides command line flag `-G` to show column in normal mode. | `O_GISTATUS` |
 | namefirst | Print filenames first in the detail view. Print user/group columns when a directory contains different users/groups. | `O_NAMEFIRST` |
+| restorepreview | Add pipe to close and restore [`preview-tui`](https://github.com/jarun/nnn/blob/master/plugins/preview-tui) for internal undetached edits (<kbd>e</kbd> key)| `O_RESTOREPREVIEW` |
 
 To apply a patch, use the corresponding make variable, e.g.:
 
diff --git a/patches/restorepreview/mainline.diff b/patches/restorepreview/mainline.diff
new file mode 100644
index 00000000..0e35e6f2
--- /dev/null
+++ b/patches/restorepreview/mainline.diff
@@ -0,0 +1,257 @@
+# Description: Adds preview pipe to enable closing and re-opening
+#              the preview pane when running an undetached editor.
+#
+# Authors: Luuk van Baal
+
+diff --git a/src/nnn.c b/src/nnn.c
+index 44f297f4..f15b3bc1 100644
+--- a/src/nnn.c
++++ b/src/nnn.c
+@@ -367,7 +367,8 @@ typedef struct {
+ 	uint_t stayonsel  : 1;  /* Disable auto-proceed on select */
+ 	uint_t trash      : 2;  /* Use trash to delete files 1: trash-cli, 2: gio trash */
+ 	uint_t uidgid     : 1;  /* Show owner and group info */
+-	uint_t reserved   : 7;  /* Adjust when adding/removing a field */
++	uint_t previewer  : 1;  /* Run state of previewer */
++	uint_t reserved   : 6;  /* Adjust when adding/removing a field */
+ } runstate;
+ 
+ /* Contexts or workspaces */
+@@ -513,6 +514,9 @@ static char g_tmpfpath[TMP_LEN_MAX] __attribute__ ((aligned));
+ /* Buffer to store plugins control pipe location */
+ static char g_pipepath[TMP_LEN_MAX] __attribute__ ((aligned));
+ 
++/* Buffer to store preview plugins control pipe location */
++static char g_ppipepath[TMP_LEN_MAX] __attribute__ ((aligned));
++
+ /* Non-persistent runtime states */
+ static runstate g_state;
+ 
+@@ -687,12 +691,13 @@ static const char * const messages[] = {
+ #define NNN_FCOLORS 5
+ #define NNNLVL      6
+ #define NNN_PIPE    7
+-#define NNN_MCLICK  8
+-#define NNN_SEL     9
+-#define NNN_ARCHIVE 10
+-#define NNN_ORDER   11
+-#define NNN_HELP    12 /* strings end here */
+-#define NNN_TRASH   13 /* flags begin here */
++#define NNN_PPIPE   8
++#define NNN_MCLICK  9
++#define NNN_SEL     10
++#define NNN_ARCHIVE 11
++#define NNN_ORDER   12
++#define NNN_HELP    13 /* strings end here */
++#define NNN_TRASH   14 /* flags begin here */
+ 
+ static const char * const env_cfg[] = {
+ 	"NNN_OPTS",
+@@ -703,6 +708,7 @@ static const char * const env_cfg[] = {
+ 	"NNN_FCOLORS",
+ 	"NNNLVL",
+ 	"NNN_PIPE",
++	"NNN_PPIPE",
+ 	"NNN_MCLICK",
+ 	"NNN_SEL",
+ 	"NNN_ARCHIVE",
+@@ -846,7 +852,7 @@ static char *load_input(int fd, const char *path);
+ static int set_sort_flags(int r);
+ static void statusbar(char *path);
+ #ifndef NOFIFO
+-static void notify_fifo(bool force);
++static void notify_fifo(bool force, bool closepreview);
+ #endif
+ 
+ /* Functions */
+@@ -3045,7 +3051,7 @@ try_quit:
+ 			} else {
+ #ifndef NOFIFO
+ 				if (!g_state.fifomode)
+-					notify_fifo(TRUE); /* Send hovered path to NNN_FIFO */
++					notify_fifo(TRUE, FALSE); /* Send hovered path to NNN_FIFO */
+ #endif
+ 				escaped = TRUE;
+ 				settimeout();
+@@ -5131,15 +5137,20 @@ static bool run_cmd_as_plugin(const char *file, uchar_t flags)
+ 
+ static bool plctrl_init(void)
+ {
+-	size_t len;
++	size_t len, lenbuf;
++	pid_t pid = getpid();
+ 
+ 	/* g_tmpfpath is used to generate tmp file names */
+ 	g_tmpfpath[tmpfplen - 1] = '\0';
+-	len = xstrsncpy(g_pipepath, g_tmpfpath, TMP_LEN_MAX);
++	len = lenbuf = xstrsncpy(g_pipepath, g_tmpfpath, TMP_LEN_MAX);
+ 	g_pipepath[len - 1] = '/';
+-	len = xstrsncpy(g_pipepath + len, "nnn-pipe.", TMP_LEN_MAX - len) + len;
+-	xstrsncpy(g_pipepath + len - 1, xitoa(getpid()), TMP_LEN_MAX - len);
++	xstrsncpy(g_ppipepath, g_pipepath, TMP_LEN_MAX);
++	len += xstrsncpy(g_pipepath + len, "nnn-pipe.", TMP_LEN_MAX - len);
++	xstrsncpy(g_pipepath + len - 1, xitoa(pid), TMP_LEN_MAX - len);
++	len = xstrsncpy(g_ppipepath + lenbuf, "nnn-ppipe.", TMP_LEN_MAX - lenbuf) + lenbuf;
++	xstrsncpy(g_ppipepath + len - 1, xitoa(pid), TMP_LEN_MAX - len);
+ 	setenv(env_cfg[NNN_PIPE], g_pipepath, TRUE);
++	setenv(env_cfg[NNN_PPIPE], g_ppipepath, TRUE);
+ 
+ 	return EXIT_SUCCESS;
+ }
+@@ -5168,6 +5179,21 @@ static ssize_t read_nointr(int fd, void *buf, size_t count)
+ 	return len;
+ }
+ 
++void *previewpipe(void *arg __attribute__ ((unused)))
++{
++	int fd, buf;
++
++	mkfifo(g_ppipepath, 0600);
++	fd = open(g_ppipepath, O_RDONLY);
++
++	if (read(fd, &buf, 1) == 1)
++		g_state.previewer = buf;
++
++	close(fd);
++	unlink(g_ppipepath);
++	return NULL;
++}
++
+ static char *readpipe(int fd, char *ctxnum, char **path)
+ {
+ 	char ctx, *nextpath = NULL;
+@@ -5787,7 +5813,7 @@ static void populate(char *path, char *lastname)
+ }
+ 
+ #ifndef NOFIFO
+-static void notify_fifo(bool force)
++static void notify_fifo(bool force, bool closepreview)
+ {
+ 	if (!fifopath)
+ 		return;
+@@ -5803,6 +5829,12 @@ static void notify_fifo(bool force)
+ 		}
+ 	}
+ 
++	if (closepreview) {
++		if (write(fifofd, "close\n", 6) != 6)
++			xerror();
++		return;
++	}
++
+ 	static struct entry lastentry;
+ 
+ 	if (!force && !memcmp(&lastentry, &pdents[cur], sizeof(struct entry)))
+@@ -5852,7 +5884,7 @@ static void move_cursor(int target, int ignore_scrolloff)
+ 
+ #ifndef NOFIFO
+ 	if (!g_state.fifomode)
+-		notify_fifo(FALSE); /* Send hovered path to NNN_FIFO */
++		notify_fifo(FALSE, FALSE); /* Send hovered path to NNN_FIFO */
+ #endif
+ }
+ 
+@@ -6473,6 +6505,7 @@ static bool browse(char *ipath, const char *session, int pkey)
+ 	const uchar_t opener_flags = (cfg.cliopener ? F_CLI : (F_NOTRACE | F_NOSTDIN | F_NOWAIT));
+ 	bool watch = FALSE;
+ 	ino_t inode = 0;
++	static int previewkey;
+ 
+ #ifndef NOMOUSE
+ 	MEVENT event = {0};
+@@ -6735,7 +6768,7 @@ nochange:
+ 					move_cursor(r, 1);
+ #ifndef NOFIFO
+ 				else if ((event.bstate == BUTTON1_PRESSED) && !g_state.fifomode)
+-					notify_fifo(TRUE); /* Send clicked path to NNN_FIFO */
++					notify_fifo(TRUE, FALSE); /* Send clicked path to NNN_FIFO */
+ #endif
+ 				/* Handle right click selection */
+ 				if (event.bstate == BUTTON3_PRESSED) {
+@@ -6808,7 +6841,7 @@ nochange:
+                         }
+ #ifndef NOFIFO
+ 			if (g_state.fifomode && (sel == SEL_OPEN)) {
+-				notify_fifo(TRUE); /* Send opened path to NNN_FIFO */
++				notify_fifo(TRUE, FALSE); /* Send opened path to NNN_FIFO */
+ 				goto nochange;
+ 			}
+ #endif
+@@ -6890,7 +6923,17 @@ nochange:
+ 			    && strstr(g_buf, "text")
+ #endif
+ 			) {
++
++				if (g_state.previewer)
++					notify_fifo(FALSE, TRUE);
++
+ 				spawn(editor, newpath, NULL, NULL, F_CLI);
++
++				if (g_state.previewer) {
++					pkey = previewkey;
++					goto run_plugin;
++				}
++
+ 				if (cfg.filtermode) {
+ 					presel = FILTER;
+ 					clearfilter();
+@@ -7198,7 +7241,17 @@ nochange:
+ 				copycurname();
+ 				goto nochange;
+ 			case SEL_EDIT:
++
++				if (g_state.previewer)
++					notify_fifo(FALSE, TRUE);
++
+ 				spawn(editor, newpath, NULL, NULL, F_CLI);
++
++				if (g_state.previewer) {
++					pkey = previewkey;
++					goto run_plugin;
++				}
++
+ 				continue;
+ 			default: /* SEL_LOCK */
+ 				lock_terminal();
+@@ -7558,6 +7611,7 @@ nochange:
+ 
+ 			goto begin;
+ 		}
++run_plugin:
+ 		case SEL_PLUGIN:
+ 			/* Check if directory is accessible */
+ 			if (!xdiraccess(plgpath)) {
+@@ -7583,6 +7637,12 @@ nochange:
+ 					goto nochange;
+ 				}
+ 
++				if (xstrcmp(tmp, "preview-tui") == 0) {
++					previewkey = r;
++					pthread_t tid;
++					pthread_create(&tid, NULL, previewpipe, NULL);
++				}
++
+ 				if (tmp[0] == '-' && tmp[1]) {
+ 					++tmp;
+ 					r = FALSE; /* Do not refresh dir after completion */
+@@ -8181,8 +8241,10 @@ static void cleanup(void)
+ 	if (g_state.autofifo)
+ 		unlink(fifopath);
+ #endif
+-	if (g_state.pluginit)
++	if (g_state.pluginit){
+ 		unlink(g_pipepath);
++		unlink(g_ppipepath);
++	}
+ #ifdef DEBUG
+ 	disabledbg();
+ #endif
+@@ -8681,7 +8743,7 @@ int main(int argc, char *argv[])
+ 
+ #ifndef NOFIFO
+ 	if (!g_state.fifomode)
+-		notify_fifo(FALSE);
++		notify_fifo(FALSE, FALSE);
+ 	if (fifofd != -1)
+ 		close(fifofd);
+ #endif
diff --git a/plugins/preview-tui b/plugins/preview-tui
index b6788fc4..e08dd715 100755
--- a/plugins/preview-tui
+++ b/plugins/preview-tui
@@ -151,8 +151,10 @@ toggle_preview() {
         if [ -n "$QLPATH" ] && stat "$1"; then
             f="$(wslpath -w "$1")" && "$QLPATH" "$f" &
         fi
+        printf "0" > "$NNN_PPIPE"
     else
         start_preview "$1" "$QLPATH"
+        printf "1" > "$NNN_PPIPE"
     fi
 } >/dev/null 2>&1
 
@@ -389,6 +391,7 @@ preview_fifo() {
         if [ -n "$selection" ]; then
             kill "$(cat "$PREVIEWPID")"
             [ -p "$FIFO_UEBERZUG" ] && ueberzug_remove
+            [ "$selection" = "close" ] && sleep 0.1 && break
             preview_file "$selection"
             printf "%s" "$selection" > "$CURSEL"
         fi