Thumbnail

rani/cscroll.git

Clone URL: https://git.buni.party/rani/cscroll.git

commit e2c8217edc2dbfbb1477ff5df58edb0e27c84b79 Author: rani <clagv.randomgames@gmail.com> Date: Thu Jan 15 17:24:31 2026 +0000 Add: marked file deletion 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";