commit a447c12866f645dc9c6c7dc0137e63b52a974640
parent ffe472ac32b0ea71cb266f0dde4505b983d4970b
Author: Terminator X <engineerarun@gmail.com>
Date: Wed, 22 Sep 2021 09:08:32 +0530
Merge pull request #1173 from luukvbaal/previewpatch
Add restorepreview patch
Diffstat:
4 files changed, 269 insertions(+), 0 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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