#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",
"/.nnnXXXXXX",
"0 selected",
"missing dep",
- "mount failed",
+ "failed!",
};
/* Supported configuration environment variables */
}
}
+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;
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;
}
/* Connect to remote */
if (spawn(env, tmp, newpath, NULL, flag)) {
- printwait(messages[MOUNT_FAILED], presel);
+ printwait(messages[OPERATION_FAILED], presel);
return FALSE;
}
}
if (spawn(cmd, "-u", newpath, NULL, F_NORMAL)) {
- printwait("unmount failed", presel);
+ printwait(messages[OPERATION_FAILED], presel);
return FALSE;
}
"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"
endselection();
if (!batch_rename(path)) {
- printwait("batch rename failed", &presel);
+ printwait(messages[OPERATION_FAILED], &presel);
goto nochange;
}
break;
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();
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);