Add option to show noti and copy selection to system clipboard

This commit is contained in:
Arun Prakash Jana 2019-12-12 19:51:08 +05:30
parent f95ee54870
commit fd8a8387b8
No known key found for this signature in database
GPG key ID: A75979F35C080412
9 changed files with 89 additions and 48 deletions

View file

@ -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
```

View file

@ -31,6 +31,7 @@ _nnn ()
-S
-t
-v
-x
-h
)
if [[ $prev == -b ]]; then

View file

@ -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'

View file

@ -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'
)

View file

@ -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
View file

@ -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
View 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

View file

@ -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];