From b9e2bc280befaf259bb5a61d1b6e41de3b8ed3c7 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 8 Nov 2019 15:28:01 +0100 Subject: [PATCH] Cleanup of bb->selected (renamed from bb->firstselected) to ensure that $n arguments for scripts are in FIFO order instead of LIFO order (i.e. $1 is the first selected item). `Ctrl-a` is also now bound to use `+select` instead of `+select: *` which ensures that the correct sorting order is preserved. --- bb.c | 59 +++++++++++++++++++++++++---------------------------- bb.h | 6 +++--- bindings.bb | 3 +-- 3 files changed, 32 insertions(+), 36 deletions(-) diff --git a/bb.c b/bb.c index c8ffe4a..6672fd6 100644 --- a/bb.c +++ b/bb.c @@ -458,7 +458,7 @@ int populate_files(bb_t *bb, const char *path) size_t space = 0; if (strcmp(bb->path, "") == 0) { - for (entry_t *e = bb->firstselected; e; e = e->selected.next) { + for (entry_t *e = bb->selected; e; e = e->selected.next) { if ((size_t)bb->nfiles + 1 > space) bb->files = memcheck(realloc(bb->files, (space += 100)*sizeof(void*))); e->index = bb->nfiles; @@ -614,16 +614,15 @@ void run_bbcmd(bb_t *bb, const char *cmd) return; } // Filename may no longer exist: - for (e = bb->firstselected; e; e = e->selected.next) { + for (e = bb->selected; e; e = e->selected.next) { if (strcmp(e->fullname, pbuf) == 0) { set_selected(bb, e, 0); break; } } } else if (matches_cmd(cmd, "deselect")) { // +deselect - while (bb->firstselected) - set_selected(bb, bb->firstselected, 0); - return; + while (bb->selected) + set_selected(bb, bb->selected, 0); } else if (matches_cmd(cmd, "dotfiles:") || matches_cmd(cmd, "dotfiles")) { // +dotfiles: set_bool(bb->show_dotfiles); setenv("BBDOTFILES", bb->show_dotfiles ? "1" : "", 1); @@ -720,10 +719,13 @@ void run_bbcmd(bb_t *bb, const char *cmd) else set_scroll(bb, n); } else if (matches_cmd(cmd, "select:") || matches_cmd(cmd, "select")) { // +select: - if (!value && !bb->nfiles) return; - if (!value) value = bb->files[bb->cursor]->fullname; - entry_t *e = load_entry(bb, value, 1); - if (e) set_selected(bb, e, 1); + if (!value) { + for (int i = 0; i < bb->nfiles; i++) + set_selected(bb, bb->files[i], 1); + } else { + entry_t *e = load_entry(bb, value, 1); + if (e) set_selected(bb, e, 1); + } } else if (matches_cmd(cmd, "sort:")) { // +sort: set_sort(bb, value); sort_files(bb); @@ -925,9 +927,9 @@ void render(bb_t *bb) move_cursor(tty_out, winsize.ws_col/2, winsize.ws_row - 1); fputs("\033[0m\033[K", tty_out); int x = winsize.ws_col; - if (bb->firstselected) { // Number of selected files + if (bb->selected) { // Number of selected files int n = 0; - for (entry_t *s = bb->firstselected; s; s = s->selected.next) ++n; + for (entry_t *s = bb->selected; s; s = s->selected.next) ++n; x -= 14; for (int k = n; k; k /= 10) x--; move_cursor(tty_out, MAX(0, x), winsize.ws_row - 1); @@ -975,20 +977,18 @@ int run_script(bb_t *bb, const char *cmd) fclose(tty_out); tty_out = NULL; fclose(tty_in); tty_in = NULL; setpgid(0, 0); - // TODO: is there a max number of args? Should this be batched? - size_t space = 32; - char **args = memcheck(calloc(space, sizeof(char*))); - size_t i = 0; + char **args = memcheck(calloc(4 + bb->nselected + 1, sizeof(char*))); + int i = 0; args[i++] = SH; args[i++] = "-c"; args[i++] = fullcmd; args[i++] = "--"; // ensure files like "-i" are not interpreted as flags for sh - for (entry_t *e = bb->firstselected; e; e = e->selected.next) { - if (i >= space) - args = memcheck(realloc(args, (space += 100)*sizeof(char*))); - args[i++] = e->fullname; - } - args[i] = NULL; + // bb->selected is in most-recent order, so populate args in reverse to make sure + // that $1 is the first selected, etc. + i += bb->nselected; + for (entry_t *e = bb->selected; e; e = e->selected.next) + args[--i] = e->fullname; + setenv("BBCURSOR", bb->nfiles ? bb->files[bb->cursor]->fullname : "", 1); int ttyout, ttyin; @@ -1072,10 +1072,12 @@ void set_selected(bb_t *bb, entry_t *e, int selected) dirty = 1; if (selected) { - LL_PREPEND(bb->firstselected, e, selected); + LL_PREPEND(bb->selected, e, selected); + ++bb->nselected; } else { LL_REMOVE(e, selected); try_free_entry(e); + --bb->nselected; } } @@ -1301,8 +1303,8 @@ int main(int argc, char *argv[]) fputs(T_LEAVE_BBMODE, tty_out); cleanup(); - if (bb->firstselected && print_selection) { - for (entry_t *e = bb->firstselected; e; e = e->selected.next) { + if (bb->selected && print_selection) { + for (entry_t *e = bb->selected; e; e = e->selected.next) { write(STDOUT_FILENO, e->fullname, strlen(e->fullname)); write(STDOUT_FILENO, &sep, 1); } @@ -1313,13 +1315,8 @@ int main(int argc, char *argv[]) // Cleanup: populate_files(bb, NULL); - for (entry_t *next, *e = bb->firstselected; e; e = next) { - next = e->selected.next; - e->selected.atme = NULL; - e->selected.next = NULL; - try_free_entry(e); - } - bb->firstselected = NULL; + while (bb->selected) + set_selected(bb, bb->selected, 0); free(bb); if (cmdfilename) free(cmdfilename); diff --git a/bb.h b/bb.h index d80f48b..ec1440f 100644 --- a/bb.h +++ b/bb.h @@ -25,7 +25,7 @@ #include "bterm.h" // Macros: -#define BB_VERSION "0.19.0" +#define BB_VERSION "0.19.1" #ifndef PATH_MAX #define PATH_MAX 4096 @@ -136,10 +136,10 @@ typedef struct entry_s { typedef struct bb_s { entry_t *hash[HASH_SIZE]; entry_t **files; - entry_t *firstselected; + entry_t *selected; char path[PATH_MAX]; char prev_path[PATH_MAX]; - int nfiles; + int nfiles, nselected; int scroll, cursor; char sort[MAX_SORT+1]; diff --git a/bindings.bb b/bindings.bb index 792d5ca..5088a4e 100644 --- a/bindings.bb +++ b/bindings.bb @@ -81,8 +81,7 @@ Shift-Home: # Spread the selection to the top Shift-End: # Spread the selection to the bottom bb +spread:100%n Ctrl-a: # Select all files here - if [ $BBDOTFILES ]; then bb +sel: * .[!.]* ..?* - else bb +sel: *; fi + bb +select Section: File Actions Left click: # Move cursor to file