mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 03:41:27 +00:00
Fix nnn.vim #82: support picker plugins
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
This commit is contained in:
parent
715abc7a3f
commit
cbc4587630
6
nnn.1
6
nnn.1
|
@ -419,6 +419,8 @@ separated by \fI;\fR:
|
||||||
x:_chmod +x $nnn | Make the hovered file executable
|
x:_chmod +x $nnn | Make the hovered file executable
|
||||||
y:-_sync* | Flush cached writes
|
y:-_sync* | Flush cached writes
|
||||||
----------------------------------- + -------------------------------------------------
|
----------------------------------- + -------------------------------------------------
|
||||||
|
|
||||||
|
Online docs: https://github.com/jarun/nnn/tree/master/plugins
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
\fBNNN_COLORS:\fR string of color numbers for each context, e.g.:
|
\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.
|
1. Overridden by a temporary path with -a option.
|
||||||
2. If the FIFO file doesn't exist it will be created,
|
2. If the FIFO file doesn't exist it will be created,
|
||||||
but not removed (unless it is generated by -a option).
|
but not removed (unless it is generated by -a option).
|
||||||
|
|
||||||
|
Online docs: https://github.com/jarun/nnn/wiki/Live-previews
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.Em https://github.com/jarun/nnn/wiki/Live-previews
|
|
||||||
.Pp
|
|
||||||
\fBNNN_LOCKER:\fR terminal locker program.
|
\fBNNN_LOCKER:\fR terminal locker program.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
export NNN_LOCKER='bmon -p wlp1s0'
|
export NNN_LOCKER='bmon -p wlp1s0'
|
||||||
|
|
|
@ -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 | - |
|
| [finder](finder) | Run custom find command and list | sh | - |
|
||||||
| [fzcd](fzcd) | Change to the directory of a fuzzy-selected file/dir | sh | fzf |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [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 |
|
| [getplugs](getplugs) | Update plugins to installed `nnn` version | sh | curl |
|
||||||
|
@ -188,9 +188,10 @@ Notes:
|
||||||
|
|
||||||
When `nnn` executes a plugin, it does the following:
|
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)
|
- 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.
|
1. The hovered file's name.
|
||||||
2. The working directory (might differ from `$PWD` in case of symlinked paths; non-canonical).
|
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.
|
- Sets the environment variable `NNN_PIPE` used to control `nnn` active directory.
|
||||||
|
|
||||||
Plugins can also read the `.selection` file in the config 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 |
|
| `c` | change directory |
|
||||||
| `l` | list files in list mode |
|
| `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.
|
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.
|
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.
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
# Description: Fuzzy find a file in directory subtree
|
# Description: Regular mode:
|
||||||
# Opens in $VISUAL or $EDITOR if text
|
# Fuzzy find a file in directory subtree.
|
||||||
# Opens other type of files with xdg-open
|
# 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
|
# Dependencies: fd/find, fzf/skim, xdg-open
|
||||||
#
|
#
|
||||||
# Shell: POSIX compliant
|
# Shell: POSIX compliant
|
||||||
# Author: Arun Prakash Jana
|
# Author: Arun Prakash Jana
|
||||||
|
|
||||||
|
. "$(dirname "$0")"/.nnn-plugin-helper
|
||||||
|
|
||||||
if type fzf >/dev/null 2>&1; then
|
if type fzf >/dev/null 2>&1; then
|
||||||
cmd="$FZF_DEFAULT_COMMAND"
|
cmd="$FZF_DEFAULT_COMMAND"
|
||||||
if type fd >/dev/null 2>&1; then
|
if type fd >/dev/null 2>&1; then
|
||||||
|
@ -16,7 +26,7 @@ if type fzf >/dev/null 2>&1; then
|
||||||
else
|
else
|
||||||
[ -z "$cmd" ] && cmd="find . -type f 2>/dev/null"
|
[ -z "$cmd" ] && cmd="find . -type f 2>/dev/null"
|
||||||
fi
|
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
|
# To show only the file name
|
||||||
# entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden)
|
# entry=$(find . -type f 2>/dev/null | fzf --delimiter / --with-nth=-1 --tiebreak=begin --info=hidden)
|
||||||
elif type sk >/dev/null 2>&1; then
|
elif type sk >/dev/null 2>&1; then
|
||||||
|
@ -25,6 +35,23 @@ else
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
case "$(file -biL "$entry")" in
|
||||||
*text*)
|
*text*)
|
||||||
"${VISUAL:-$EDITOR}" "$entry" ;;
|
"${VISUAL:-$EDITOR}" "$entry" ;;
|
||||||
|
|
123
src/nnn.c
123
src/nnn.c
|
@ -176,7 +176,7 @@
|
||||||
#define TMP_LEN_MAX 64
|
#define TMP_LEN_MAX 64
|
||||||
#define DOT_FILTER_LEN 7
|
#define DOT_FILTER_LEN 7
|
||||||
#define ASCII_MAX 128
|
#define ASCII_MAX 128
|
||||||
#define EXEC_ARGS_MAX 8
|
#define EXEC_ARGS_MAX 10
|
||||||
#define LIST_FILES_MAX (1 << 16)
|
#define LIST_FILES_MAX (1 << 16)
|
||||||
#define SCROLLOFF 3
|
#define SCROLLOFF 3
|
||||||
|
|
||||||
|
@ -775,7 +775,7 @@ static haiku_nm_h haiku_hnd;
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
static void redraw(char *path);
|
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 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 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);
|
||||||
|
@ -1051,7 +1051,7 @@ static char *getgrname(gid_t gid)
|
||||||
|
|
||||||
static inline bool getutil(char *util)
|
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;
|
return FALSE;
|
||||||
|
|
||||||
snprintf(g_buf, CMD_LEN_MAX, "tr \'\\0\' \'\\n\' < %s", selpath);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1550,7 @@ static void endselection(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), patterns[P_REPLACE], listpath, listroot, g_tmpfpath);
|
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);
|
fd = open(g_tmpfpath, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
@ -1628,7 +1628,7 @@ static int editselection(void)
|
||||||
}
|
}
|
||||||
mtime = sb.st_mtime;
|
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);
|
fd = open(g_tmpfpath, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
|
@ -1746,7 +1746,7 @@ static void export_file_list(void)
|
||||||
DPRINTF_S(strerror(errno));
|
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])))
|
if (xconfirm(get_input(messages[MSG_RM_TMP])))
|
||||||
unlink(g_tmpfpath);
|
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.
|
* 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;
|
pid_t pid;
|
||||||
int status = 0, retstatus = 0xFFFF;
|
int status = 0, retstatus = 0xFFFF;
|
||||||
|
@ -2013,9 +2013,13 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
|
||||||
if (!file || !*file)
|
if (!file || !*file)
|
||||||
return retstatus;
|
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) {
|
if (!arg1 && arg2) {
|
||||||
arg1 = arg2;
|
arg1 = arg2;
|
||||||
|
if (arg3) {
|
||||||
|
arg2 = arg3;
|
||||||
|
arg3 = NULL;
|
||||||
|
} else
|
||||||
arg2 = NULL;
|
arg2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2030,7 +2034,7 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
|
||||||
|
|
||||||
xstrsncpy(cmd, file, len);
|
xstrsncpy(cmd, file, len);
|
||||||
status = parseargs(cmd, argv);
|
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);
|
free(cmd);
|
||||||
DPRINTF_S("NULL or too many args");
|
DPRINTF_S("NULL or too many args");
|
||||||
return retstatus;
|
return retstatus;
|
||||||
|
@ -2040,6 +2044,7 @@ static int spawn(char *file, char *arg1, char *arg2, uchar_t flag)
|
||||||
|
|
||||||
argv[status] = arg1;
|
argv[status] = arg1;
|
||||||
argv[++status] = arg2;
|
argv[++status] = arg2;
|
||||||
|
argv[++status] = arg3;
|
||||||
|
|
||||||
if (flag & F_NORMAL)
|
if (flag & F_NORMAL)
|
||||||
exitcurses();
|
exitcurses();
|
||||||
|
@ -2147,11 +2152,11 @@ static bool xrm(char *fpath)
|
||||||
if (!rm_opts[1])
|
if (!rm_opts[1])
|
||||||
return FALSE;
|
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)
|
} else if (g_state.trash == 1)
|
||||||
spawn("trash-put", fpath, NULL, F_NORMAL);
|
spawn("trash-put", fpath, NULL, NULL, F_NORMAL);
|
||||||
else
|
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 */
|
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 */
|
/* selsafe() returned TRUE for this to be called */
|
||||||
if (!selbufpos) {
|
if (!selbufpos) {
|
||||||
snprintf(buf, sizeof(buf), "tr '\\0' '\\n' < %s > %s", selpath, g_tmpfpath);
|
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));
|
count = lines_in_file(fd, buf, sizeof(buf));
|
||||||
if (!count)
|
if (!count)
|
||||||
|
@ -2195,9 +2200,9 @@ static bool cpmv_rename(int choice, const char *path)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), patterns[P_CPMVFMT], g_tmpfpath);
|
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);
|
fd = open(g_tmpfpath, O_RDONLY);
|
||||||
if (fd == -1)
|
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);
|
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;
|
ret = TRUE;
|
||||||
finish:
|
finish:
|
||||||
if (fd >= 0)
|
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]);
|
printmsg(messages[MSG_FAILED]);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -2314,7 +2319,7 @@ static bool batch_rename(void)
|
||||||
if (dir) /* Don't retain dir entries in selection */
|
if (dir) /* Don't retain dir entries in selection */
|
||||||
selbufpos = 0;
|
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 */
|
/* Reopen file descriptor to get updated contents */
|
||||||
fd2 = open(g_tmpfpath, O_RDONLY);
|
fd2 = open(g_tmpfpath, O_RDONLY);
|
||||||
|
@ -2330,7 +2335,7 @@ static bool batch_rename(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), batchrenamecmd, foriginal, g_tmpfpath);
|
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;
|
ret = TRUE;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
|
@ -2380,7 +2385,7 @@ static void archive_selection(const char *cmd, const char *archive, const char *
|
||||||
selpath, curpath, cmd, archive
|
selpath, curpath, cmd, archive
|
||||||
#endif
|
#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);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4057,7 +4062,7 @@ static char *get_output(char *buf, const size_t bytes, const char *file,
|
||||||
/* Show in pager in child */
|
/* Show in pager in child */
|
||||||
dup2(pipefd[0], STDIN_FILENO);
|
dup2(pipefd[0], STDIN_FILENO);
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
spawn(pager, NULL, NULL, F_CLI);
|
spawn(pager, NULL, NULL, NULL, F_CLI);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4135,7 +4140,7 @@ static bool show_stats(const char *fpath, const struct stat *sb)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
spawn(pager, g_tmpfpath, NULL, F_CLI);
|
spawn(pager, g_tmpfpath, NULL, NULL, F_CLI);
|
||||||
unlink(g_tmpfpath);
|
unlink(g_tmpfpath);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -4186,7 +4191,7 @@ static void handle_archive(char *fpath, char op)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == 'x') /* extract */
|
if (op == 'x') /* extract */
|
||||||
spawn(util, arg, fpath, F_NORMAL);
|
spawn(util, arg, fpath, NULL, F_NORMAL);
|
||||||
else /* list */
|
else /* list */
|
||||||
get_output(NULL, 0, util, arg, fpath, TRUE);
|
get_output(NULL, 0, util, arg, fpath, TRUE);
|
||||||
}
|
}
|
||||||
|
@ -4338,7 +4343,7 @@ static bool archive_mount(char *newpath)
|
||||||
/* Mount archive */
|
/* Mount archive */
|
||||||
DPRINTF_S(name);
|
DPRINTF_S(name);
|
||||||
DPRINTF_S(newpath);
|
DPRINTF_S(newpath);
|
||||||
if (spawn(cmd, name, newpath, F_NORMAL)) {
|
if (spawn(cmd, name, newpath, NULL, F_NORMAL)) {
|
||||||
printmsg(messages[MSG_FAILED]);
|
printmsg(messages[MSG_FAILED]);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4403,12 +4408,12 @@ static bool remote_mount(char *newpath)
|
||||||
|
|
||||||
/* Connect to remote */
|
/* Connect to remote */
|
||||||
if (opt == 's') {
|
if (opt == 's') {
|
||||||
if (spawn(env, tmp, newpath, flag)) {
|
if (spawn(env, tmp, newpath, NULL, flag)) {
|
||||||
printmsg(messages[MSG_FAILED]);
|
printmsg(messages[MSG_FAILED]);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spawn(env, tmp, newpath, flag);
|
spawn(env, tmp, newpath, NULL, flag);
|
||||||
printmsg(messages[MSG_RCLONE_DELAY]);
|
printmsg(messages[MSG_RCLONE_DELAY]);
|
||||||
xdelay(XDELAY_INTERVAL_MS << 2); /* Set 4 times the usual 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 defined (__APPLE__) || defined (__FreeBSD__)
|
||||||
if (spawn(cmd, newpath, NULL, F_NORMAL)) {
|
if (spawn(cmd, newpath, NULL, NULL, F_NORMAL)) {
|
||||||
#else
|
#else
|
||||||
if (spawn(cmd, "-u", newpath, F_NORMAL)) {
|
if (spawn(cmd, "-u", newpath, NULL, F_NORMAL)) {
|
||||||
#endif
|
#endif
|
||||||
if (!xconfirm(get_input(messages[MSG_LAZY])))
|
if (!xconfirm(get_input(messages[MSG_LAZY])))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (spawn(cmd, "-l", newpath, F_NORMAL)) {
|
if (spawn(cmd, "-l", newpath, NULL, F_NORMAL)) {
|
||||||
#elif defined (__FreeBSD__)
|
#elif defined (__FreeBSD__)
|
||||||
if (spawn(cmd, "-f", newpath, F_NORMAL)) {
|
if (spawn(cmd, "-f", newpath, NULL, F_NORMAL)) {
|
||||||
#else
|
#else
|
||||||
if (spawn(cmd, "-uz", newpath, F_NORMAL)) {
|
if (spawn(cmd, "-uz", newpath, NULL, F_NORMAL)) {
|
||||||
#endif
|
#endif
|
||||||
printwait(messages[MSG_FAILED], presel);
|
printwait(messages[MSG_FAILED], presel);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -4500,7 +4505,7 @@ static bool unmount(char *name, char *newpath, int *presel, char *currentpath)
|
||||||
|
|
||||||
static void lock_terminal(void)
|
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)
|
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);
|
fclose(fp);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
spawn(pager, g_tmpfpath, NULL, F_CLI);
|
spawn(pager, g_tmpfpath, NULL, NULL, F_CLI);
|
||||||
unlink(g_tmpfpath);
|
unlink(g_tmpfpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4680,7 +4685,7 @@ static bool run_cmd_as_plugin(const char *file, char *runfile, uchar_t flags)
|
||||||
else
|
else
|
||||||
runfile = NULL;
|
runfile = NULL;
|
||||||
|
|
||||||
spawn(g_buf, runfile, NULL, flags);
|
spawn(g_buf, runfile, NULL, NULL, flags);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4704,7 +4709,7 @@ static void rmlistpath(void)
|
||||||
if (listpath) {
|
if (listpath) {
|
||||||
DPRINTF_S(__func__);
|
DPRINTF_S(__func__);
|
||||||
DPRINTF_S(listpath);
|
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 */
|
/* Do not free if program was started in list mode */
|
||||||
if (listpath != initpath)
|
if (listpath != initpath)
|
||||||
free(listpath);
|
free(listpath);
|
||||||
|
@ -4756,14 +4761,16 @@ static void readpipe(int fd, char **path, char **lastname, char **lastdir)
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Terminate the path read */
|
g_buf[len] = '\0'; /* Terminate the path read */
|
||||||
g_buf[len] = '\0';
|
|
||||||
nextpath = g_buf;
|
nextpath = g_buf;
|
||||||
} else if (op == 'l') {
|
} else if (op == 'l') {
|
||||||
/* Remove last list mode path, if any */
|
rmlistpath(); /* Remove last list mode path, if any */
|
||||||
rmlistpath();
|
|
||||||
|
|
||||||
nextpath = load_input(fd, *path);
|
nextpath = load_input(fd, *path);
|
||||||
|
} else if (op == 'p') {
|
||||||
|
free(selpath);
|
||||||
|
selpath = NULL;
|
||||||
|
clearselection();
|
||||||
|
g_state.picker = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextpath) {
|
if (nextpath) {
|
||||||
|
@ -4829,14 +4836,20 @@ static bool run_selected_plugin(char **path, const char *file, char *runfile, ch
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (!cmd_as_plugin) {
|
if (!cmd_as_plugin) {
|
||||||
|
char *sel = NULL;
|
||||||
|
char std[2] = "-";
|
||||||
|
|
||||||
/* Generate absolute path to plugin */
|
/* Generate absolute path to plugin */
|
||||||
mkpath(plgpath, file, g_buf);
|
mkpath(plgpath, file, g_buf);
|
||||||
|
|
||||||
|
if (g_state.picker)
|
||||||
|
sel = selpath ? selpath : std;
|
||||||
|
|
||||||
if (runfile && runfile[0]) {
|
if (runfile && runfile[0]) {
|
||||||
xstrsncpy(*lastname, runfile, NAME_MAX);
|
xstrsncpy(*lastname, runfile, NAME_MAX);
|
||||||
spawn(g_buf, *lastname, *path, 0);
|
spawn(g_buf, *lastname, *path, sel, 0);
|
||||||
} else
|
} else
|
||||||
spawn(g_buf, NULL, *path, 0);
|
spawn(g_buf, NULL, *path, sel, 0);
|
||||||
} else
|
} else
|
||||||
run_cmd_as_plugin(file, runfile, flags);
|
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);
|
mkpath(plgpath, plugin, g_buf);
|
||||||
if (!access(g_buf, X_OK)) {
|
if (!access(g_buf, X_OK)) {
|
||||||
spawn(g_buf, NULL, NULL, flags);
|
spawn(g_buf, NULL, NULL, NULL, flags);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4887,7 +4900,7 @@ static bool launch_app(char *newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp && *tmp) // NOLINT
|
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;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4911,7 +4924,7 @@ static bool prompt_run(const char *current)
|
||||||
#endif
|
#endif
|
||||||
if (tmp && *tmp) { // NOLINT
|
if (tmp && *tmp) { // NOLINT
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
spawn(shell, "-c", tmp, F_CLI | F_CONFIRM);
|
spawn(shell, "-c", tmp, NULL, F_CLI | F_CONFIRM);
|
||||||
} else
|
} else
|
||||||
break;
|
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(env_cfg[NNNLVL], xitoa(r + 1), 1);
|
||||||
setenv(envs[ENV_NCUR], current, 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);
|
setenv(env_cfg[NNNLVL], xitoa(r), 1);
|
||||||
return TRUE;
|
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));
|
(r == 'g' ? F_NOWAIT | F_NOTRACE | F_MULTI : 0));
|
||||||
if (r) {
|
if (r) {
|
||||||
mkpath(path, name, newpath);
|
mkpath(path, name, newpath);
|
||||||
spawn(tmp, newpath, NULL, r);
|
spawn(tmp, newpath, NULL, NULL, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6346,7 +6359,7 @@ nochange:
|
||||||
&& strstr(g_buf, "text")
|
&& strstr(g_buf, "text")
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
spawn(editor, newpath, NULL, F_CLI);
|
spawn(editor, newpath, NULL, NULL, F_CLI);
|
||||||
if (cfg.filtermode) {
|
if (cfg.filtermode) {
|
||||||
presel = FILTER;
|
presel = FILTER;
|
||||||
clearfilter();
|
clearfilter();
|
||||||
|
@ -6397,7 +6410,7 @@ nochange:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Invoke desktop opener as last resort */
|
/* 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 */
|
/* Move cursor to the next entry if not the last entry */
|
||||||
if (g_state.autonext && cur != ndents - 1)
|
if (g_state.autonext && cur != ndents - 1)
|
||||||
|
@ -6648,7 +6661,7 @@ nochange:
|
||||||
copycurname();
|
copycurname();
|
||||||
goto nochange;
|
goto nochange;
|
||||||
case SEL_EDIT:
|
case SEL_EDIT:
|
||||||
spawn(editor, newpath, NULL, F_CLI);
|
spawn(editor, newpath, NULL, NULL, F_CLI);
|
||||||
continue;
|
continue;
|
||||||
default: /* SEL_LOCK */
|
default: /* SEL_LOCK */
|
||||||
lock_terminal();
|
lock_terminal();
|
||||||
|
@ -6903,7 +6916,7 @@ nochange:
|
||||||
}
|
}
|
||||||
get_archive_cmd(newpath, tmp);
|
get_archive_cmd(newpath, tmp);
|
||||||
(r == 's') ? archive_selection(newpath, tmp, path)
|
(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);
|
mkpath(path, tmp, newpath);
|
||||||
if (access(newpath, F_OK) == 0) { /* File created */
|
if (access(newpath, F_OK) == 0) { /* File created */
|
||||||
|
@ -6965,7 +6978,7 @@ nochange:
|
||||||
if (sel == SEL_RENAME) {
|
if (sel == SEL_RENAME) {
|
||||||
/* Rename the file */
|
/* Rename the file */
|
||||||
if (ret == 'd')
|
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) {
|
else if (renameat(fd, pdents[cur].name, fd, tmp) != 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
printwarn(&presel);
|
printwarn(&presel);
|
||||||
|
@ -8046,7 +8059,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (g_state.pickraw || g_state.picker) {
|
if (g_state.picker) {
|
||||||
if (selbufpos) {
|
if (selbufpos) {
|
||||||
fd = g_state.pickraw ? STDOUT_FILENO : open(selpath, O_WRONLY | O_CREAT, 0600);
|
fd = g_state.pickraw ? STDOUT_FILENO : open(selpath, O_WRONLY | O_CREAT, 0600);
|
||||||
if ((fd == -1) || (seltofile(fd, NULL) != (size_t)(selbufpos)))
|
if ((fd == -1) || (seltofile(fd, NULL) != (size_t)(selbufpos)))
|
||||||
|
|
Loading…
Reference in a new issue