commit e2c8217edc2dbfbb1477ff5df58edb0e27c84b79
Author: rani <clagv.randomgames@gmail.com>
Date: Thu Jan 15 17:24:31 2026 +0000
diff --git a/include/dir.h b/include/dir.h
index eea10af..52bf7c2 100644
--- a/include/dir.h
+++ b/include/dir.h
@@ -957 +959 @@ cvector(dirent_t) dir_entries(const dir_t * dir);
void dir_sort(dir_t * dir);
const char * dir_get_home(void);
size_t dir_get_total_marked(void);
+size_t dir_marked_subfiles(void);
int dir_paste_marks(const char * cwd, size_t * total_pastes);
+int dir_marked_delete(void);
char dirent_crepr(const dirent_t * de); // character representing dir entry
char dirent_creprl(const dirent_t * de); // like above, but for the link
diff --git a/include/ui.h b/include/ui.h
index 92bcf37..9c9d12d 100644
--- a/include/ui.h
+++ b/include/ui.h
@@ -677 +677 @@ void ui_print_cursor(size_t cursor, size_t total, enum prog_mode mode, size_t to
void ui_resize(void);
const char * ui_readline(const char * prompt);
const char * ui_prompt(const char * prompt, prompt_opts_t opts);
-bool ui_prompt_deletion(const dirent_t * de);
+bool ui_prompt_deletion(const dirent_t * de, size_t total_marked);
bool ui_prompt_paste(size_t total_marked);
#endif /* UI_H */
diff --git a/src/dir.c b/src/dir.c
index 77c4b1e..8f0d9b4 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -7983 +79872 @@ int dir_paste_marks(const char * cwd, size_t * total_pastes) {
n_marks = 0;
return retval;
}
+
+size_t dir_marked_subfiles(void) {
+ size_t total = 0;
+
+ hashmap_walk_state marksws = {0};
+ while (hashmap_walk(marks, &marksws)) {
+ const char * dirpath = marksws.key;
+ hashmap * dirmarks = marksws.val;
+
+ DIR * basedir = opendir(dirpath);
+ if (!basedir) continue;
+ int basedirfd = dirfd(basedir);
+
+ hashmap_walk_state dirmarksws = {0};
+ while (hashmap_walk(dirmarks, &dirmarksws)) {
+ const char * fname = dirmarksws.key;
+
+ struct stat statbuf;
+ int ret = fstatat(basedirfd, fname, &statbuf, AT_SYMLINK_NOFOLLOW);
+ if (ret < 0) continue;
+ if (!S_ISDIR(statbuf.st_mode)) continue;
+
+ char * subpath = malloc(strlen(dirpath) + 1 + strlen(fname) + 1);
+ sprintf(subpath, "%s/%s", dirpath, fname);
+
+ size_t subfiles = 0;
+ dir_internal_ftw(subpath, dirent_subfiles_ftw_cb, &subfiles, false);
+ free(subpath);
+ total += subfiles;
+ }
+
+ closedir(basedir);
+ }
+
+ return total;
+}
+
+int dir_marked_delete(void) {
+ int retval = 0;
+
+ hashmap_walk_state marksws = {0};
+ while (hashmap_walk(marks, &marksws)) {
+ const char * dirpath = marksws.key;
+ hashmap * dirmarks = marksws.val;
+
+ hashmap_walk_state dirmarksws = {0};
+ while (hashmap_walk(dirmarks, &dirmarksws)) {
+ const char * fname = dirmarksws.key;
+
+ char * subpath = malloc(strlen(dirpath) + 1 + strlen(fname) + 1);
+ sprintf(subpath, "%s/%s", dirpath, fname);
+
+ // subpath is absolute so dirfd isn't used
+ dirent_t de;
+ dir_entry(-1, subpath, &de, NULL);
+ free(subpath);
+
+ int ret = dirent_delete(&de);
+ if (ret < 0) retval = ret;
+ free_dirent(&de);
+ }
+ }
+
+ hashmap_destroy(marks);
+ marks = hashmap_new(marks_destroyer);
+ n_marks = 0;
+
+ return retval;
+}
diff --git a/src/main.c b/src/main.c
index 1955f4b..f9c4ae5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1497 +1497 @@ int main(int argc, char ** argv) {
break;
}
ui_refresh();
- bool del = ui_prompt_deletion(cur_de);
+ bool del = ui_prompt_deletion(cur_de, dir_get_total_marked());
if (!del) {
ui_status_info("Not Deleting");
ui_refresh();
@@ -1597 +1599 @@ int main(int argc, char ** argv) {
ui_status_info("Deleting");
ui_refresh();
- int ret = dirent_delete(cur_de);
+ int ret;
+ if (dir_get_total_marked() == 0) ret = dirent_delete(cur_de);
+ else ret = dir_marked_delete();
if (ret < 0) {
ui_status_error("Deletion Failed");
} else {
diff --git a/src/ui.c b/src/ui.c
index 1571bc6..47be8e2 100644
--- a/src/ui.c
+++ b/src/ui.c
@@ -5727 +5727 @@ const char * ui_prompt(const char * prompt, prompt_opts_t opts) {
return ret;
}
-bool ui_prompt_deletion(const dirent_t * de) {
+static bool ui_internal_prompt_dirent_deletion(const dirent_t * de) {
static const char * no = "No";
static const char * yes = "Yes";
@@ -6106 +61045 @@ bool ui_prompt_deletion(const dirent_t * de) {
return true;
}
+static bool ui_internal_prompt_marked_deletion(size_t total_marked) {
+ static const char * no = "No";
+ static const char * yes = "Yes";
+
+ ui_status_info("listing...");
+ ui_refresh();
+ size_t subfiles = dir_marked_subfiles();
+ ui_status_info("");
+ ui_refresh();
+
+ char * prompt;
+ if (subfiles == 0) {
+ const char * fstr = "Delete %zu marked files?";
+ size_t len = snprintf(NULL, 0, fstr, total_marked);
+ prompt = malloc(len + 1);
+ sprintf(prompt, fstr, total_marked);
+ } else {
+ const char * fstr = "Delete %zu marked files and %zu subfiles?";
+ size_t len = snprintf(NULL, 0, fstr, total_marked, subfiles);
+ prompt = malloc(len + 1);
+ sprintf(prompt, fstr, total_marked, subfiles);
+ }
+
+ const char * ret = ui_prompt(prompt, (prompt_opts_t){no, yes, NULL});
+ free(prompt);
+ if (ret != yes) return false;
+
+ ret = ui_prompt("This action cannot be undone. Proceed?", (prompt_opts_t){no, yes, NULL});
+ if (ret != yes) return false;
+ return true;
+}
+
+bool ui_prompt_deletion(const dirent_t * de, size_t total_marked) {
+ if (total_marked > 0)
+ return ui_internal_prompt_marked_deletion(total_marked);
+ else
+ return ui_internal_prompt_dirent_deletion(de);
+}
+
bool ui_prompt_paste(size_t total_marked) {
static const char * no = "No";
static const char * yes = "Yes";