From 8888c23cadbcf0b958519fcaf8dd1869eb399449 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 23 Feb 2020 19:48:24 -0800 Subject: [PATCH] Cleaned up column rendering logic, including adding a 'stretchy' option for columns to fill available space. Also fixed some coloring issues. --- bb.c | 56 ++++++++++++++++++++++++--------- bb.h | 3 +- columns.h | 93 ++++++++++++++++++++----------------------------------- 3 files changed, 76 insertions(+), 76 deletions(-) diff --git a/bb.c b/bb.c index 8eec2ee..ab95d0b 100644 --- a/bb.c +++ b/bb.c @@ -84,6 +84,18 @@ void cleanup(void) } } +/* + * Returns the color of a file listing, given its mode. + */ +const char* color_of(mode_t mode) +{ + if (S_ISDIR(mode)) return DIR_COLOR; + else if (S_ISLNK(mode)) return LINK_COLOR; + else if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) + return EXECUTABLE_COLOR; + else return NORMAL_COLOR; +} + /* * Used for sorting, this function compares files according to the sorting-related options, * like bb->sort @@ -143,7 +155,7 @@ int compare_files(const void *v1, const void *v2, void *v) case COL_MTIME: COMPARE_TIME(mtime(e1->info), mtime(e2->info)); break; case COL_CTIME: COMPARE_TIME(ctime(e1->info), ctime(e2->info)); break; case COL_ATIME: COMPARE_TIME(atime(e1->info), atime(e2->info)); break; - case COL_RANDOM: COMPARE(e1->shufflepos, e2->shufflepos); break; + case COL_RANDOM: COMPARE(e2->shufflepos, e1->shufflepos); break; } } return 0; @@ -723,7 +735,6 @@ void run_bbcmd(bb_t *bb, const char *cmd) void render(bb_t *bb) { static int lastcursor = -1, lastscroll = -1; - char buf[PATH_MAX * 2]; if (!dirty) { // Use terminal scrolling: @@ -734,6 +745,22 @@ void render(bb_t *bb) } } + int colwidths[MAX_COLS] = {0}; + int space = winsize.ws_col - 1, nstretchy = 0; + for (int c = 0; bb->columns[c]; c++) { + column_t col = columns[(int)bb->columns[c]]; + if (col.stretchy) { + ++nstretchy; + } else { + colwidths[c] = strlen(col.name) + 1; + space -= colwidths[c]; + } + if (c > 0) --space; + } + for (int c = 0; bb->columns[c]; c++) + if (columns[(int)bb->columns[c]].stretchy) + colwidths[c] = space / nstretchy; + if (dirty) { // Path move_cursor(tty_out, 0, 0); @@ -773,7 +800,7 @@ void render(bb_t *bb) move_cursor(tty_out, x, 1); fputs(indicator, tty_out); fputs(title, tty_out); - x += (int)strlen(title) + 1; + x += colwidths[col]; } fputs(" \033[K\033[0m", tty_out); } @@ -805,28 +832,27 @@ void render(bb_t *bb) } entry_t *entry = files[i]; - if (i == bb->cursor) fputs(CURSOR_COLOR, tty_out); + const char *color = i == bb->cursor ? + CURSOR_COLOR : color_of(bb->files[i]->info.st_mode); int x = 0; for (int c = 0; bb->columns[c]; c++) { column_t col = columns[(int)bb->columns[c]]; - memset(buf, 0, sizeof(buf)); - col.render(bb, entry, buf, strlen(col.name)+1); - - fprintf(tty_out, "\033[%d;%dH\033[K", y+1, x+1); if (col.name == NULL) continue; + move_cursor(tty_out, x, y); + fputs(color, tty_out); if (c > 0) { - if (i == bb->cursor) fputs("┃", tty_out); - else fputs("\033[37;2m┃\033[22m", tty_out); - fputs(i == bb->cursor ? CURSOR_COLOR : "\033[0m", tty_out); + if (i == bb->cursor) fprintf(tty_out, "\033[2m┃\033[22m"); + else fprintf(tty_out, "\033[37;2m┃\033[22m%s", color); x += 1; } - move_cursor(tty_out, x, y); + char buf[PATH_MAX * 2] = {0}; + col.render(entry, color, buf, colwidths[c]); fputs(buf, tty_out); - fputs("\033[K", tty_out); - x += (int)strlen(col.name) + 1; + fprintf(tty_out, "\033[0m%s\033[K", color); + x += colwidths[c]; } - fputs(" \033[K\033[0m", tty_out); // Reset color and attributes + fputs("\033[0m", tty_out); } // Scrollbar: diff --git a/bb.h b/bb.h index d85e793..068122c 100644 --- a/bb.h +++ b/bb.h @@ -32,7 +32,7 @@ #define PATH_MAX 4096 #endif -#define BB_TIME_FMT " %I:%M%p %D " +#define BB_TIME_FMT " %T %D " #define MAX_COLS 12 #define MAX_SORT (2*MAX_COLS) #define HASH_SIZE 1024 @@ -183,6 +183,7 @@ void bb_browse(bb_t *bb, const char *initial_path); static void check_cmdfile(bb_t *bb); static void cleanup(void); static void cleanup_and_raise(int sig); +static const char* color_of(mode_t mode); #ifdef __APPLE__ static int compare_files(void *v, const void *v1, const void *v2); #else diff --git a/columns.h b/columns.h index e8b92be..f4f7ef6 100644 --- a/columns.h +++ b/columns.h @@ -12,18 +12,6 @@ static void lpad(char *buf, int width) } } -/* - * Returns the color of a file listing, given its mode. - */ -static const char* color_of(mode_t mode) -{ - if (S_ISDIR(mode)) return DIR_COLOR; - else if (S_ISLNK(mode)) return LINK_COLOR; - else if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) - return EXECUTABLE_COLOR; - else return NORMAL_COLOR; -} - static char* stpcpy_escaped(char *buf, const char *str, const char *color) { static const char *escapes = " abtnvfr e"; @@ -36,7 +24,7 @@ static char* stpcpy_escaped(char *buf, const char *str, const char *color) *(buf++) = *c; } } - *(buf++) = '\0'; + *buf = '\0'; return buf; } @@ -78,63 +66,59 @@ static void timeago(char *buf, time_t t) sprintf(buf, "%d years", (int)delta/YEAR); } -void col_mreltime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_mreltime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; timeago(buf, entry->info.st_mtime); lpad(buf, width); } -void col_areltime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_areltime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; timeago(buf, entry->info.st_atime); lpad(buf, width); } -void col_creltime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_creltime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; timeago(buf, entry->info.st_ctime); lpad(buf, width); } -void col_mtime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_mtime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_mtime))); } -void col_atime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_atime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_atime))); } -void col_ctime(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; +void col_ctime(entry_t *entry, const char *color, char *buf, int width) { + (void)color; strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_ctime))); } -void col_selected(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; (void)width; +void col_selected(entry_t *entry, const char *color, char *buf, int width) { + (void)width; buf = stpcpy(buf, IS_SELECTED(entry) ? SELECTED_INDICATOR : NOT_SELECTED_INDICATOR); - buf = stpcpy(buf, entry == bb->files[bb->cursor] ? - CURSOR_COLOR : color_of(entry->info.st_mode)); + buf = stpcpy(buf, color); } -void col_perm(bb_t *bb, entry_t *entry, char *buf, int width) { - (void)bb; (void)width; +void col_perm(entry_t *entry, const char *color, char *buf, int width) { + (void)color; (void)width; sprintf(buf, " %03o", entry->info.st_mode & 0777); } -void col_random(bb_t *bb, entry_t *entry, char *buf, int width) +void col_random(entry_t *entry, const char *color, char *buf, int width) { - (void)width; - double k = (double)entry->shufflepos/(double)bb->nfiles; - int color = (int)(k*232 + (1.-k)*255); - sprintf(buf, "\033[48;5;%dm \033[0m%s", color, - entry == bb->files[bb->cursor] ? CURSOR_COLOR : "\033[0m"); + (void)color; + sprintf(buf, "%*d", width, entry->shufflepos); } -void col_size(bb_t *bb, entry_t *entry, char *buf, int width) +void col_size(entry_t *entry, const char *color, char *buf, int width) { - (void)bb; (void)width; + (void)color; (void)width; int j = 0; const char* units = "BKMGTPEZY"; double bytes = (double)entry->info.st_size; @@ -145,29 +129,17 @@ void col_size(bb_t *bb, entry_t *entry, char *buf, int width) sprintf(buf, " %6.*f%c ", j > 0 ? 1 : 0, bytes, units[j]); } -void col_name(bb_t *bb, entry_t *entry, char *buf, int width) +void col_name(entry_t *entry, const char *color, char *buf, int width) { (void)width; - char color[128]; - strcpy(color, color_of(entry->info.st_mode)); - if (entry == bb->files[bb->cursor]) strcpy(color, CURSOR_COLOR); - buf = stpcpy(buf, color); - - int use_fullname = strcmp(bb->path, "") == 0; - char *name = use_fullname ? entry->fullname : entry->name; - if (entry->no_esc) buf = stpcpy(buf, name); - else buf = stpcpy_escaped(buf, name, color); + if (entry->no_esc) buf = stpcpy(buf, entry->name); + else buf = stpcpy_escaped(buf, entry->name, color); if (E_ISDIR(entry)) buf = stpcpy(buf, "/"); if (!entry->linkname) return; - if (entry != bb->files[bb->cursor]) - buf = stpcpy(buf, "\033[37m"); buf = stpcpy(buf, "\033[2m -> \033[3m"); - strcpy(color, color_of(entry->linkedmode)); - if (entry == bb->files[bb->cursor]) strcat(color, CURSOR_COLOR); - strcat(color, "\033[3;2m"); buf = stpcpy(buf, color); if (entry->link_no_esc) buf = stpcpy(buf, entry->linkname); else buf = stpcpy_escaped(buf, entry->linkname, color); @@ -180,19 +152,20 @@ void col_name(bb_t *bb, entry_t *entry, char *buf, int width) typedef struct { const char *name; - void (*render)(bb_t *, entry_t *, char *, int); + void (*render)(entry_t*, const char*, char*, int); + unsigned int stretchy : 1; } column_t; static column_t columns[255] = { ['*'] = {.name = "*", .render = col_selected}, - ['n'] = {.name = "Name ", .render = col_name}, + ['n'] = {.name = "Name", .render = col_name, .stretchy = 1}, ['s'] = {.name = " Size", .render = col_size}, ['p'] = {.name = "Perm", .render = col_perm}, ['m'] = {.name = " Modified", .render = col_mreltime}, - ['M'] = {.name = " Modified ", .render = col_mtime}, + ['M'] = {.name = " Modified ", .render = col_mtime}, ['a'] = {.name = " Accessed", .render = col_areltime}, - ['A'] = {.name = " Accessed ", .render = col_atime}, + ['A'] = {.name = " Accessed ", .render = col_atime}, ['c'] = {.name = " Created", .render = col_creltime}, - ['C'] = {.name = " Created ", .render = col_ctime}, - ['r'] = {.name = "R", .render = col_random}, + ['C'] = {.name = " Created ", .render = col_ctime}, + ['r'] = {.name = "Random", .render = col_random}, };