From b2e7f7794cbf52048b71093ccb18549c43f2512b Mon Sep 17 00:00:00 2001 From: Michael Lan <44309097+mizlan@users.noreply.github.com> Date: Thu, 17 Jun 2021 16:51:51 -0700 Subject: [PATCH] Refactor fifo code and add explorer (#1075) * Refactor fifo code and add explorer * add explorer option and flag * notify explorer fifo on selection * close explorer fifo file descriptor * Try to create explorer fifo if doesn't exist This doesn't quite work * Allow uncreated fifos * delete persistence fifo on cleanup with correct formatting Co-authored-by: luukvbaal <31730729+luukvbaal@users.noreply.github.com> * Work correctly with NOFIFO * Refactor variable names * fix * Use -X flag for explorer mode * Update manpage with explorer mode Co-authored-by: luukvbaal <31730729+luukvbaal@users.noreply.github.com> --- nnn.1 | 5 +++- src/nnn.c | 78 +++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/nnn.1 b/nnn.1 index 452bb566..19e5ba76 100644 --- a/nnn.1 +++ b/nnn.1 @@ -6,7 +6,7 @@ .Nd The unorthodox terminal file manager. .Sh SYNOPSIS .Nm -.Op Ar -aAcCdDeEfgHJKlnQrRSuUVwxh +.Op Ar -aAcCdDeEfgHJKlnQrRSuUVwxXh .Op Ar -b key .Op Ar -p file .Op Ar -P key @@ -139,6 +139,9 @@ supports the following options: copy path to system clipboard on select show xterm title (if non-picker mode) .Pp +.Fl "X fifo" + run in explorer mode, where file path is sent to 'fifo' on 'Enter' or '^M' +.Pp .Fl h show program help and exit .Sh CONFIGURATION diff --git a/src/nnn.c b/src/nnn.c index 7d46018b..1c993838 100644 --- a/src/nnn.c +++ b/src/nnn.c @@ -331,6 +331,7 @@ typedef struct { uint_t dircolor : 1; /* Current status of dir color */ uint_t picker : 1; /* Write selection to user-specified file */ uint_t picked : 1; /* Plugin has picked files */ + uint_t explorer : 1; /* Explorer mode: send picked files to FIFO without exiting */ uint_t runplugin : 1; /* Choose plugin mode */ uint_t runctx : 3; /* The context in which plugin is to be run */ uint_t selmode : 1; /* Set when selecting files */ @@ -340,7 +341,7 @@ typedef struct { uint_t uidgid : 1; /* Show owner and group info */ uint_t prstssn : 1; /* Persistent session */ uint_t duinit : 1; /* Initialize disk usage */ - uint_t reserved : 8; /* Adjust when adding/removing a field */ + uint_t reserved : 7; /* Adjust when adding/removing a field */ } runstate; /* Contexts or workspaces */ @@ -401,7 +402,8 @@ static context g_ctx[CTX_MAX] __attribute__ ((aligned)); static int ndents, cur, last, curscroll, last_curscroll, total_dents = ENTRY_INCR, scroll_lines = 1; static int nselected; #ifndef NOFIFO -static int fifofd = -1; +static int hfifofd = -1; /* FIFO used in hover (NNN_FIFO) */ +static int efifofd = -1; /* FIFO used in explorer mode (-X) */ #endif static uint_t idletimeout, selbufpos, lastappendpos, selbuflen; static ushort_t xlines, xcols; @@ -424,7 +426,8 @@ static char *plgpath; static char *pnamebuf, *pselbuf; static char *mark; #ifndef NOFIFO -static char *fifopath; +static char *hfifopath; /* FIFO used in hover (NNN_FIFO) */ +static char *efifopath; /* FIFO used in explorer mode (-X) */ #endif static unsigned long long *ihashbmp; static struct entry *pdents; @@ -808,7 +811,7 @@ static void move_cursor(int target, int ignore_scrolloff); static char *load_input(int fd, const char *path); static int set_sort_flags(int r); #ifndef NOFIFO -static void notify_fifo(bool force); +static void notify_fifo(bool force, bool explorer); #endif /* Functions */ @@ -2757,7 +2760,7 @@ try_quit: } else { #ifndef NOFIFO /* Send hovered path to NNN_FIFO */ - notify_fifo(TRUE); + notify_fifo(TRUE, FALSE); #endif escaped = TRUE; settimeout(); @@ -5409,18 +5412,22 @@ static void populate(char *path, char *lastname) } #ifndef NOFIFO -static void notify_fifo(bool force) +static void notify_fifo(bool force, bool explorer) { - if (!fifopath) + /* refer to the explorer fifo instead of the hover fifo if explorer is true */ + char **ppath = explorer ? &efifopath : &hfifopath; + int *pptr = explorer ? &efifofd : &hfifofd; + + if (!(*ppath)) return; - if (fifofd == -1) { - fifofd = open(fifopath, O_WRONLY|O_NONBLOCK|O_CLOEXEC); - if (fifofd == -1) { + if (*pptr == -1) { + *pptr = open(*ppath, O_WRONLY|O_NONBLOCK|O_CLOEXEC); + if (*pptr == -1) { if (errno != ENXIO) /* Unexpected error, the FIFO file might have been removed */ /* We give up FIFO notification */ - fifopath = NULL; + *ppath = NULL; return; } } @@ -5437,7 +5444,7 @@ static void notify_fifo(bool force) path[len - 1] = '\n'; - ssize_t ret = write(fifofd, path, len); + ssize_t ret = write(*pptr, path, len); if (ret != (ssize_t)len && !(ret == -1 && (errno == EAGAIN || errno == EPIPE))) { DPRINTF_S(strerror(errno)); @@ -5473,7 +5480,7 @@ static void move_cursor(int target, int ignore_scrolloff) curscroll = MAX(curscroll, MAX(cur - (onscreen - 1), 0)); #ifndef NOFIFO - notify_fifo(FALSE); + notify_fifo(FALSE, FALSE); #endif } @@ -6339,7 +6346,7 @@ nochange: move_cursor(r, 1); #ifndef NOFIFO else if (event.bstate == BUTTON1_PRESSED) - notify_fifo(TRUE); + notify_fifo(TRUE, FALSE); #endif /* Handle right click selection */ if (event.bstate == BUTTON3_PRESSED) { @@ -6409,6 +6416,11 @@ nochange: if (!S_ISREG(sb.st_mode)) { printwait(messages[MSG_UNSUPPORTED], &presel); goto nochange; + } + + if (g_state.explorer && sel == SEL_OPEN) { + notify_fifo(TRUE, TRUE); + goto nochange; } /* If opened as vim plugin and Enter/^M pressed, pick */ @@ -7636,6 +7648,9 @@ static void usage(void) " -w place HW cursor on hovered\n" #ifndef NOX11 " -x notis, selection sync, xterm title\n" +#endif +#ifndef NOFIFO + " -X fifo explorer mode\n" #endif " -h show help\n\n" "v%s\n%s\n", __func__, VERSION, GENERAL_INFO); @@ -7761,7 +7776,9 @@ static void cleanup(void) free(plug); #ifndef NOFIFO if (g_state.autofifo) - unlink(fifopath); + unlink(hfifopath); + if (g_state.explorer) + unlink(efifopath); #endif if (g_state.pluginit) unlink(g_pipepath); @@ -7793,7 +7810,7 @@ int main(int argc, char *argv[]) while ((opt = (env_opts_id > 0 ? env_opts[--env_opts_id] - : getopt(argc, argv, "aAb:cCdDeEfgHJKl:nop:P:QrRs:St:T:uUVwxh"))) != -1) { + : getopt(argc, argv, "aAb:cCdDeEfgHJKl:nop:P:QrRs:St:T:uUVwxX:h"))) != -1) { switch (opt) { #ifndef NOFIFO case 'a': @@ -7920,6 +7937,12 @@ int main(int argc, char *argv[]) case 'x': cfg.x11 = 1; break; + case 'X': +#ifndef NOFIFO + g_state.explorer = TRUE; + efifopath = optarg; +#endif + break; case 'h': usage(); return EXIT_SUCCESS; @@ -8075,9 +8098,18 @@ int main(int argc, char *argv[]) setenv("NNN_FIFO", g_buf, TRUE); } - fifopath = xgetenv("NNN_FIFO", NULL); - if (fifopath) { - if (mkfifo(fifopath, 0600) != 0 && !(errno == EEXIST && access(fifopath, W_OK) == 0)) { + hfifopath = xgetenv("NNN_FIFO", NULL); + if (hfifopath) { + if (mkfifo(hfifopath, 0600) != 0 && !(errno == EEXIST && access(hfifopath, W_OK) == 0)) { + xerror(); + return EXIT_FAILURE; + } + + sigaction(SIGPIPE, &(struct sigaction){.sa_handler = SIG_IGN}, NULL); + } + + if (g_state.explorer) { + if (mkfifo(efifopath, 0600) != 0 && !(errno == EEXIST && access(efifopath, W_OK) == 0)) { xerror(); return EXIT_FAILURE; } @@ -8232,9 +8264,11 @@ int main(int argc, char *argv[]) #endif #ifndef NOFIFO - notify_fifo(FALSE); - if (fifofd != -1) - close(fifofd); + notify_fifo(FALSE, FALSE); + if (hfifofd != -1) + close(hfifofd); + if (efifofd != -1) + close(efifofd); #endif return opt;