mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Support in-place file rename
This commit is contained in:
parent
5404cee9ee
commit
0b3bec329f
|
@ -210,6 +210,7 @@ To cook yourself, download the [latest stable release](https://github.com/jarun/
|
||||||
D | Show current file details
|
D | Show current file details
|
||||||
m | Show concise media info
|
m | Show concise media info
|
||||||
M | Show full media info
|
M | Show full media info
|
||||||
|
^R | Rename selected entry
|
||||||
s | Toggle sort by file size
|
s | Toggle sort by file size
|
||||||
S | Toggle disk usage mode
|
S | Toggle disk usage mode
|
||||||
t | Toggle sort by mtime
|
t | Toggle sort by mtime
|
||||||
|
|
3
config.h
3
config.h
|
@ -34,6 +34,7 @@ enum action {
|
||||||
SEL_MTIME,
|
SEL_MTIME,
|
||||||
SEL_REDRAW,
|
SEL_REDRAW,
|
||||||
SEL_COPY,
|
SEL_COPY,
|
||||||
|
SEL_RENAME,
|
||||||
SEL_HELP,
|
SEL_HELP,
|
||||||
SEL_RUN,
|
SEL_RUN,
|
||||||
SEL_RUNARG,
|
SEL_RUNARG,
|
||||||
|
@ -140,6 +141,8 @@ static struct key bindings[] = {
|
||||||
{ KEY_F(2), SEL_REDRAW, "", "" },
|
{ KEY_F(2), SEL_REDRAW, "", "" },
|
||||||
/* Copy currently selected file path */
|
/* Copy currently selected file path */
|
||||||
{ CONTROL('K'), SEL_COPY, "", "" },
|
{ CONTROL('K'), SEL_COPY, "", "" },
|
||||||
|
/* Show rename prompt */
|
||||||
|
{ CONTROL('R'), SEL_RENAME, "", "" },
|
||||||
/* Show help */
|
/* Show help */
|
||||||
{ '?', SEL_HELP, "", "" },
|
{ '?', SEL_HELP, "", "" },
|
||||||
/* Run command */
|
/* Run command */
|
||||||
|
|
2
nnn.1
2
nnn.1
|
@ -75,6 +75,8 @@ Show current file details screen
|
||||||
Show concise media info
|
Show concise media info
|
||||||
.It Ic M
|
.It Ic M
|
||||||
Show full media info
|
Show full media info
|
||||||
|
.It Ic ^R
|
||||||
|
Rename selected entry
|
||||||
.It Ic s
|
.It Ic s
|
||||||
Toggle sort by file size
|
Toggle sort by file size
|
||||||
.It Ic S
|
.It Ic S
|
||||||
|
|
63
nnn.c
63
nnn.c
|
@ -1541,6 +1541,7 @@ show_help(char *path)
|
||||||
"eD | Show current file details\n"
|
"eD | Show current file details\n"
|
||||||
"em | Show concise media info\n"
|
"em | Show concise media info\n"
|
||||||
"eM | Show full media info\n"
|
"eM | Show full media info\n"
|
||||||
|
"d^R | Rename selected entry\n"
|
||||||
"es | Toggle sort by file size\n"
|
"es | Toggle sort by file size\n"
|
||||||
"eS | Toggle disk usage mode\n"
|
"eS | Toggle disk usage mode\n"
|
||||||
"et | Toggle sort by mtime\n"
|
"et | Toggle sort by mtime\n"
|
||||||
|
@ -2322,7 +2323,7 @@ nochange:
|
||||||
tmp = readinput();
|
tmp = readinput();
|
||||||
clearprompt();
|
clearprompt();
|
||||||
if (tmp == NULL)
|
if (tmp == NULL)
|
||||||
goto nochange;
|
break;
|
||||||
|
|
||||||
for (r = 0; bookmark[r].key && r < MAX_BM; ++r) {
|
for (r = 0; bookmark[r].key && r < MAX_BM; ++r) {
|
||||||
if (xstrcmp(bookmark[r].key, tmp) == -1)
|
if (xstrcmp(bookmark[r].key, tmp) == -1)
|
||||||
|
@ -2389,9 +2390,6 @@ nochange:
|
||||||
mkpath(path, dents[cur].name, oldpath, PATH_MAX);
|
mkpath(path, dents[cur].name, oldpath, PATH_MAX);
|
||||||
goto begin;
|
goto begin;
|
||||||
case SEL_STATS:
|
case SEL_STATS:
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
|
|
||||||
if (ndents > 0) {
|
if (ndents > 0) {
|
||||||
mkpath(path, dents[cur].name, oldpath, PATH_MAX);
|
mkpath(path, dents[cur].name, oldpath, PATH_MAX);
|
||||||
|
|
||||||
|
@ -2403,14 +2401,12 @@ nochange:
|
||||||
} else {
|
} else {
|
||||||
r = show_stats(oldpath, dents[cur].name, &sb);
|
r = show_stats(oldpath, dents[cur].name, &sb);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
printmsg(strerror(errno));
|
printwarn();
|
||||||
goto nochange;
|
goto nochange;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case SEL_MEDIA: // fallthrough
|
case SEL_MEDIA: // fallthrough
|
||||||
case SEL_FMEDIA:
|
case SEL_FMEDIA:
|
||||||
if (ndents > 0) {
|
if (ndents > 0) {
|
||||||
|
@ -2475,6 +2471,59 @@ nochange:
|
||||||
} else if (!copier)
|
} else if (!copier)
|
||||||
printmsg("NNN_COPIER is not set");
|
printmsg("NNN_COPIER is not set");
|
||||||
goto nochange;
|
goto nochange;
|
||||||
|
case SEL_RENAME:
|
||||||
|
if (ndents <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
printprompt("rename to: ");
|
||||||
|
tmp = readinput();
|
||||||
|
clearprompt();
|
||||||
|
if (tmp == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Allow only relative paths */
|
||||||
|
if (tmp[0] == '/' || basename(tmp) != tmp) {
|
||||||
|
printmsg("relative paths only");
|
||||||
|
goto nochange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip renaming to same name */
|
||||||
|
if (xstrcmp(tmp, dents[cur].name) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Open the descriptor to currently open directory */
|
||||||
|
fd = open(path, O_RDONLY | O_DIRECTORY | O_NOATIME);
|
||||||
|
if (fd == -1) {
|
||||||
|
printwarn();
|
||||||
|
goto nochange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if another file with same name exists */
|
||||||
|
if (faccessat(fd, tmp, F_OK, AT_SYMLINK_NOFOLLOW) != -1) {
|
||||||
|
/* File with the same name exists */
|
||||||
|
xstrlcpy(g_buf, tmp, NAME_MAX);
|
||||||
|
|
||||||
|
printprompt("overwrite? (y): ");
|
||||||
|
tmp = readinput();
|
||||||
|
if (tmp == NULL || tmp[0] != 'y' || tmp[1] != '\0') {
|
||||||
|
close(fd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = g_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rename the file */
|
||||||
|
r = renameat(fd, dents[cur].name, fd, tmp);
|
||||||
|
if (r != 0) {
|
||||||
|
printwarn();
|
||||||
|
close(fd);
|
||||||
|
goto nochange;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
mkpath(path, tmp, oldpath, PATH_MAX);
|
||||||
|
goto begin;
|
||||||
case SEL_HELP:
|
case SEL_HELP:
|
||||||
show_help(path);
|
show_help(path);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue