]> Sergey Matveev's repositories - nnn.git/commitdiff
Fix nnn.vim #82: support picker plugins
authorArun Prakash Jana <engineerarun@gmail.com>
Sun, 16 May 2021 19:25:29 +0000 (00:55 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Sun, 16 May 2021 19:41:35 +0000 (01:11 +0530)
Plugins like fzopen have the capability to pick files.
This comes handy if nnn is executing as a file picker.

This is a 2-way communication:

- nnn sends the picker output file to plugin ("-" for stdout)
- the plugin tells nnn if it has overwritten the output file

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

diff --git a/nnn.1 b/nnn.1
index 6d7f2db70f302a47485a3043d288fdbbf9c3001b..178abed16f6c61c1fcb6602bb34209429fb8e0b2 100644 (file)
--- a/nnn.1
+++ b/nnn.1
@@ -419,6 +419,8 @@ separated by \fI;\fR:
     x:_chmod +x $nnn                    | Make the hovered file executable
     y:-_sync*                           | Flush cached writes
     ----------------------------------- + -------------------------------------------------
+
+    Online docs: https://github.com/jarun/nnn/tree/master/plugins
 .Ed
 .Pp
 \fBNNN_COLORS:\fR string of color numbers for each context, e.g.:
@@ -503,10 +505,10 @@ separated by \fI;\fR:
     1. Overridden by a temporary path with -a option.
     2. If the FIFO file doesn't exist it will be created,
        but not removed (unless it is generated by -a option).
+
+    Online docs: https://github.com/jarun/nnn/wiki/Live-previews
 .Ed
 .Pp
-.Em https://github.com/jarun/nnn/wiki/Live-previews
-.Pp
 \fBNNN_LOCKER:\fR terminal locker program.
 .Bd -literal
     export NNN_LOCKER='bmon -p wlp1s0'
index b2f619def5bd2401cfbae8b6090e166ca0d65bf1..49b7887300e630a1c97b5d7deda2d4ced34a4f36 100644 (file)
@@ -27,7 +27,7 @@ Plugins extend the capabilities of `nnn`. They are _executable_ scripts (or bina
 | [finder](finder) | Run custom find command and list | sh | - |
 | [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf |
 | [fzhist](fzhist) | Fuzzy-select a cmd from history, edit in `$EDITOR` and run | sh | fzf, mktemp |
-| [fzopen](fzopen) | Fuzzy find a file in dir subtree and edit or open | sh | fzf, xdg-open |
+| [fzopen](fzopen) | Fuzzy find file(s) in subtree to edit/open/pick | sh | fzf, xdg-open |
 | [fzplug](fzplug) | Fuzzy find, preview and run other plugins | sh | fzf |
 | [fzz](fzz) | Change to any directory in the z database with fzf | sh | fzf, z |
 | [getplugs](getplugs) | Update plugins to installed `nnn` version | sh | curl |
@@ -188,9 +188,10 @@ Notes:
 
 When `nnn` executes a plugin, it does the following:
 - Changes to the directory where the plugin is to be run (`$PWD` pointing to the active directory)
-- Passes two arguments to the script:
+- Passes three arguments to the script:
     1. The hovered file's name.
     2. The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
+    3. The picker mode output file (`-` for stdout) if `nnn` is executed as a file picker.
 - Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
 
 Plugins can also read the `.selection` file in the config directory.
@@ -221,6 +222,7 @@ The `opcode` indicates the operation type.
 |:---:| --- |
 | `c` | change directory |
 | `l` | list files in list mode |
+| `p` | picker file overwritten |
 
 For convenience, we provided a helper script named `.nnn-plugin-helper` and a function named `nnn_cd` to ease this process. `nnn_cd` receives the path to change to as the first argument, and the context as an optional second argument.
 If a context is not provided, it is asked for explicitly. To skip this and choose the current context, set the `CUR_CTX` variable in `.nnn-plugin-helper` (or in the specific plugin after sourcing `.nnn-plugin-helper`) to 1.
index 63f2e2f92c4f1918ba3919c7ed7902283e6fb9be..95ae9be4835f1afb33ad4d0ca70995985658cf24 100755 (executable)
@@ -1,14 +1,24 @@
 #!/usr/bin/env sh
 
-# Description: Fuzzy find a file in directory subtree
-#              Opens in $VISUAL or $EDITOR if text
-#              Opens other type of files with xdg-open
+# Description: Regular mode:
+#                Fuzzy find a file in directory subtree.
+#                Opens in $VISUAL or $EDITOR if text.
+#                Opens other type of files with xdg-open.
+#                Work only with a single file selected.
+#
+#              Picker mode:
+#                If picker mode output file is passed, it
+#                will be overwritten with any picked files.
+#                Leaves untouched if no file is picked.
+#                Works with single/multiple files selected.
 #
 # Dependencies: fd/find, fzf/skim, xdg-open
 #
 # Shell: POSIX compliant
 # Author: Arun Prakash Jana
 
+. "$(dirname "$0")"/.nnn-plugin-helper
+
 if type fzf >/dev/null 2>&1; then
     cmd="$FZF_DEFAULT_COMMAND"
     if type fd >/dev/null 2>&1; then
@@ -16,7 +26,7 @@ if type fzf >/dev/null 2>&1; then
     else
         [ -z "$cmd" ] && cmd="find . -type f 2>/dev/null"
     fi
-    entry="$(eval "$cmd" | fzf --delimiter / --nth=-1 --tiebreak=begin --info=hidden)"
+    entry="$(eval "$cmd" | fzf -m --delimiter / --nth=-1 --tiebreak=begin --info=hidden)"
     # To show only the file name
     # entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden)
 elif type sk >/dev/null 2>&1; then
@@ -25,6 +35,23 @@ else
     exit 1
 fi
 
+# Check for picker mode
+if [ "$3" ]; then
+    if [ "$entry" ]; then
+        if [ "-" = "$3" ]; then
+            printf "%s\n" "$entry"
+        else
+            printf "%s\n" "$entry" > "$3"
+        fi
+
+        # Tell `nnn` to clear its internal selection
+        printf "%s" "0p" > "$NNN_PIPE"
+    fi
+
+    exit 0
+fi
+
+# Open the file (works for a single file only)
 case "$(file -biL "$entry")" in
     *text*)
         "${VISUAL:-$EDITOR}" "$entry" ;;
index 53d09f1e31ee21b2ec3dc6c90760a7e927c9b0b6..bc7b629cc296e7f9b208e5466f245b60e3a76655 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
 #define TMP_LEN_MAX 64
 #define DOT_FILTER_LEN 7
 #define ASCII_MAX 128
-#define EXEC_ARGS_MAX 8
+#define EXEC_ARGS_MAX 10
 #define LIST_FILES_MAX (1 << 16)
 #define SCROLLOFF 3
 
@@ -775,7 +775,7 @@ static haiku_nm_h haiku_hnd;
 
 /* Forward declarations */
 static void redraw(char *path);
-static int spawn(char *file, char *arg1, char *arg2, uchar_t flag);
+static int spawn(char *file, char *arg1, char *arg2, char *arg3, uchar_t flag);
 static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
 static void move_cursor(int target, int ignore_scrolloff);
 static char *load_input(int fd, const char *path);
@@ -1051,7 +1051,7 @@ static char *getgrname(gid_t gid)
 
 static inline bool getutil(char *util)
 {
-       return spawn("which", util, NULL, F_NORMAL | F_NOTRACE) == 0;
+       return spawn("which", util, NULL, NULL, F_NORMAL | F_NOTRACE) == 0;
 }
 
 /*
@@ -1431,7 +1431,7 @@ static bool listselfile(void)
                return FALSE;
 
        snprintf(g_buf, CMD_LEN_MAX, "tr \'\\0\' \'\\n\' < %s", selpath);
-       spawn(utils[UTIL_SH_EXEC], g_buf, NULL, F_CLI | F_CONFIRM);
+       spawn(utils[UTIL_SH_EXEC], g_buf, NULL, NULL, F_CLI | F_CONFIRM);
 
        return TRUE;
 }
@@ -1550,7 +1550,7 @@ static void endselection(void)
        }
 
        snprintf(buf, sizeof(buf), patterns[P_REPLACE], listpath, listroot, g_tmpfpath);
-       spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI);
+       spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI);
 
        fd = open(g_tmpfpath, O_RDONLY);
        if (fd == -1) {
@@ -1628,7 +1628,7 @@ static int editselection(void)
        }
        mtime = sb.st_mtime;
 
-       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, F_CLI);
+       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, NULL, F_CLI);
 
        fd = open(g_tmpfpath, O_RDONLY);
        if (fd == -1) {
@@ -1746,7 +1746,7 @@ static void export_file_list(void)
                DPRINTF_S(strerror(errno));
        }
 
-       spawn(editor, g_tmpfpath, NULL, F_CLI);
+       spawn(editor, g_tmpfpath, NULL, NULL, F_CLI);
 
        if (xconfirm(get_input(messages[MSG_RM_TMP])))
                unlink(g_tmpfpath);
@@ -2001,9 +2001,9 @@ static int join(pid_t p, uchar_t flag)
 
 /*
  * Spawns a child process. Behaviour can be controlled using flag.
- * Limited to 2 arguments to a program, flag works on bit set.
+ * Limited to 3 arguments to a program, flag works on bit set.
  */
-static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
+static int spawn(char *file, char *arg1, char *arg2, char *arg3, uchar_t flag)
 {
        pid_t pid;
        int status = 0, retstatus = 0xFFFF;
@@ -2013,10 +2013,14 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
        if (!file || !*file)
                return retstatus;
 
-       /* Swap args if the first arg is NULL and second isn't */
+       /* Swap args if the first arg is NULL and the other 2 aren't */
        if (!arg1 && arg2) {
                arg1 = arg2;
-               arg2 = NULL;
+               if (arg3) {
+                       arg2 = arg3;
+                       arg3 = NULL;
+               } else
+                       arg2 = NULL;
        }
 
        if (flag & F_MULTI) {
@@ -2030,7 +2034,7 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
 
                xstrsncpy(cmd, file, len);
                status = parseargs(cmd, argv);
-               if (status == -1 || status > (EXEC_ARGS_MAX - 3)) { /* arg1, arg2 and last NULL */
+               if (status == -1 || status > (EXEC_ARGS_MAX - 4)) { /* 3 args and last NULL */
                        free(cmd);
                        DPRINTF_S("NULL or too many args");
                        return retstatus;
@@ -2040,6 +2044,7 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
 
        argv[status] = arg1;
        argv[++status] = arg2;
+       argv[++status] = arg3;
 
        if (flag & F_NORMAL)
                exitcurses();
@@ -2147,11 +2152,11 @@ static bool xrm(char *fpath)
                if (!rm_opts[1])
                        return FALSE;
 
-               spawn("rm", rm_opts, fpath, F_NORMAL | F_CHKRTN);
+               spawn("rm", rm_opts, fpath, NULL, F_NORMAL | F_CHKRTN);
        } else if (g_state.trash == 1)
-               spawn("trash-put", fpath, NULL, F_NORMAL);
+               spawn("trash-put", fpath, NULL, NULL, F_NORMAL);
        else
-               spawn("gio trash", fpath, NULL, F_NORMAL | F_MULTI);
+               spawn("gio trash", fpath, NULL, NULL, F_NORMAL | F_MULTI);
 
        return (access(fpath, F_OK) == -1); /* File is removed */
 }
@@ -2184,7 +2189,7 @@ static bool cpmv_rename(int choice, const char *path)
        /* selsafe() returned TRUE for this to be called */
        if (!selbufpos) {
                snprintf(buf, sizeof(buf), "tr '\\0' '\\n' < %s > %s", selpath, g_tmpfpath);
-               spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI);
+               spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI);
 
                count = lines_in_file(fd, buf, sizeof(buf));
                if (!count)
@@ -2195,9 +2200,9 @@ static bool cpmv_rename(int choice, const char *path)
        close(fd);
 
        snprintf(buf, sizeof(buf), patterns[P_CPMVFMT], g_tmpfpath);
-       spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI);
+       spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI);
 
-       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, F_CLI);
+       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, NULL, F_CLI);
 
        fd = open(g_tmpfpath, O_RDONLY);
        if (fd == -1)
@@ -2212,7 +2217,7 @@ static bool cpmv_rename(int choice, const char *path)
        }
 
        snprintf(buf, sizeof(buf), patterns[P_CPMVRNM], path, g_tmpfpath, cmd);
-       if (!spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI | F_CHKRTN))
+       if (!spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI | F_CHKRTN))
                ret = TRUE;
 finish:
        if (fd >= 0)
@@ -2259,7 +2264,7 @@ static bool cpmvrm_selection(enum action sel, char *path)
                }
        }
 
-       if (sel != SEL_CPMVAS && spawn(utils[UTIL_SH_EXEC], g_buf, NULL, F_CLI | F_CHKRTN)) {
+       if (sel != SEL_CPMVAS && spawn(utils[UTIL_SH_EXEC], g_buf, NULL, NULL, F_CLI | F_CHKRTN)) {
                printmsg(messages[MSG_FAILED]);
                return FALSE;
        }
@@ -2314,7 +2319,7 @@ static bool batch_rename(void)
        if (dir) /* Don't retain dir entries in selection */
                selbufpos = 0;
 
-       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, F_CLI);
+       spawn((cfg.waitedit ? enveditor : editor), g_tmpfpath, NULL, NULL, F_CLI);
 
        /* Reopen file descriptor to get updated contents */
        fd2 = open(g_tmpfpath, O_RDONLY);
@@ -2330,7 +2335,7 @@ static bool batch_rename(void)
        }
 
        snprintf(buf, sizeof(buf), batchrenamecmd, foriginal, g_tmpfpath);
-       spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI);
+       spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI);
        ret = TRUE;
 
 finish:
@@ -2380,7 +2385,7 @@ static void archive_selection(const char *cmd, const char *archive, const char *
                selpath, curpath, cmd, archive
 #endif
                );
-       spawn(utils[UTIL_SH_EXEC], buf, NULL, F_CLI | F_CONFIRM);
+       spawn(utils[UTIL_SH_EXEC], buf, NULL, NULL, F_CLI | F_CONFIRM);
        free(buf);
 }
 
@@ -4057,7 +4062,7 @@ static char *get_output(char *buf, const size_t bytes, const char *file,
                /* Show in pager in child */
                dup2(pipefd[0], STDIN_FILENO);
                close(pipefd[0]);
-               spawn(pager, NULL, NULL, F_CLI);
+               spawn(pager, NULL, NULL, NULL, F_CLI);
                _exit(EXIT_SUCCESS);
        }
 
@@ -4135,7 +4140,7 @@ static bool show_stats(const char *fpath, const struct stat *sb)
        fclose(fp);
        close(fd);
 
-       spawn(pager, g_tmpfpath, NULL, F_CLI);
+       spawn(pager, g_tmpfpath, NULL, NULL, F_CLI);
        unlink(g_tmpfpath);
        return TRUE;
 }
@@ -4186,7 +4191,7 @@ static void handle_archive(char *fpath, char op)
        }
 
        if (op == 'x') /* extract */
-               spawn(util, arg, fpath, F_NORMAL);
+               spawn(util, arg, fpath, NULL, F_NORMAL);
        else /* list */
                get_output(NULL, 0, util, arg, fpath, TRUE);
 }
@@ -4338,7 +4343,7 @@ static bool archive_mount(char *newpath)
        /* Mount archive */
        DPRINTF_S(name);
        DPRINTF_S(newpath);
-       if (spawn(cmd, name, newpath, F_NORMAL)) {
+       if (spawn(cmd, name, newpath, NULL, F_NORMAL)) {
                printmsg(messages[MSG_FAILED]);
                return FALSE;
        }
@@ -4403,12 +4408,12 @@ static bool remote_mount(char *newpath)
 
        /* Connect to remote */
        if (opt == 's') {
-               if (spawn(env, tmp, newpath, flag)) {
+               if (spawn(env, tmp, newpath, NULL, flag)) {
                        printmsg(messages[MSG_FAILED]);
                        return FALSE;
                }
        } else {
-               spawn(env, tmp, newpath, flag);
+               spawn(env, tmp, newpath, NULL, flag);
                printmsg(messages[MSG_RCLONE_DELAY]);
                xdelay(XDELAY_INTERVAL_MS << 2); /* Set 4 times the usual delay */
        }
@@ -4471,19 +4476,19 @@ static bool unmount(char *name, char *newpath, int *presel, char *currentpath)
        }
 
 #if defined (__APPLE__) || defined (__FreeBSD__)
-       if (spawn(cmd, newpath, NULL, F_NORMAL)) {
+       if (spawn(cmd, newpath, NULL, NULL, F_NORMAL)) {
 #else
-       if (spawn(cmd, "-u", newpath, F_NORMAL)) {
+       if (spawn(cmd, "-u", newpath, NULL, F_NORMAL)) {
 #endif
                if (!xconfirm(get_input(messages[MSG_LAZY])))
                        return FALSE;
 
 #ifdef __APPLE__
-               if (spawn(cmd, "-l", newpath, F_NORMAL)) {
+               if (spawn(cmd, "-l", newpath, NULL, F_NORMAL)) {
 #elif defined (__FreeBSD__)
-               if (spawn(cmd, "-f", newpath, F_NORMAL)) {
+               if (spawn(cmd, "-f", newpath, NULL, F_NORMAL)) {
 #else
-               if (spawn(cmd, "-uz", newpath, F_NORMAL)) {
+               if (spawn(cmd, "-uz", newpath, NULL, F_NORMAL)) {
 #endif
                        printwait(messages[MSG_FAILED], presel);
                        return FALSE;
@@ -4500,7 +4505,7 @@ static bool unmount(char *name, char *newpath, int *presel, char *currentpath)
 
 static void lock_terminal(void)
 {
-       spawn(xgetenv("NNN_LOCKER", utils[UTIL_LOCKER]), NULL, NULL, F_CLI);
+       spawn(xgetenv("NNN_LOCKER", utils[UTIL_LOCKER]), NULL, NULL, NULL, F_CLI);
 }
 
 static void printkv(kv *kvarr, FILE *fp, uchar_t max, uchar_t id)
@@ -4658,7 +4663,7 @@ static void show_help(const char *path)
        fclose(fp);
        close(fd);
 
-       spawn(pager, g_tmpfpath, NULL, F_CLI);
+       spawn(pager, g_tmpfpath, NULL, NULL, F_CLI);
        unlink(g_tmpfpath);
 }
 
@@ -4680,7 +4685,7 @@ static bool run_cmd_as_plugin(const char *file, char *runfile, uchar_t flags)
        else
                runfile = NULL;
 
-       spawn(g_buf, runfile, NULL, flags);
+       spawn(g_buf, runfile, NULL, NULL, flags);
        return TRUE;
 }
 
@@ -4704,7 +4709,7 @@ static void rmlistpath(void)
        if (listpath) {
                DPRINTF_S(__func__);
                DPRINTF_S(listpath);
-               spawn("rm -rf", listpath, NULL, F_NOTRACE | F_MULTI);
+               spawn("rm -rf", listpath, NULL, NULL, F_NOTRACE | F_MULTI);
                /* Do not free if program was started in list mode */
                if (listpath != initpath)
                        free(listpath);
@@ -4756,14 +4761,16 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir)
                if (len <= 0)
                        return;
 
-               /* Terminate the path read */
-               g_buf[len] = '\0';
+               g_buf[len] = '\0'; /* Terminate the path read */
                nextpath = g_buf;
        } else if (op == 'l') {
-               /* Remove last list mode path, if any */
-               rmlistpath();
-
+               rmlistpath(); /* Remove last list mode path, if any */
                nextpath = load_input(fd, *path);
+       } else if (op == 'p') {
+               free(selpath);
+               selpath = NULL;
+               clearselection();
+               g_state.picker = 0;
        }
 
        if (nextpath) {
@@ -4829,14 +4836,20 @@ static bool run_selected_plugin(char **path, const char *file, char *runfile, ch
                        _exit(EXIT_FAILURE);
 
                if (!cmd_as_plugin) {
+                       char *sel = NULL;
+                       char std[2] = "-";
+
                        /* Generate absolute path to plugin */
                        mkpath(plgpath, file, g_buf);
 
+                       if (g_state.picker)
+                               sel = selpath ? selpath : std;
+
                        if (runfile && runfile[0]) {
                                xstrsncpy(*lastname, runfile, NAME_MAX);
-                               spawn(g_buf, *lastname, *path, 0);
+                               spawn(g_buf, *lastname, *path, sel, 0);
                        } else
-                               spawn(g_buf, NULL, *path, 0);
+                               spawn(g_buf, NULL, *path, sel, 0);
                } else
                        run_cmd_as_plugin(file, runfile, flags);
 
@@ -4867,7 +4880,7 @@ static bool plugscript(const char *plugin, uchar_t flags)
 {
        mkpath(plgpath, plugin, g_buf);
        if (!access(g_buf, X_OK)) {
-               spawn(g_buf, NULL, NULL, flags);
+               spawn(g_buf, NULL, NULL, NULL, flags);
                return TRUE;
        }
 
@@ -4887,7 +4900,7 @@ static bool launch_app(char *newpath)
        }
 
        if (tmp && *tmp) // NOLINT
-               spawn(tmp, (r == F_NORMAL) ? "0" : NULL, NULL, r);
+               spawn(tmp, (r == F_NORMAL) ? "0" : NULL, NULL, NULL, r);
 
        return FALSE;
 }
@@ -4911,7 +4924,7 @@ static bool prompt_run(const char *current)
 #endif
                if (tmp && *tmp) { // NOLINT
                        ret = TRUE;
-                       spawn(shell, "-c", tmp, F_CLI | F_CONFIRM);
+                       spawn(shell, "-c", tmp, NULL, F_CLI | F_CONFIRM);
                } else
                        break;
        }
@@ -4935,7 +4948,7 @@ static bool handle_cmd(enum action sel, const char *current, char *newpath)
 
        setenv(env_cfg[NNNLVL], xitoa(r + 1), 1);
        setenv(envs[ENV_NCUR], current, 1);
-       spawn(shell, NULL, NULL, F_CLI);
+       spawn(shell, NULL, NULL, NULL, F_CLI);
        setenv(env_cfg[NNNLVL], xitoa(r), 1);
        return TRUE;
 }
@@ -5423,7 +5436,7 @@ static void handle_openwith(const char *path, const char *name, char *newpath, c
             (r == 'g' ? F_NOWAIT | F_NOTRACE | F_MULTI : 0));
        if (r) {
                mkpath(path, name, newpath);
-               spawn(tmp, newpath, NULL, r);
+               spawn(tmp, newpath, NULL, NULL, r);
        }
 }
 
@@ -6346,7 +6359,7 @@ nochange:
                            && strstr(g_buf, "text")
 #endif
                        ) {
-                               spawn(editor, newpath, NULL, F_CLI);
+                               spawn(editor, newpath, NULL, NULL, F_CLI);
                                if (cfg.filtermode) {
                                        presel = FILTER;
                                        clearfilter();
@@ -6397,7 +6410,7 @@ nochange:
                        }
 
                        /* Invoke desktop opener as last resort */
-                       spawn(opener, newpath, NULL, opener_flags);
+                       spawn(opener, newpath, NULL, NULL, opener_flags);
 
                        /* Move cursor to the next entry if not the last entry */
                        if (g_state.autonext && cur != ndents - 1)
@@ -6648,7 +6661,7 @@ nochange:
                                        copycurname();
                                goto nochange;
                        case SEL_EDIT:
-                               spawn(editor, newpath, NULL, F_CLI);
+                               spawn(editor, newpath, NULL, NULL, F_CLI);
                                continue;
                        default: /* SEL_LOCK */
                                lock_terminal();
@@ -6903,7 +6916,7 @@ nochange:
                                }
                                get_archive_cmd(newpath, tmp);
                                (r == 's') ? archive_selection(newpath, tmp, path)
-                                          : spawn(newpath, tmp, pdents[cur].name, F_CLI | F_CONFIRM);
+                                          : spawn(newpath, tmp, pdents[cur].name, NULL, F_CLI | F_CONFIRM);
 
                                mkpath(path, tmp, newpath);
                                if (access(newpath, F_OK) == 0) { /* File created */
@@ -6965,7 +6978,7 @@ nochange:
                        if (sel == SEL_RENAME) {
                                /* Rename the file */
                                if (ret == 'd')
-                                       spawn("cp -rp", pdents[cur].name, tmp, F_SILENT);
+                                       spawn("cp -rp", pdents[cur].name, tmp, NULL, F_SILENT);
                                else if (renameat(fd, pdents[cur].name, fd, tmp) != 0) {
                                        close(fd);
                                        printwarn(&presel);
@@ -8046,7 +8059,7 @@ int main(int argc, char *argv[])
        }
 #endif
 
-       if (g_state.pickraw || g_state.picker) {
+       if (g_state.picker) {
                if (selbufpos) {
                        fd = g_state.pickraw ? STDOUT_FILENO : open(selpath, O_WRONLY | O_CREAT, 0600);
                        if ((fd == -1) || (seltofile(fd, NULL) != (size_t)(selbufpos)))