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>
This commit is contained in:
Michael Lan 2021-06-17 16:51:51 -07:00 committed by Arun Prakash Jana
parent 02b5b15001
commit b2e7f7794c
No known key found for this signature in database
GPG key ID: A75979F35C080412
2 changed files with 60 additions and 23 deletions

5
nnn.1
View file

@ -6,7 +6,7 @@
.Nd The unorthodox terminal file manager. .Nd The unorthodox terminal file manager.
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Ar -aAcCdDeEfgHJKlnQrRSuUVwxh .Op Ar -aAcCdDeEfgHJKlnQrRSuUVwxXh
.Op Ar -b key .Op Ar -b key
.Op Ar -p file .Op Ar -p file
.Op Ar -P key .Op Ar -P key
@ -139,6 +139,9 @@ supports the following options:
copy path to system clipboard on select copy path to system clipboard on select
show xterm title (if non-picker mode) show xterm title (if non-picker mode)
.Pp .Pp
.Fl "X fifo"
run in explorer mode, where file path is sent to 'fifo' on 'Enter' or '^M'
.Pp
.Fl h .Fl h
show program help and exit show program help and exit
.Sh CONFIGURATION .Sh CONFIGURATION

View file

@ -331,6 +331,7 @@ typedef struct {
uint_t dircolor : 1; /* Current status of dir color */ uint_t dircolor : 1; /* Current status of dir color */
uint_t picker : 1; /* Write selection to user-specified file */ uint_t picker : 1; /* Write selection to user-specified file */
uint_t picked : 1; /* Plugin has picked files */ 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 runplugin : 1; /* Choose plugin mode */
uint_t runctx : 3; /* The context in which plugin is to be run */ uint_t runctx : 3; /* The context in which plugin is to be run */
uint_t selmode : 1; /* Set when selecting files */ 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 uidgid : 1; /* Show owner and group info */
uint_t prstssn : 1; /* Persistent session */ uint_t prstssn : 1; /* Persistent session */
uint_t duinit : 1; /* Initialize disk usage */ 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; } runstate;
/* Contexts or workspaces */ /* 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 ndents, cur, last, curscroll, last_curscroll, total_dents = ENTRY_INCR, scroll_lines = 1;
static int nselected; static int nselected;
#ifndef NOFIFO #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 #endif
static uint_t idletimeout, selbufpos, lastappendpos, selbuflen; static uint_t idletimeout, selbufpos, lastappendpos, selbuflen;
static ushort_t xlines, xcols; static ushort_t xlines, xcols;
@ -424,7 +426,8 @@ static char *plgpath;
static char *pnamebuf, *pselbuf; static char *pnamebuf, *pselbuf;
static char *mark; static char *mark;
#ifndef NOFIFO #ifndef NOFIFO
static char *fifopath; static char *hfifopath; /* FIFO used in hover (NNN_FIFO) */
static char *efifopath; /* FIFO used in explorer mode (-X) */
#endif #endif
static unsigned long long *ihashbmp; static unsigned long long *ihashbmp;
static struct entry *pdents; 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 char *load_input(int fd, const char *path);
static int set_sort_flags(int r); static int set_sort_flags(int r);
#ifndef NOFIFO #ifndef NOFIFO
static void notify_fifo(bool force); static void notify_fifo(bool force, bool explorer);
#endif #endif
/* Functions */ /* Functions */
@ -2757,7 +2760,7 @@ try_quit:
} else { } else {
#ifndef NOFIFO #ifndef NOFIFO
/* Send hovered path to NNN_FIFO */ /* Send hovered path to NNN_FIFO */
notify_fifo(TRUE); notify_fifo(TRUE, FALSE);
#endif #endif
escaped = TRUE; escaped = TRUE;
settimeout(); settimeout();
@ -5409,18 +5412,22 @@ static void populate(char *path, char *lastname)
} }
#ifndef NOFIFO #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; return;
if (fifofd == -1) { if (*pptr == -1) {
fifofd = open(fifopath, O_WRONLY|O_NONBLOCK|O_CLOEXEC); *pptr = open(*ppath, O_WRONLY|O_NONBLOCK|O_CLOEXEC);
if (fifofd == -1) { if (*pptr == -1) {
if (errno != ENXIO) if (errno != ENXIO)
/* Unexpected error, the FIFO file might have been removed */ /* Unexpected error, the FIFO file might have been removed */
/* We give up FIFO notification */ /* We give up FIFO notification */
fifopath = NULL; *ppath = NULL;
return; return;
} }
} }
@ -5437,7 +5444,7 @@ static void notify_fifo(bool force)
path[len - 1] = '\n'; 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))) { if (ret != (ssize_t)len && !(ret == -1 && (errno == EAGAIN || errno == EPIPE))) {
DPRINTF_S(strerror(errno)); 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)); curscroll = MAX(curscroll, MAX(cur - (onscreen - 1), 0));
#ifndef NOFIFO #ifndef NOFIFO
notify_fifo(FALSE); notify_fifo(FALSE, FALSE);
#endif #endif
} }
@ -6339,7 +6346,7 @@ nochange:
move_cursor(r, 1); move_cursor(r, 1);
#ifndef NOFIFO #ifndef NOFIFO
else if (event.bstate == BUTTON1_PRESSED) else if (event.bstate == BUTTON1_PRESSED)
notify_fifo(TRUE); notify_fifo(TRUE, FALSE);
#endif #endif
/* Handle right click selection */ /* Handle right click selection */
if (event.bstate == BUTTON3_PRESSED) { if (event.bstate == BUTTON3_PRESSED) {
@ -6409,6 +6416,11 @@ nochange:
if (!S_ISREG(sb.st_mode)) { if (!S_ISREG(sb.st_mode)) {
printwait(messages[MSG_UNSUPPORTED], &presel); printwait(messages[MSG_UNSUPPORTED], &presel);
goto nochange; 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 */ /* 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" " -w place HW cursor on hovered\n"
#ifndef NOX11 #ifndef NOX11
" -x notis, selection sync, xterm title\n" " -x notis, selection sync, xterm title\n"
#endif
#ifndef NOFIFO
" -X fifo explorer mode\n"
#endif #endif
" -h show help\n\n" " -h show help\n\n"
"v%s\n%s\n", __func__, VERSION, GENERAL_INFO); "v%s\n%s\n", __func__, VERSION, GENERAL_INFO);
@ -7761,7 +7776,9 @@ static void cleanup(void)
free(plug); free(plug);
#ifndef NOFIFO #ifndef NOFIFO
if (g_state.autofifo) if (g_state.autofifo)
unlink(fifopath); unlink(hfifopath);
if (g_state.explorer)
unlink(efifopath);
#endif #endif
if (g_state.pluginit) if (g_state.pluginit)
unlink(g_pipepath); unlink(g_pipepath);
@ -7793,7 +7810,7 @@ int main(int argc, char *argv[])
while ((opt = (env_opts_id > 0 while ((opt = (env_opts_id > 0
? env_opts[--env_opts_id] ? 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) { switch (opt) {
#ifndef NOFIFO #ifndef NOFIFO
case 'a': case 'a':
@ -7920,6 +7937,12 @@ int main(int argc, char *argv[])
case 'x': case 'x':
cfg.x11 = 1; cfg.x11 = 1;
break; break;
case 'X':
#ifndef NOFIFO
g_state.explorer = TRUE;
efifopath = optarg;
#endif
break;
case 'h': case 'h':
usage(); usage();
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -8075,9 +8098,18 @@ int main(int argc, char *argv[])
setenv("NNN_FIFO", g_buf, TRUE); setenv("NNN_FIFO", g_buf, TRUE);
} }
fifopath = xgetenv("NNN_FIFO", NULL); hfifopath = xgetenv("NNN_FIFO", NULL);
if (fifopath) { if (hfifopath) {
if (mkfifo(fifopath, 0600) != 0 && !(errno == EEXIST && access(fifopath, W_OK) == 0)) { 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(); xerror();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -8232,9 +8264,11 @@ int main(int argc, char *argv[])
#endif #endif
#ifndef NOFIFO #ifndef NOFIFO
notify_fifo(FALSE); notify_fifo(FALSE, FALSE);
if (fifofd != -1) if (hfifofd != -1)
close(fifofd); close(hfifofd);
if (efifofd != -1)
close(efifofd);
#endif #endif
return opt; return opt;