mirror of
https://github.com/jarun/nnn.git
synced 2024-11-28 05:41:31 +00:00
Trash file when deleted
This commit is contained in:
parent
bf7a5f25aa
commit
62d1ff278f
|
@ -102,11 +102,11 @@ It runs on Linux, macOS, Raspberry Pi, BSD, Cygwin, Linux subsystem for Windows
|
||||||
- Convenience
|
- Convenience
|
||||||
- Create, rename files and directories
|
- Create, rename files and directories
|
||||||
- Select files across dirs; all/range selection
|
- Select files across dirs; all/range selection
|
||||||
- Copy, move, delete, archive selection
|
- Copy, move, trash, delete, archive selection
|
||||||
- Show copy, move progress on Linux (needs avdcpmv)
|
- Show copy, move progress on Linux (needs avdcpmv)
|
||||||
- Create sym/hard link(s) to selection
|
- Create sym/hard link(s) to selection
|
||||||
- Transfer files using lftp
|
- Transfer files using lftp
|
||||||
- Batch rename/move/delete (needs vidir)
|
- Batch rename (needs vidir)
|
||||||
- Show directories in custom color (default: blue)
|
- Show directories in custom color (default: blue)
|
||||||
- Per-context directory color
|
- Per-context directory color
|
||||||
- Spawn a subshell in the current directory
|
- Spawn a subshell in the current directory
|
||||||
|
@ -153,7 +153,7 @@ Intrigued? Find out [HOW](https://github.com/jarun/nnn/wiki/performance-factors)
|
||||||
| cp, mv, rm, xargs (from findutils on Linux) | copy, move and remove files |
|
| cp, mv, rm, xargs (from findutils on Linux) | copy, move and remove files |
|
||||||
| mediainfo, exiftool | multimedia file details |
|
| mediainfo, exiftool | multimedia file details |
|
||||||
| atool, patool ([integration](https://github.com/jarun/nnn/wiki/How-to#integrate-patool)) | create, list and extract archives |
|
| atool, patool ([integration](https://github.com/jarun/nnn/wiki/How-to#integrate-patool)) | create, list and extract archives |
|
||||||
| vidir (from moreutils) | batch rename, move, delete dir entries |
|
| vidir (from moreutils) | batch rename dir entries |
|
||||||
| vlock (Linux), bashlock (macOS), lock(1) (BSD) | terminal locker |
|
| vlock (Linux), bashlock (macOS), lock(1) (BSD) | terminal locker |
|
||||||
| advcpmv (Linux) ([integration](https://github.com/jarun/nnn/wiki/How-to#show-cp-mv-progress)) | copy, move progress |
|
| advcpmv (Linux) ([integration](https://github.com/jarun/nnn/wiki/How-to#show-cp-mv-progress)) | copy, move progress |
|
||||||
| $EDITOR (overridden by $VISUAL, if defined) | edit files (fallback vi) |
|
| $EDITOR (overridden by $VISUAL, if defined) | edit files (fallback vi) |
|
||||||
|
@ -254,7 +254,7 @@ Press <kbd>?</kbd> in `nnn` to see the list anytime.
|
||||||
FILES
|
FILES
|
||||||
^O Open with... n Create new/link
|
^O Open with... n Create new/link
|
||||||
D File details ^R Rename entry
|
D File details ^R Rename entry
|
||||||
⎵ ^K / Y Select entry/all r Open dir in vidir
|
⎵ ^K / Y Select entry/all r Batch rename
|
||||||
K ^Y Toggle selection y List selection
|
K ^Y Toggle selection y List selection
|
||||||
P Copy selection X Delete selection
|
P Copy selection X Delete selection
|
||||||
V Move selection ^X Delete entry
|
V Move selection ^X Delete entry
|
||||||
|
@ -393,6 +393,7 @@ The following indicators are used in the detail view:
|
||||||
| `NNN_NO_AUTOSELECT=1` | do not auto-select matching dir in _nav-as-you-type` mode |
|
| `NNN_NO_AUTOSELECT=1` | do not auto-select matching dir in _nav-as-you-type` mode |
|
||||||
| `NNN_RESTRICT_NAV_OPEN=1` | open files on <kbd> ↵</kbd>, not <kbd>→</kbd> or <kbd>l</kbd> |
|
| `NNN_RESTRICT_NAV_OPEN=1` | open files on <kbd> ↵</kbd>, not <kbd>→</kbd> or <kbd>l</kbd> |
|
||||||
| `NNN_RESTRICT_0B=1` | do not open 0-byte files |
|
| `NNN_RESTRICT_0B=1` | do not open 0-byte files |
|
||||||
|
| `NNN_TRASH=1` | move files to `~/.local/share/nnn/trash` on delete |
|
||||||
| `NNN_CP_MV_PROG=1` | show copy, move progress on Linux |
|
| `NNN_CP_MV_PROG=1` | show copy, move progress on Linux |
|
||||||
|
|
||||||
#### Help
|
#### Help
|
||||||
|
|
7
nnn.1
7
nnn.1
|
@ -97,7 +97,7 @@ Show entry details
|
||||||
.It Ic ^R
|
.It Ic ^R
|
||||||
Rename selected entry
|
Rename selected entry
|
||||||
.It Ic r
|
.It Ic r
|
||||||
Open directory in vidir
|
Batch rename
|
||||||
.It Ic K, ^Y
|
.It Ic K, ^Y
|
||||||
Toggle selection mode
|
Toggle selection mode
|
||||||
.It Ic Y
|
.It Ic Y
|
||||||
|
@ -348,6 +348,11 @@ files.
|
||||||
export NNN_RESTRICT_0B=1
|
export NNN_RESTRICT_0B=1
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
|
\fBNNN_TRASH:\fR move files to \fB~/.local/share/nnn/trash\fR on delete.
|
||||||
|
.Bd -literal
|
||||||
|
export NNN_TRASH=1
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
\fBNNN_CP_MV_PROG:\fR show progress of copy, move operations (Linux-only, needs advcpmv).
|
\fBNNN_CP_MV_PROG:\fR show progress of copy, move operations (Linux-only, needs advcpmv).
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
export NNN_CP_MV_PROG=1
|
export NNN_CP_MV_PROG=1
|
||||||
|
|
59
src/nnn.c
59
src/nnn.c
|
@ -285,7 +285,7 @@ typedef struct {
|
||||||
uint dircolor : 1; /* Current status of dir color */
|
uint dircolor : 1; /* Current status of dir color */
|
||||||
uint metaviewer : 1; /* Index of metadata viewer in utils[] */
|
uint metaviewer : 1; /* Index of metadata viewer in utils[] */
|
||||||
uint ctxactive : 1; /* Context active or not */
|
uint ctxactive : 1; /* Context active or not */
|
||||||
uint reserved : 8;
|
uint reserved : 7;
|
||||||
/* The following settings are global */
|
/* The following settings are global */
|
||||||
uint curctx : 2; /* Current context number */
|
uint curctx : 2; /* Current context number */
|
||||||
uint picker : 1; /* Write selection to user-specified file */
|
uint picker : 1; /* Write selection to user-specified file */
|
||||||
|
@ -297,6 +297,7 @@ typedef struct {
|
||||||
uint restrict0b : 1; /* Restrict 0-byte file opening */
|
uint restrict0b : 1; /* Restrict 0-byte file opening */
|
||||||
uint filter_re : 1; /* Use regex filters */
|
uint filter_re : 1; /* Use regex filters */
|
||||||
uint wild : 1; /* Do not sort entries on dir load */
|
uint wild : 1; /* Do not sort entries on dir load */
|
||||||
|
uint trash : 1; /* Move removed files to trash */
|
||||||
} settings;
|
} settings;
|
||||||
|
|
||||||
/* Contexts or workspaces */
|
/* Contexts or workspaces */
|
||||||
|
@ -311,7 +312,7 @@ typedef struct {
|
||||||
/* GLOBALS */
|
/* GLOBALS */
|
||||||
|
|
||||||
/* Configuration, contexts */
|
/* Configuration, contexts */
|
||||||
static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0};
|
static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1};
|
||||||
static context g_ctx[CTX_MAX] __attribute__ ((aligned));
|
static context g_ctx[CTX_MAX] __attribute__ ((aligned));
|
||||||
|
|
||||||
static struct entry *dents;
|
static struct entry *dents;
|
||||||
|
@ -446,8 +447,9 @@ static const char * const messages[] = {
|
||||||
#define NNN_NO_AUTOSELECT 11
|
#define NNN_NO_AUTOSELECT 11
|
||||||
#define NNN_RESTRICT_NAV_OPEN 12
|
#define NNN_RESTRICT_NAV_OPEN 12
|
||||||
#define NNN_RESTRICT_0B 13
|
#define NNN_RESTRICT_0B 13
|
||||||
|
#define NNN_TRASH 14
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#define NNN_CP_MV_PROG 14
|
#define NNN_CP_MV_PROG 15
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char * const env_cfg[] = {
|
static const char * const env_cfg[] = {
|
||||||
|
@ -465,6 +467,7 @@ static const char * const env_cfg[] = {
|
||||||
"NNN_NO_AUTOSELECT",
|
"NNN_NO_AUTOSELECT",
|
||||||
"NNN_RESTRICT_NAV_OPEN",
|
"NNN_RESTRICT_NAV_OPEN",
|
||||||
"NNN_RESTRICT_0B",
|
"NNN_RESTRICT_0B",
|
||||||
|
"NNN_TRASH",
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
"NNN_CP_MV_PROG",
|
"NNN_CP_MV_PROG",
|
||||||
#endif
|
#endif
|
||||||
|
@ -1152,18 +1155,26 @@ static void cpstr(char *buf)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mvstr(char *buf)
|
static void mvstr(char *buf, const char *dst)
|
||||||
{
|
{
|
||||||
snprintf(buf, CMD_LEN_MAX,
|
snprintf(buf, CMD_LEN_MAX,
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
"xargs -0 -a %s -%c src %s src .", g_cppath, REPLACE_STR, mv);
|
"xargs -0 -a %s -%c src %s src %s", g_cppath, REPLACE_STR, mv, dst);
|
||||||
#else
|
#else
|
||||||
"cat %s | xargs -0 -o -%c src mv -i src .", g_cppath, REPLACE_STR);
|
"cat %s | xargs -0 -o -%c src mv -i src %s", g_cppath, REPLACE_STR, dst);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rmmulstr(char *buf)
|
static bool rmmulstr(char *buf, const char *curpath)
|
||||||
{
|
{
|
||||||
|
if (cfg.trash && strcmp(curpath, g_trash) != 0) {
|
||||||
|
if (!xdiraccess(g_trash))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
mvstr(buf, g_trash);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(buf, CMD_LEN_MAX,
|
snprintf(buf, CMD_LEN_MAX,
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
"xargs -0 -a %s rm -%cr",
|
"xargs -0 -a %s rm -%cr",
|
||||||
|
@ -1171,13 +1182,27 @@ static void rmmulstr(char *buf)
|
||||||
"cat %s | xargs -0 -o rm -%cr",
|
"cat %s | xargs -0 -o rm -%cr",
|
||||||
#endif
|
#endif
|
||||||
g_cppath, confirm_force());
|
g_cppath, confirm_force());
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xrm(char *path)
|
static bool xrm(char *path)
|
||||||
{
|
{
|
||||||
|
DPRINTF_S(path);
|
||||||
|
DPRINTF_S(xbasename(path));
|
||||||
|
DPRINTF_S(g_trash);
|
||||||
|
if (cfg.trash && strcmp(xdirname(path), g_trash) != 0) {
|
||||||
|
if (!xdiraccess(g_trash))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
spawn("mv", path, g_trash, NULL, F_NORMAL | F_SIGINT);
|
||||||
|
DPRINTF_S(g_buf);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
char rm_opts[] = {'-', confirm_force(), 'r'};
|
char rm_opts[] = {'-', confirm_force(), 'r'};
|
||||||
|
|
||||||
spawn("rm", rm_opts, path, NULL, F_NORMAL | F_SIGINT);
|
spawn("rm", rm_opts, path, NULL, F_NORMAL | F_SIGINT);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int digit_compare(const char *a, const char *b)
|
static int digit_compare(const char *a, const char *b)
|
||||||
|
@ -2332,7 +2357,7 @@ static bool show_help(const char *path)
|
||||||
"1FILES\n"
|
"1FILES\n"
|
||||||
"b^O Open with... n Create new/link\n"
|
"b^O Open with... n Create new/link\n"
|
||||||
"cD File details ^R Rename entry\n"
|
"cD File details ^R Rename entry\n"
|
||||||
"5⎵ ^K / Y Select entry/all r Open dir in vidir\n"
|
"5⎵ ^K / Y Select entry/all r Batch rename\n"
|
||||||
"9K ^Y Toggle selection y List selection\n"
|
"9K ^Y Toggle selection y List selection\n"
|
||||||
"cP Copy selection X Delete selection\n"
|
"cP Copy selection X Delete selection\n"
|
||||||
"cV Move selection ^X Delete entry\n"
|
"cV Move selection ^X Delete entry\n"
|
||||||
|
@ -2383,7 +2408,7 @@ static bool show_help(const char *path)
|
||||||
dprintf(fd, "\n");
|
dprintf(fd, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = NNN_OPENER; i <= NNN_RESTRICT_0B; ++i) {
|
for (i = NNN_OPENER; i <= NNN_TRASH; ++i) {
|
||||||
start = getenv(env_cfg[i]);
|
start = getenv(env_cfg[i]);
|
||||||
if (start) {
|
if (start) {
|
||||||
if (i < NNN_USE_EDITOR)
|
if (i < NNN_USE_EDITOR)
|
||||||
|
@ -3498,10 +3523,11 @@ nochange:
|
||||||
cpstr(g_buf);
|
cpstr(g_buf);
|
||||||
break;
|
break;
|
||||||
case SEL_MV:
|
case SEL_MV:
|
||||||
mvstr(g_buf);
|
mvstr(g_buf, ".");
|
||||||
break;
|
break;
|
||||||
default: /* SEL_RMMUL */
|
default: /* SEL_RMMUL */
|
||||||
rmmulstr(g_buf);
|
if (!rmmulstr(g_buf, path))
|
||||||
|
goto nochange;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3519,7 +3545,8 @@ nochange:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mkpath(path, dents[cur].name, newpath);
|
mkpath(path, dents[cur].name, newpath);
|
||||||
xrm(newpath);
|
if (!xrm(newpath))
|
||||||
|
goto nochange;
|
||||||
|
|
||||||
/* Don't optimize cur if filtering is on */
|
/* Don't optimize cur if filtering is on */
|
||||||
if (!cfg.filtermode && cur && access(newpath, F_OK) == -1)
|
if (!cfg.filtermode && cur && access(newpath, F_OK) == -1)
|
||||||
|
@ -4090,9 +4117,9 @@ int main(int argc, char *argv[])
|
||||||
home = getenv("HOME");
|
home = getenv("HOME");
|
||||||
DPRINTF_S(home);
|
DPRINTF_S(home);
|
||||||
|
|
||||||
if (getenv("NNN_TRASH")) {
|
if (getenv(env_cfg[NNN_TRASH])) {
|
||||||
if (!home) {
|
if (!home) {
|
||||||
fprintf(stderr, "trash! no HOME!\n");
|
fprintf(stderr, "trash: HOME!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4108,6 +4135,8 @@ int main(int argc, char *argv[])
|
||||||
DPRINTF_S(g_trash);
|
DPRINTF_S(g_trash);
|
||||||
if (!createdir(g_trash, 0777))
|
if (!createdir(g_trash, 0777))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
cfg.trash = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (home) {
|
if (home) {
|
||||||
|
|
Loading…
Reference in a new issue