mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 05:41:31 +00:00
Add option to show noti and copy selection to system clipboard
This commit is contained in:
parent
f95ee54870
commit
fd8a8387b8
|
@ -62,6 +62,7 @@ Add to that an awesome [Wiki](https://github.com/jarun/nnn/wiki)!
|
|||
- Batch renamer (feature-limited) for selection or dir
|
||||
- Copy (as), move (as), delete, archive, link selection
|
||||
- Notification on cp, mv, rm completion
|
||||
- Copy file paths to system clipboard on select
|
||||
- Create (with parents), rename, duplicate (anywhere) files and dirs
|
||||
- Launch GUI apps, run commands, execute file, spawn a shell
|
||||
- Hovered file set as `$nnn` at prompt and spawned shell
|
||||
|
@ -162,7 +163,6 @@ There is no config file. Associated files are stored under `${XDG_CONFIG_HOME:-$
|
|||
| `NNN_SSHFS_OPTS='sshfs -o reconnect,idmap=user'` | specify SSHFS options |
|
||||
| `NNN_RCLONE_OPTS='rclone mount --read-only'` | specify rclone options |
|
||||
| `NNN_IDLE_TIMEOUT=300` | idle seconds to lock terminal [default: disabled] |
|
||||
| `NNN_COPIER=copier` | clipboard copier script [default: none] |
|
||||
| `NNN_TRASH=1` | trash files to the desktop Trash [default: delete] |
|
||||
|
||||
#### Cmdline options
|
||||
|
@ -195,6 +195,7 @@ optional args:
|
|||
-S du mode
|
||||
-t disable dir auto-select
|
||||
-v show version
|
||||
-x notis, sel to system clipboard
|
||||
-h show help
|
||||
```
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ _nnn ()
|
|||
-S
|
||||
-t
|
||||
-v
|
||||
-x
|
||||
-h
|
||||
)
|
||||
if [[ $prev == -b ]]; then
|
||||
|
|
|
@ -30,4 +30,5 @@ complete -c nnn -s s -d 'use substring match for filters'
|
|||
complete -c nnn -s S -d 'start in disk usage analyzer mode'
|
||||
complete -c nnn -s t -d 'disable dir auto-select'
|
||||
complete -c nnn -s v -d 'show program version and exit'
|
||||
complete -c nnn -s x -d 'notis, sel to system clipboard'
|
||||
complete -c nnn -s h -d 'show program help'
|
||||
|
|
|
@ -28,6 +28,7 @@ args=(
|
|||
'(-S)-S[start in disk usage analyzer mode]'
|
||||
'(-t)-t[disable dir auto-select]'
|
||||
'(-v)-v[show program version and exit]'
|
||||
'(-x)-x[notis, sel to system clipboard]'
|
||||
'(-h)-h[show program help]'
|
||||
'*:filename:_files'
|
||||
)
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Copy selection to clipboard
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
SELECTION=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection
|
||||
|
||||
# Linux
|
||||
xargs -0 < "$SELECTION" | xsel -bi
|
||||
|
||||
# macOS
|
||||
# xargs -0 < "$SELECTION" | pbcopy
|
||||
|
||||
# Termux
|
||||
# xargs -0 < "$SELECTION" | termux-clipboard-set
|
||||
|
||||
# Cygwin
|
||||
# xargs -0 < "$SELECTION" | clip
|
||||
|
||||
# Wayland
|
||||
# xargs -0 < "$SELECTION" | wl-copy
|
8
nnn.1
8
nnn.1
|
@ -23,6 +23,7 @@
|
|||
.Op Ar -s
|
||||
.Op Ar -S
|
||||
.Op Ar -v
|
||||
.Op Ar -x
|
||||
.Op Ar -h
|
||||
.Op Ar PATH
|
||||
.Sh DESCRIPTION
|
||||
|
@ -100,6 +101,9 @@ supports the following options:
|
|||
.Fl v
|
||||
show version and exit
|
||||
.Pp
|
||||
.Fl x
|
||||
show notis on selection cp, mv, rm completion; copy path to system clipboard on select
|
||||
.Pp
|
||||
.Fl h
|
||||
show program help and exit
|
||||
.Sh CONFIGURATION
|
||||
|
@ -166,7 +170,7 @@ There are 3 groups of shortcuts to add files to selection:
|
|||
.Pp
|
||||
The selection can now be listed, copied, moved, removed, archived or linked.
|
||||
.Pp
|
||||
Absolute paths of the selected files are copied to the temporary file \fB.selection\fR in the config directory. The path is shown in the help and configuration screen. If \fB$NNN_COPIER\fR is set (see ENVIRONMENT section below) the file paths are also copied to the system clipboard.
|
||||
Absolute paths of the selected files are copied to the temporary file \fB.selection\fR in the config directory. The path is shown in the help and configuration screen.
|
||||
.Pp
|
||||
To flush the selection without running any operation use the _edit, flush selection_ key. The list is flushed even if unchanged. Use this key to remove a file from selection after you navigate away from its directory. Flushing doesn't end the selection mode. You can add more files to the selection and edit/flush the list again. Flushing doesn't end the selection mode. You can add more files to the selection and edit/flush the list again.
|
||||
.Pp
|
||||
|
@ -239,8 +243,6 @@ when dealing with the !, e and p commands respectively. A single combination to
|
|||
.Pp
|
||||
\fBNNN_IDLE_TIMEOUT:\fR set idle timeout (in seconds) to invoke terminal locker (default: disabled).
|
||||
.Pp
|
||||
\fBNNN_COPIER:\fR system clipboard copier script. The project page has some sample copier scripts.
|
||||
.Pp
|
||||
\fBNNN_TRASH:\fR trash (instead of \fIdelete\fR) files to desktop Trash.
|
||||
.Bd -literal
|
||||
export NNN_TRASH=1
|
||||
|
|
45
plugins/.cbcp
Executable file
45
plugins/.cbcp
Executable file
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Description: Copy selection to system clipboard as newline-separated entries
|
||||
# Requires: tr and
|
||||
# xclip/xsel (Linux)
|
||||
# pbcopy (macOS)
|
||||
# termux-clipboard-set (Termux)
|
||||
# clip.exe (WSL)
|
||||
# clip (Cygwin)
|
||||
# wl-copy (Wayland)
|
||||
#
|
||||
# LIMITATION: breaks if a filename has newline in it
|
||||
#
|
||||
# Note: For a space-separated list:
|
||||
# xargs -0 < "$SELECTION"
|
||||
#
|
||||
# Shell: POSIX compliant
|
||||
# Author: Arun Prakash Jana
|
||||
|
||||
IFS="$(printf '%b_' '\n')"; IFS="${IFS%_}" # protect trailing \n
|
||||
|
||||
SELECTION=${XDG_CONFIG_HOME:-$HOME/.config}/nnn/.selection
|
||||
|
||||
if which xsel >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$SELECTION" | xsel -bi
|
||||
elif which xclip >/dev/null 2>&1; then
|
||||
# Linux
|
||||
tr '\0' '\n' < "$SELECTION" | xclip -sel clip
|
||||
elif which pbcopy >/dev/null 2>&1; then
|
||||
# macOS
|
||||
tr '\0' '\n' < "$SELECTION" | pbcopy
|
||||
elif which termux-clipboard-set >/dev/null 2>&1; then
|
||||
# Termux
|
||||
tr '\0' '\n' < "$SELECTION" | termux-clipboard-set
|
||||
elif which clip.exe >/dev/null 2>&1; then
|
||||
# WSL
|
||||
tr '\0' '\n' < "$SELECTION" | clip.exe
|
||||
elif which clip >/dev/null 2>&1; then
|
||||
# Cygwin
|
||||
tr '\0' '\n' < "$SELECTION" | clip
|
||||
elif which wl-copy >/dev/null 2>&1; then
|
||||
# Wayland
|
||||
tr '\0' '\n' < "$SELECTION" | wl-copy
|
||||
fi
|
55
src/nnn.c
55
src/nnn.c
|
@ -227,8 +227,9 @@ typedef struct {
|
|||
uint selmode : 1; /* Set when selecting files */
|
||||
uint showdetail : 1; /* Clear to show fewer file info */
|
||||
uint ctxactive : 1; /* Context active or not */
|
||||
uint reserved : 3;
|
||||
uint reserved : 2;
|
||||
/* The following settings are global */
|
||||
uint x11 : 1; /* Copy to system clipboard and show notis */
|
||||
uint curctx : 2; /* Current context number */
|
||||
uint dircolor : 1; /* Current status of dir color */
|
||||
uint picker : 1; /* Write selection to user-specified file */
|
||||
|
@ -281,6 +282,7 @@ static settings cfg = {
|
|||
0, /* showdetail */
|
||||
1, /* ctxactive */
|
||||
0, /* reserved */
|
||||
0, /* x11 */
|
||||
0, /* curctx */
|
||||
0, /* dircolor */
|
||||
0, /* picker */
|
||||
|
@ -310,7 +312,6 @@ static uint idletimeout, selbufpos, lastappendpos, selbuflen;
|
|||
static char *bmstr;
|
||||
static char *pluginstr;
|
||||
static char *opener;
|
||||
static char *copier;
|
||||
static char *editor;
|
||||
static char *enveditor;
|
||||
static char *pager;
|
||||
|
@ -379,7 +380,8 @@ static bool g_plinit = FALSE;
|
|||
#define UTIL_SH 14
|
||||
#define UTIL_FZF 15
|
||||
#define UTIL_FZY 16
|
||||
#define UTIL_NOTIFY 17
|
||||
#define UTIL_NTFY 17
|
||||
#define UTIL_CBCP 18
|
||||
|
||||
/* Utilities to open files, run actions */
|
||||
static char * const utils[] = {
|
||||
|
@ -412,7 +414,8 @@ static char * const utils[] = {
|
|||
"sh",
|
||||
"fzf",
|
||||
"fzy",
|
||||
".notify",
|
||||
".ntfy",
|
||||
".cbcp",
|
||||
};
|
||||
|
||||
/* Common strings */
|
||||
|
@ -507,18 +510,16 @@ static const char * const messages[] = {
|
|||
#define NNN_OPENER 1
|
||||
#define NNN_CONTEXT_COLORS 2
|
||||
#define NNN_IDLE_TIMEOUT 3
|
||||
#define NNN_COPIER 4
|
||||
#define NNNLVL 5
|
||||
#define NNN_PIPE 6 /* strings end here */
|
||||
#define NNN_USE_EDITOR 7 /* flags begin here */
|
||||
#define NNN_TRASH 8
|
||||
#define NNNLVL 4
|
||||
#define NNN_PIPE 5 /* strings end here */
|
||||
#define NNN_USE_EDITOR 6 /* flags begin here */
|
||||
#define NNN_TRASH 7
|
||||
|
||||
static const char * const env_cfg[] = {
|
||||
"NNN_BMS",
|
||||
"NNN_OPENER",
|
||||
"NNN_CONTEXT_COLORS",
|
||||
"NNN_IDLE_TIMEOUT",
|
||||
"NNN_COPIER",
|
||||
"NNNLVL",
|
||||
"NNN_PIPE",
|
||||
"NNN_USE_EDITOR",
|
||||
|
@ -597,6 +598,7 @@ static inline bool getutil(char *util);
|
|||
static size_t mkpath(const char *dir, const char *name, char *out);
|
||||
static void updateselbuf(const char *path, char *newpath);
|
||||
static char *xgetenv(const char *name, char *fallback);
|
||||
static void run_plugin(const char *plugin, char *newpath, const uchar flags);
|
||||
|
||||
/* Functions */
|
||||
|
||||
|
@ -1040,7 +1042,8 @@ static void endselection(const char *path, char *newpath)
|
|||
|
||||
if (selbufpos) { /* File path(s) written to the buffer */
|
||||
writesel(pselbuf, selbufpos - 1); /* Truncate NULL from end */
|
||||
spawn(copier, NULL, NULL, NULL, F_NOTRACE);
|
||||
if (cfg.x11)
|
||||
run_plugin(utils[UTIL_CBCP], newpath, F_NOWAIT | F_NOTRACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1127,7 +1130,6 @@ static int editselection(void)
|
|||
|
||||
nselected = lines;
|
||||
writesel(pselbuf, selbufpos - 1);
|
||||
spawn(copier, NULL, NULL, NULL, F_NOTRACE);
|
||||
|
||||
return 1;
|
||||
|
||||
|
@ -3631,6 +3633,13 @@ static bool run_selected_plugin(char **path, const char *file, char *newpath, ch
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void run_plugin(const char *plugin, char *newpath, const uchar flags)
|
||||
{
|
||||
mkpath(plugindir, plugin, newpath);
|
||||
if (!access(newpath, X_OK))
|
||||
spawn(newpath, NULL, NULL, NULL, flags);
|
||||
}
|
||||
|
||||
static void launch_app(const char *path, char *newpath)
|
||||
{
|
||||
int r = F_NORMAL;
|
||||
|
@ -4854,7 +4863,8 @@ nochange:
|
|||
selbufpos = lastappendpos;
|
||||
appendfpath(newpath, mkpath(path, dents[cur].name, newpath));
|
||||
writesel(pselbuf, selbufpos - 1); /* Truncate NULL from end */
|
||||
spawn(copier, NULL, NULL, NULL, F_NOTRACE);
|
||||
if (cfg.x11)
|
||||
run_plugin(utils[UTIL_CBCP], newpath, F_NOWAIT | F_NOTRACE);
|
||||
lastappendpos = selbufpos;
|
||||
selbufpos = utmp;
|
||||
}
|
||||
|
@ -4938,7 +4948,8 @@ nochange:
|
|||
|
||||
if (selbufpos != utmp) {
|
||||
writesel(pselbuf, selbufpos - 1); /* Truncate NULL from end */
|
||||
spawn(copier, NULL, NULL, NULL, F_NOTRACE);
|
||||
if (cfg.x11)
|
||||
run_plugin(utils[UTIL_CBCP], newpath, F_NOWAIT | F_NOTRACE);
|
||||
/* Restore current selection buffer position */
|
||||
lastappendpos = selbufpos;
|
||||
selbufpos = utmp;
|
||||
|
@ -4962,7 +4973,8 @@ nochange:
|
|||
= (!r ? messages[MSG_0_SELECTED] : messages[MSG_FAILED]);
|
||||
printwait(msg, &presel);
|
||||
goto nochange;
|
||||
}
|
||||
} else if (cfg.x11)
|
||||
run_plugin(utils[UTIL_CBCP], newpath, F_NOWAIT | F_NOTRACE);
|
||||
break;
|
||||
case SEL_CP: // fallthrough
|
||||
case SEL_MV: // fallthrough
|
||||
|
@ -4975,8 +4987,8 @@ nochange:
|
|||
goto nochange;
|
||||
|
||||
/* Show notification on operation complete */
|
||||
mkpath(plugindir, utils[UTIL_NOTIFY], newpath);
|
||||
spawn(newpath, NULL, NULL, NULL, F_NOWAIT | F_NOTRACE);
|
||||
if (cfg.x11)
|
||||
run_plugin(utils[UTIL_NTFY], newpath, F_NOWAIT | F_NOTRACE);
|
||||
|
||||
if (ndents)
|
||||
copycurname();
|
||||
|
@ -5479,6 +5491,7 @@ static void usage(void)
|
|||
" -S du mode\n"
|
||||
" -t disable dir auto-select\n"
|
||||
" -v show version\n"
|
||||
" -x notis, sel to system clipboard\n"
|
||||
" -h show help\n\n"
|
||||
"v%s\n%s\n", __func__, VERSION, GENERAL_INFO);
|
||||
}
|
||||
|
@ -5621,7 +5634,7 @@ int main(int argc, char *argv[])
|
|||
bool progress = FALSE;
|
||||
#endif
|
||||
|
||||
while ((opt = getopt(argc, argv, "HSKiab:cde:Efnop:rRstvh")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "HSKiab:cde:Efnop:rRstvxh")) != -1) {
|
||||
switch (opt) {
|
||||
case 'S':
|
||||
cfg.blkorder = 1;
|
||||
|
@ -5699,6 +5712,9 @@ int main(int argc, char *argv[])
|
|||
case 'v':
|
||||
fprintf(stdout, "%s\n", VERSION);
|
||||
return _SUCCESS;
|
||||
case 'x':
|
||||
cfg.x11 = 1;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return _SUCCESS;
|
||||
|
@ -5837,9 +5853,6 @@ int main(int argc, char *argv[])
|
|||
if (!set_tmp_path())
|
||||
return _FAILURE;
|
||||
|
||||
/* Get the clipboard copier, if set */
|
||||
copier = getenv(env_cfg[NNN_COPIER]);
|
||||
|
||||
#ifdef __linux__
|
||||
if (!progress) {
|
||||
cp[5] = cp[4];
|
||||
|
|
Loading…
Reference in a new issue