aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar KlzXS <azszwymmvqdi@yahoo.com>2019-10-14 18:36:45 +0200
committerGravatar Mischievous Meerkat <engineerarun@gmail.com>2019-10-14 22:06:45 +0530
commitb9d183db26956cc1a3e1260dabd5c40d9ad2e8b4 (patch)
tree1eded00dad28feae173a8b3d49f9571d90a3e97a /src
parent04cba311284be91990057242409443159bd3a77c (diff)
downloadnnn-b9d183db26956cc1a3e1260dabd5c40d9ad2e8b4.tar.gz
Added copy/move-as (copy/move and rename) (#356)
* Added copy/move-as (copy/move and rename) * Little refactorings * Also handle selection file for cpmv_rename()
Diffstat (limited to 'src')
-rw-r--r--src/nnn.c102
-rw-r--r--src/nnn.h6
2 files changed, 97 insertions, 11 deletions
diff --git a/src/nnn.c b/src/nnn.c
index b18f3d7..093cc37 100644
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -390,7 +390,7 @@ static char mv[] = "mvg -gi";
#define STR_TMPFILE 3
#define NONE_SELECTED 4
#define UTIL_MISSING 5
-#define MOUNT_FAILED 6
+#define OPERATION_FAILED 6
static const char * const messages[] = {
"no traversal",
@@ -399,7 +399,7 @@ static const char * const messages[] = {
"/.nnnXXXXXX",
"0 selected",
"missing dep",
- "mount failed",
+ "failed!",
};
/* Supported configuration environment variables */
@@ -1280,6 +1280,70 @@ static void xrm(char *path)
}
}
+static bool cpmv_rename(const char *path, const char *cmd)
+{
+ int fd, i;
+ uint count = 0, lines = 0;
+ bool ret = FALSE;
+ const char formatcmd[] = "sed -i 's|^\\(\\(.*/\\)\\(.*\\)$\\)|#\\1\\n\\3|' %s";
+ const char renamecmd[] =
+ "sed 's|^\\([^#][^/]\\?.*\\)$|%s/\\1|;s|^#\\(/.*\\)$|\\1|' %s | tr '\\n' '\\0' | xargs -0 -o -n2 %s";
+ char buf[sizeof(renamecmd) + sizeof(cmd) + (PATH_MAX << 1)];
+
+ if ((fd = create_tmp_file()) == -1)
+ return ret;
+
+ /* selsafe() returned TRUE for this to be called */
+ if (!selbufpos) {
+ snprintf(buf, sizeof(buf), "cat %s | tr '\\0' '\\n' > %s", g_selpath, g_tmpfpath);
+ spawn("sh", "-c", buf, NULL, F_NORMAL | F_CMD);
+
+ while ((i = read(fd, buf, sizeof(buf))) > 0)
+ while(i)
+ count += (buf[--i] == '\n');
+
+ if (!count)
+ goto finish;
+ } else {
+ seltofile(fd, &count);
+ }
+
+ close(fd);
+
+ snprintf(buf, sizeof(buf), formatcmd, g_tmpfpath);
+ spawn("sh", "-c", buf, path, F_NORMAL);
+
+ spawn(editor, g_tmpfpath, NULL, path, F_CLI);
+
+ if ((fd = open(g_tmpfpath, O_RDONLY)) == -1)
+ goto finish;
+
+ while ((i = read(fd, buf, sizeof(buf))) > 0)
+ while (i)
+ lines += (buf[--i] == '\n');
+
+ if (i < 0)
+ goto finish;
+
+ DPRINTF_U(count);
+ DPRINTF_U(lines);
+
+ if (2 * count != lines) {
+ DPRINTF_S("cannot delete files");
+ goto finish;
+ }
+
+ snprintf(buf, sizeof(buf), renamecmd, path, g_tmpfpath, cmd);
+ spawn("sh", "-c", buf, path, F_NORMAL);
+ ret = TRUE;
+
+finish:
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
static bool batch_rename(const char *path)
{
int fd1, fd2, i;
@@ -2847,7 +2911,7 @@ static bool archive_mount(char *name, char *path, char *newpath, int *presel)
DPRINTF_S(name);
DPRINTF_S(newpath);
if (spawn(cmd, name, newpath, path, F_NORMAL)) {
- printwait(messages[MOUNT_FAILED], presel);
+ printwait(messages[OPERATION_FAILED], presel);
return FALSE;
}
@@ -2889,7 +2953,7 @@ static bool sshfs_mount(char *newpath, int *presel)
/* Connect to remote */
if (spawn(env, tmp, newpath, NULL, flag)) {
- printwait(messages[MOUNT_FAILED], presel);
+ printwait(messages[OPERATION_FAILED], presel);
return FALSE;
}
@@ -2939,7 +3003,7 @@ static bool unmount(char *name, char *newpath, int *presel, char *currentpath)
}
if (spawn(cmd, "-u", newpath, NULL, F_NORMAL)) {
- printwait("unmount failed", presel);
+ printwait(messages[OPERATION_FAILED], presel);
return FALSE;
}
@@ -2997,8 +3061,9 @@ static void show_help(const char *path)
"9⎵ ^J Select entry r Batch rename\n"
"9m ^K Sel range, clear M List selection\n"
"ca Select all K Edit selection\n"
- "cP Copy selection X Delete selection\n"
- "cV Move selection ^X Delete entry\n"
+ "cP Copy selection w Copy selection as\n"
+ "cV Move selection W Move selection as\n"
+ "cX Delete selection ^X Delete entry\n"
"cf Create archive T Mount archive\n"
"b^F Extract archive F List archive\n"
"ce Edit in EDITOR p Open in PAGER\n"
@@ -4187,7 +4252,7 @@ nochange:
endselection();
if (!batch_rename(path)) {
- printwait("batch rename failed", &presel);
+ printwait(messages[OPERATION_FAILED], &presel);
goto nochange;
}
break;
@@ -4319,12 +4384,14 @@ nochange:
goto nochange;
case SEL_SELEDIT:
if (!seledit()){
- printwait("edit failed!", &presel);
+ printwait(messages[OPERATION_FAILED], &presel);
goto nochange;
}
break;
case SEL_CP:
case SEL_MV:
+ case SEL_CPAS:
+ case SEL_MVAS:
case SEL_RMMUL:
{
endselection();
@@ -4341,15 +4408,28 @@ nochange:
case SEL_MV:
mvstr(g_buf);
break;
+ case SEL_CPAS:
+ if (!cpmv_rename(path, cp)) {
+ printwait(messages[OPERATION_FAILED], &presel);
+ goto nochange;
+ }
+ break;
+ case SEL_MVAS:
+ if (!cpmv_rename(path, mv)) {
+ printwait(messages[OPERATION_FAILED], &presel);
+ goto nochange;
+ }
+ break;
default: /* SEL_RMMUL */
rmmulstr(g_buf);
break;
}
- spawn("sh", "-c", g_buf, path, F_NORMAL);
+ if (sel != SEL_CPAS && sel != SEL_MVAS)
+ spawn("sh", "-c", g_buf, path, F_NORMAL);
/* Clear selection on move or delete */
- if (sel == SEL_MV || sel == SEL_RMMUL) {
+ if (sel == SEL_MV || sel == SEL_MVAS || sel == SEL_RMMUL) {
nselected = 0;
selbufpos = 0;
writesel(NULL, 0);
diff --git a/src/nnn.h b/src/nnn.h
index 2933d26..b6f4886 100644
--- a/src/nnn.h
+++ b/src/nnn.h
@@ -82,6 +82,8 @@ enum action {
SEL_SELEDIT,
SEL_CP,
SEL_MV,
+ SEL_CPAS,
+ SEL_MVAS,
SEL_RMMUL,
SEL_RM,
SEL_OPENWITH,
@@ -217,6 +219,10 @@ static struct key bindings[] = {
{ 'P', SEL_CP },
/* Move from selection buffer */
{ 'V', SEL_MV },
+ /* Copyfrom selection buffer and rename */
+ { 'w', SEL_CPAS },
+ /* Movefrom selection buffer and rename */
+ { 'W', SEL_MVAS },
/* Delete from selection buffer */
{ 'X', SEL_RMMUL },
/* Delete currently selected */