enabling colors for bmon

This commit enables colors in bmon. It adds configuration options to
let the user decide, which colors should be used. Therefor the graph_rx and graph_tx
layouts are introduced and applied respectively.

* Add graph_rx, graph_tx and layout_cfg fields.
* Setting default colors if colorized output is enabled.
* draw_table accept additional layout parameter and apply the given layout for
  the table graph.
* Apply layouts for rx, tx graph and header and statusbar.
* Add include/layout.h, which provides functions to parse, color and attribute
  strings and set the layout.
* Adding a default layout-config example in examples/bmon.conf.

[Edit: Based on original work by eri!, #PR23]
This commit is contained in:
blastmaster 2016-07-16 01:53:42 +02:00 committed by Thomas Graf
parent 1c25eacc95
commit 828b5b5368
5 changed files with 253 additions and 18 deletions

View File

@ -86,3 +86,27 @@ history day {
interval = 86400.
size = 60
}
layout colors {
color default {
color_pair = {"white", "black"}
}
color statusbar {
color_pair = {"blue", "white", "reverse"}
}
color header {
color_pair = {"yellow", "black"}
}
color list {
color_pair = {"white", "black"}
}
color selected {
color_pair = {"white", "black", "reverse"}
}
color RX_graph {
color_pair = {"green", "black"}
}
color TX_graph {
color_pair = {"red", "black"}
}
}

View File

@ -74,6 +74,8 @@ enum {
LAYOUT_HEADER,
LAYOUT_LIST,
LAYOUT_SELECTED,
LAYOUT_RX_GRAPH,
LAYOUT_TX_GRAPH,
__LAYOUT_MAX
};

128
include/bmon/layout.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef __BMON_LAYOUT_H_
#define __BMON_LAYOUT_H_
#include <bmon/bmon.h>
#include <bmon/conf.h>
#include <bmon/unit.h>
#include <bmon/utils.h>
static int parse_color(const char* color)
{
int color_code = -1;
if ((strcasestr(color, "red") != NULL))
color_code = COLOR_RED;
else if ((strcasestr(color, "green") != NULL))
color_code = COLOR_GREEN;
else if ((strcasestr(color, "white") != NULL))
color_code = COLOR_WHITE;
else if ((strcasestr(color, "black") != NULL))
color_code = COLOR_BLACK;
else if ((strcasestr(color, "blue") != NULL))
color_code = COLOR_BLUE;
else if ((strcasestr(color, "yellow") != NULL))
color_code = COLOR_YELLOW;
else if ((strcasestr(color, "magenta") != NULL))
color_code = COLOR_MAGENTA;
else if ((strcasestr(color, "cyan") != NULL))
color_code = COLOR_CYAN;
return color_code;
}
/*
A_NORMAL Normal display (no highlight)
A_STANDOUT Best highlighting mode of the terminal.
A_UNDERLINE Underlining
A_REVERSE Reverse video
A_BLINK Blinking
A_DIM Half bright
A_BOLD Extra bright or bold
A_PROTECT Protected mode
A_INVIS Invisible or blank mode
A_ALTCHARSET Alternate character set
A_CHARTEXT Bit-mask to extract a character
*/
static int parse_attribute(const char* attr)
{
/* no attribute is valid, so we have nothing to do */
if (attr == NULL)
return 0;
if ((strcasestr(attr, "normal") != NULL))
return A_NORMAL;
else if ((strcasestr(attr, "standout") != NULL))
return A_STANDOUT;
else if ((strcasestr(attr, "underline") != NULL))
return A_UNDERLINE;
else if ((strcasestr(attr, "reverse") != NULL))
return A_REVERSE;
else if ((strcasestr(attr, "blink") != NULL))
return A_BLINK;
else if ((strcasestr(attr, "dim") != NULL))
return A_DIM;
else if ((strcasestr(attr, "bold") != NULL))
return A_BOLD;
else if ((strcasestr(attr, "protect") != NULL))
return A_PROTECT;
else if ((strcasestr(attr, "invis") != NULL))
return A_INVIS;
else if ((strcasestr(attr, "altcharset") != NULL))
return A_ALTCHARSET;
else if ((strcasestr(attr, "chartext") != NULL))
return A_CHARTEXT;
return -1;
}
static void add_layout(const char *layout_name, cfg_t *color_cfg)
{
const char *fg, *bg, *attr_str = NULL;
int size = -1, fg_code, bg_code, attr_mask, layout_idx = 0;
size = cfg_size(color_cfg, "color_pair");
fg = cfg_getnstr(color_cfg, "color_pair", 0);
bg = cfg_getnstr(color_cfg, "color_pair", 1);
if (size > 2)
attr_str = cfg_getnstr(color_cfg, "color_pair", 2);
fg_code = parse_color(fg);
bg_code = parse_color(bg);
if (fg_code == -1 || bg_code == -1) {
quit("Unknown color [%s]: %s\n", (fg_code == -1) ? "fg" : "bg",
(fg_code == -1) ? fg : bg);
}
attr_mask = parse_attribute(attr_str);
if (attr_mask == -1) {
quit("Unknown attribute: '%s'\n", attr_str);
}
DBG("%s:\tfg: %s bg: %s attr: %s\n", layout_name, fg, bg, attr_str);
if ((strcasecmp(layout_name, "default") == 0))
layout_idx = LAYOUT_DEFAULT;
else if ((strcasecmp(layout_name, "statusbar") == 0))
layout_idx = LAYOUT_STATUSBAR;
else if ((strcasecmp(layout_name, "header") == 0))
layout_idx = LAYOUT_HEADER;
else if ((strcasecmp(layout_name, "list") == 0))
layout_idx = LAYOUT_LIST;
else if ((strcasecmp(layout_name, "selected") == 0))
layout_idx = LAYOUT_SELECTED;
else if ((strcasecmp(layout_name, "rx_graph") == 0))
layout_idx = LAYOUT_RX_GRAPH;
else if ((strcasecmp(layout_name, "tx_graph") == 0))
layout_idx = LAYOUT_TX_GRAPH;
else {
quit("Unknown layout name: '%s'\n", layout_name);
}
struct layout l = { fg_code, bg_code, attr_mask};
cfg_layout[layout_idx] = l;
}
#endif /* __BMON_LAYOUT_H_ */

View File

@ -30,6 +30,7 @@
#include <bmon/element.h>
#include <bmon/element_cfg.h>
#include <bmon/history.h>
#include <bmon/layout.h>
#include <bmon/utils.h>
cfg_t *cfg;
@ -69,6 +70,16 @@ static cfg_opt_t unit_opts[] = {
CFG_END()
};
static cfg_opt_t color_opts[] = {
CFG_STR_LIST("color_pair", "", CFGF_NONE),
CFG_END()
};
static cfg_opt_t layout_opts[] = {
CFG_SEC("color", color_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END()
};
static cfg_opt_t global_opts[] = {
CFG_FLOAT("read_interval", 1.0f, CFGF_NONE),
CFG_FLOAT("rate_interval", 1.0f, CFGF_NONE),
@ -87,6 +98,7 @@ static cfg_opt_t global_opts[] = {
CFG_SEC("attr", attr_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("history", history_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("element", element_opts, CFGF_MULTI | CFGF_TITLE),
CFG_SEC("layout", layout_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END()
};
@ -103,22 +115,26 @@ static char * configfile = NULL;
#if defined HAVE_USE_DEFAULT_COLORS
struct layout cfg_layout[] =
{
{-1, -1, 0}, /* dummy, not used */
{-1, -1, 0}, /* default */
{-1, -1, A_REVERSE}, /* statusbar */
{-1, -1, 0}, /* header */
{-1, -1, 0}, /* list */
{-1, -1, A_REVERSE}, /* selected */
{-1, -1, 0}, /* dummy, not used */
{-1, -1, 0}, /* default */
{-1, -1, A_REVERSE}, /* statusbar */
{-1, -1, 0}, /* header */
{-1, -1, 0}, /* list */
{-1, -1, A_REVERSE}, /* selected */
{-1, -1, 0}, /* RX graph */
{-1, -1, 0}, /* TX graph */
};
#else
struct layout cfg_layout[] =
{
{0, 0, 0}, /* dummy, not used */
{COLOR_BLACK, COLOR_WHITE, 0}, /* default */
{COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* statusbar */
{COLOR_BLACK, COLOR_WHITE, 0}, /* header */
{COLOR_BLACK, COLOR_WHITE, 0}, /* list */
{COLOR_BLACK, COLOR_WHITE, A_REVERSE}, /* selected */
{0, 0, 0}, /* dummy, not used */
{COLOR_WHITE, COLOR_BLACK, 0}, /* default */
{COLOR_BLUE, COLOR_GREEN, A_REVERSE}, /* statusbar */
{COLOR_GREEN, COLOR_BLACK, 0}, /* header */
{COLOR_WHITE, COLOR_BLACK, 0}, /* list */
{COLOR_YELLOW, COLOR_BLACK, A_REVERSE}, /* selected */
{COLOR_GREEN, COLOR_BLACK, 0}, /* RX graph */
{COLOR_RED, COLOR_BLACK, 0}, /* TX graph */
};
#endif
#endif
@ -423,6 +439,41 @@ static void configfile_read_attrs(void)
}
}
static void configfile_read_layout_cfg(void)
{
int i, nlayouts;
cfg_t *lout;
nlayouts = cfg_size(cfg, "layout");
for (i = 0; i < nlayouts; i++)
{
int c, ncolors;
const char *name;
if (!(lout = cfg_getnsec(cfg, "layout", i)))
BUG();
if (!(name = cfg_title(lout)))
BUG();
ncolors = cfg_size(lout, "color");
if (ncolors > LAYOUT_MAX) {
fprintf(stderr, "Warning excceeded maximum number of layouts\n");
ncolors = LAYOUT_MAX;
}
for (c = 0; c < ncolors; c++) {
cfg_t *color_pair;
if (!(color_pair = cfg_getnsec(lout, "color", c)))
BUG();
if (!(name = cfg_title(color_pair)))
BUG();
add_layout(name, color_pair);
}
}
}
static void conf_read(const char *path, int must)
{
int err;
@ -450,6 +501,7 @@ static void conf_read(const char *path, int must)
configfile_read_history();
configfile_read_attrs();
configfile_read_element_cfg();
configfile_read_layout_cfg();
}
static const char default_config[] = \
@ -508,6 +560,29 @@ static const char default_config[] = \
"history day {" \
" interval = 86400.0" \
" size = 60" \
"}"
"layout colors {" \
" color default {" \
" color_pair = { \"white\", \"black\" }" \
" }" \
" color statusbar{" \
" color_pair = { \"blue\", \"white\", \"reverse\" }" \
" }" \
" color header {" \
" color_pair = { \"yellow\", \"black\" }" \
" }" \
" color list {" \
" color_pair = { \"white\", \"black\" }" \
" }" \
" color selected {" \
" color_pair = { \"yellow\", \"black\", \"reverse\" }" \
" }" \
" color rx_graph {" \
" color_pair = { \"green\", \"black\" }" \
" }" \
" color tx_graph {" \
" color_pair = { \"red\", \"black\" }" \
" }" \
"}";
static void conf_read_default(void)
@ -524,6 +599,7 @@ static void conf_read_default(void)
configfile_read_history();
configfile_read_attrs();
configfile_read_element_cfg();
configfile_read_layout_cfg();
}
void configfile_read(void)

View File

@ -420,6 +420,7 @@ static void draw_header(void)
move(row, COLS - strlen(PACKAGE_STRING) - 1);
put_line("%s", PACKAGE_STRING);
move(row, 0);
apply_layout(LAYOUT_LIST);
}
static int lines_required_for_statusbar(void)
@ -632,6 +633,7 @@ static void draw_element(struct element_group *g, struct element *e,
static void draw_group(struct element_group *g, void *arg)
{
apply_layout(LAYOUT_HEADER);
int *line = arg;
if (line_visible(*line)) {
@ -684,7 +686,7 @@ static void draw_graph_centered(struct graph *g, int row, int ncol,
static void draw_table(struct graph *g, struct graph_table *tbl,
struct attr *a, struct history *h,
const char *hdr, int ncol)
const char *hdr, int ncol, int layout)
{
int i, save_row;
char buf[32];
@ -709,11 +711,14 @@ static void draw_table(struct graph *g, struct graph_table *tbl,
//move(row, ncol + g->g_cfg.gc_width - 3);
//put_line("[err %.2f%%]", rtiming.rt_variance.v_error);
memset(buf, 0, strlen(buf));
for (i = (g->g_cfg.gc_height - 1); i >= 0; i--) {
move(++row, ncol);
put_line("%'8.2f %s",
tbl->gt_scale[i],
tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
sprintf(buf, "%'8.2f ", tbl->gt_scale[i]);
addstr(buf);
apply_layout(layout);
put_line("%s", tbl->gt_table + (i * graph_row_size(&g->g_cfg)));
apply_layout(LAYOUT_LIST);
}
move(++row, ncol);
@ -747,14 +752,14 @@ static void draw_history_graph(struct attr *a, struct history *h)
graph_refill(g, h);
save_row = row;
draw_table(g, &g->g_rx, a, h, "RX", ncol);
draw_table(g, &g->g_rx, a, h, "RX", ncol, LAYOUT_RX_GRAPH);
if (graph_display == GRAPH_DISPLAY_SIDE_BY_SIDE) {
ncol = cols / 2;
row = save_row;
}
draw_table(g, &g->g_tx, a, h, "TX", ncol);
draw_table(g, &g->g_tx, a, h, "TX", ncol, LAYOUT_TX_GRAPH);
graph_free(g);
}