- 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
| `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
-S du mode
-t disable dir auto-select
-v show version
+ -x notis, sel to system clipboard
-h show help
```
--- /dev/null
+#!/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
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 */
0, /* showdetail */
1, /* ctxactive */
0, /* reserved */
+ 0, /* x11 */
0, /* curctx */
0, /* dircolor */
0, /* picker */
static char *bmstr;
static char *pluginstr;
static char *opener;
-static char *copier;
static char *editor;
static char *enveditor;
static char *pager;
#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[] = {
"sh",
"fzf",
"fzy",
- ".notify",
+ ".ntfy",
+ ".cbcp",
};
/* Common strings */
#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",
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 */
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);
}
}
}
nselected = lines;
writesel(pselbuf, selbufpos - 1);
- spawn(copier, NULL, NULL, NULL, F_NOTRACE);
return 1;
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;
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;
}
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;
= (!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
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();
" -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);
}
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;
case 'v':
fprintf(stdout, "%s\n", VERSION);
return _SUCCESS;
+ case 'x':
+ cfg.x11 = 1;
+ break;
case 'h':
usage();
return _SUCCESS;
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];