Cleaned up column rendering logic, including adding a 'stretchy' option
for columns to fill available space. Also fixed some coloring issues.
This commit is contained in:
parent
2ab58f3d8c
commit
8888c23cad
56
bb.c
56
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,
|
* Used for sorting, this function compares files according to the sorting-related options,
|
||||||
* like bb->sort
|
* 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_MTIME: COMPARE_TIME(mtime(e1->info), mtime(e2->info)); break;
|
||||||
case COL_CTIME: COMPARE_TIME(ctime(e1->info), ctime(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_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;
|
return 0;
|
||||||
@ -723,7 +735,6 @@ void run_bbcmd(bb_t *bb, const char *cmd)
|
|||||||
void render(bb_t *bb)
|
void render(bb_t *bb)
|
||||||
{
|
{
|
||||||
static int lastcursor = -1, lastscroll = -1;
|
static int lastcursor = -1, lastscroll = -1;
|
||||||
char buf[PATH_MAX * 2];
|
|
||||||
|
|
||||||
if (!dirty) {
|
if (!dirty) {
|
||||||
// Use terminal scrolling:
|
// 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) {
|
if (dirty) {
|
||||||
// Path
|
// Path
|
||||||
move_cursor(tty_out, 0, 0);
|
move_cursor(tty_out, 0, 0);
|
||||||
@ -773,7 +800,7 @@ void render(bb_t *bb)
|
|||||||
move_cursor(tty_out, x, 1);
|
move_cursor(tty_out, x, 1);
|
||||||
fputs(indicator, tty_out);
|
fputs(indicator, tty_out);
|
||||||
fputs(title, tty_out);
|
fputs(title, tty_out);
|
||||||
x += (int)strlen(title) + 1;
|
x += colwidths[col];
|
||||||
}
|
}
|
||||||
fputs(" \033[K\033[0m", tty_out);
|
fputs(" \033[K\033[0m", tty_out);
|
||||||
}
|
}
|
||||||
@ -805,28 +832,27 @@ void render(bb_t *bb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry_t *entry = files[i];
|
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;
|
int x = 0;
|
||||||
for (int c = 0; bb->columns[c]; c++) {
|
for (int c = 0; bb->columns[c]; c++) {
|
||||||
column_t col = columns[(int)bb->columns[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;
|
if (col.name == NULL) continue;
|
||||||
|
move_cursor(tty_out, x, y);
|
||||||
|
fputs(color, tty_out);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
if (i == bb->cursor) fputs("┃", tty_out);
|
if (i == bb->cursor) fprintf(tty_out, "\033[2m┃\033[22m");
|
||||||
else fputs("\033[37;2m┃\033[22m", tty_out);
|
else fprintf(tty_out, "\033[37;2m┃\033[22m%s", color);
|
||||||
fputs(i == bb->cursor ? CURSOR_COLOR : "\033[0m", tty_out);
|
|
||||||
x += 1;
|
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(buf, tty_out);
|
||||||
fputs("\033[K", tty_out);
|
fprintf(tty_out, "\033[0m%s\033[K", color);
|
||||||
x += (int)strlen(col.name) + 1;
|
x += colwidths[c];
|
||||||
}
|
}
|
||||||
fputs(" \033[K\033[0m", tty_out); // Reset color and attributes
|
fputs("\033[0m", tty_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scrollbar:
|
// Scrollbar:
|
||||||
|
3
bb.h
3
bb.h
@ -32,7 +32,7 @@
|
|||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BB_TIME_FMT " %I:%M%p %D "
|
#define BB_TIME_FMT " %T %D "
|
||||||
#define MAX_COLS 12
|
#define MAX_COLS 12
|
||||||
#define MAX_SORT (2*MAX_COLS)
|
#define MAX_SORT (2*MAX_COLS)
|
||||||
#define HASH_SIZE 1024
|
#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 check_cmdfile(bb_t *bb);
|
||||||
static void cleanup(void);
|
static void cleanup(void);
|
||||||
static void cleanup_and_raise(int sig);
|
static void cleanup_and_raise(int sig);
|
||||||
|
static const char* color_of(mode_t mode);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
static int compare_files(void *v, const void *v1, const void *v2);
|
static int compare_files(void *v, const void *v1, const void *v2);
|
||||||
#else
|
#else
|
||||||
|
93
columns.h
93
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 char* stpcpy_escaped(char *buf, const char *str, const char *color)
|
||||||
{
|
{
|
||||||
static const char *escapes = " abtnvfr e";
|
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++) = *c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*(buf++) = '\0';
|
*buf = '\0';
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,63 +66,59 @@ static void timeago(char *buf, time_t t)
|
|||||||
sprintf(buf, "%d years", (int)delta/YEAR);
|
sprintf(buf, "%d years", (int)delta/YEAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void col_mreltime(bb_t *bb, entry_t *entry, char *buf, int width) {
|
void col_mreltime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
timeago(buf, entry->info.st_mtime);
|
timeago(buf, entry->info.st_mtime);
|
||||||
lpad(buf, width);
|
lpad(buf, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void col_areltime(bb_t *bb, entry_t *entry, char *buf, int width) {
|
void col_areltime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
timeago(buf, entry->info.st_atime);
|
timeago(buf, entry->info.st_atime);
|
||||||
lpad(buf, width);
|
lpad(buf, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void col_creltime(bb_t *bb, entry_t *entry, char *buf, int width) {
|
void col_creltime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
timeago(buf, entry->info.st_ctime);
|
timeago(buf, entry->info.st_ctime);
|
||||||
lpad(buf, width);
|
lpad(buf, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void col_mtime(bb_t *bb, entry_t *entry, char *buf, int width) {
|
void col_mtime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_mtime)));
|
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 col_atime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_atime)));
|
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 col_ctime(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb;
|
(void)color;
|
||||||
strftime(buf, (size_t)width, BB_TIME_FMT, localtime(&(entry->info.st_ctime)));
|
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 col_selected(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb; (void)width;
|
(void)width;
|
||||||
buf = stpcpy(buf, IS_SELECTED(entry) ? SELECTED_INDICATOR : NOT_SELECTED_INDICATOR);
|
buf = stpcpy(buf, IS_SELECTED(entry) ? SELECTED_INDICATOR : NOT_SELECTED_INDICATOR);
|
||||||
buf = stpcpy(buf, entry == bb->files[bb->cursor] ?
|
buf = stpcpy(buf, color);
|
||||||
CURSOR_COLOR : color_of(entry->info.st_mode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void col_perm(bb_t *bb, entry_t *entry, char *buf, int width) {
|
void col_perm(entry_t *entry, const char *color, char *buf, int width) {
|
||||||
(void)bb; (void)width;
|
(void)color; (void)width;
|
||||||
sprintf(buf, " %03o", entry->info.st_mode & 0777);
|
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;
|
(void)color;
|
||||||
double k = (double)entry->shufflepos/(double)bb->nfiles;
|
sprintf(buf, "%*d", width, entry->shufflepos);
|
||||||
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 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;
|
int j = 0;
|
||||||
const char* units = "BKMGTPEZY";
|
const char* units = "BKMGTPEZY";
|
||||||
double bytes = (double)entry->info.st_size;
|
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]);
|
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;
|
(void)width;
|
||||||
char color[128];
|
if (entry->no_esc) buf = stpcpy(buf, entry->name);
|
||||||
strcpy(color, color_of(entry->info.st_mode));
|
else buf = stpcpy_escaped(buf, entry->name, color);
|
||||||
if (entry == bb->files[bb->cursor]) strcpy(color, CURSOR_COLOR);
|
|
||||||
buf = stpcpy(buf, color);
|
|
||||||
|
|
||||||
int use_fullname = strcmp(bb->path, "<selection>") == 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 (E_ISDIR(entry)) buf = stpcpy(buf, "/");
|
if (E_ISDIR(entry)) buf = stpcpy(buf, "/");
|
||||||
|
|
||||||
if (!entry->linkname) return;
|
if (!entry->linkname) return;
|
||||||
|
|
||||||
if (entry != bb->files[bb->cursor])
|
|
||||||
buf = stpcpy(buf, "\033[37m");
|
|
||||||
buf = stpcpy(buf, "\033[2m -> \033[3m");
|
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);
|
buf = stpcpy(buf, color);
|
||||||
if (entry->link_no_esc) buf = stpcpy(buf, entry->linkname);
|
if (entry->link_no_esc) buf = stpcpy(buf, entry->linkname);
|
||||||
else buf = stpcpy_escaped(buf, entry->linkname, color);
|
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 {
|
typedef struct {
|
||||||
const char *name;
|
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;
|
} column_t;
|
||||||
|
|
||||||
static column_t columns[255] = {
|
static column_t columns[255] = {
|
||||||
['*'] = {.name = "*", .render = col_selected},
|
['*'] = {.name = "*", .render = col_selected},
|
||||||
['n'] = {.name = "Name ", .render = col_name},
|
['n'] = {.name = "Name", .render = col_name, .stretchy = 1},
|
||||||
['s'] = {.name = " Size", .render = col_size},
|
['s'] = {.name = " Size", .render = col_size},
|
||||||
['p'] = {.name = "Perm", .render = col_perm},
|
['p'] = {.name = "Perm", .render = col_perm},
|
||||||
['m'] = {.name = " Modified", .render = col_mreltime},
|
['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_areltime},
|
||||||
['A'] = {.name = " Accessed ", .render = col_atime},
|
['A'] = {.name = " Accessed ", .render = col_atime},
|
||||||
['c'] = {.name = " Created", .render = col_creltime},
|
['c'] = {.name = " Created", .render = col_creltime},
|
||||||
['C'] = {.name = " Created ", .render = col_ctime},
|
['C'] = {.name = " Created ", .render = col_ctime},
|
||||||
['r'] = {.name = "R", .render = col_random},
|
['r'] = {.name = "Random", .render = col_random},
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user