Add a "--gauge" option which alters the progress bar to show the current rate as a percentage of the max rate seen, if the size is unknown (#46).
This commit is contained in:
@@ -66,6 +66,7 @@ struct opts_s {
|
||||
bool cursor; /* whether to use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for transfer before display */
|
||||
bool rate_gauge; /* if size unknown, show rate vs max rate */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool null_terminated_lines; /* lines are null-terminated */
|
||||
bool no_display; /* do nothing other than pipe data */
|
||||
|
||||
@@ -123,6 +123,7 @@ struct pvstate_s {
|
||||
bool cursor; /* use cursor positioning */
|
||||
bool numeric; /* numeric output only */
|
||||
bool wait; /* wait for data before display */
|
||||
bool rate_gauge; /* if size unknown, show rate vs max rate */
|
||||
bool linemode; /* count lines instead of bytes */
|
||||
bool bits; /* report bits instead of bytes */
|
||||
bool decimal_units; /* use decimal prefixes */
|
||||
|
||||
@@ -183,6 +183,7 @@ extern void pv_state_show_stats_set(pvstate_t, bool);
|
||||
extern void pv_state_numeric_set(pvstate_t, bool);
|
||||
extern void pv_state_wait_set(pvstate_t, bool);
|
||||
extern void pv_state_delay_start_set(pvstate_t, double);
|
||||
extern void pv_state_rate_gauge_set(pvstate_t, bool);
|
||||
extern void pv_state_linemode_set(pvstate_t, bool);
|
||||
extern void pv_state_bits_set(pvstate_t, bool);
|
||||
extern void pv_state_decimal_units_set(pvstate_t, bool);
|
||||
|
||||
@@ -338,6 +338,9 @@ void display_help(void)
|
||||
{ "-s", "--size", N_("SIZE"),
|
||||
N_("set estimated data size to SIZE bytes"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-g", "--gauge", NULL,
|
||||
N_("if size unknown, show rate vs max rate"),
|
||||
{ 0, 0, 0, 0} },
|
||||
{ "-l", "--line-mode", NULL,
|
||||
N_("count lines instead of bytes"),
|
||||
{ 0, 0, 0, 0} },
|
||||
|
||||
@@ -310,6 +310,7 @@ int main(int argc, char **argv)
|
||||
pv_state_numeric_set(state, opts->numeric);
|
||||
pv_state_wait_set(state, opts->wait);
|
||||
pv_state_delay_start_set(state, opts->delay_start);
|
||||
pv_state_rate_gauge_set(state, opts->rate_gauge);
|
||||
pv_state_linemode_set(state, opts->linemode);
|
||||
pv_state_bits_set(state, opts->bits);
|
||||
pv_state_decimal_units_set(state, opts->decimal_units);
|
||||
|
||||
+5
-1
@@ -283,6 +283,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
{ "wait", 0, NULL, (int) 'W' },
|
||||
{ "delay-start", 1, NULL, (int) 'D' },
|
||||
{ "size", 1, NULL, (int) 's' },
|
||||
{ "gauge", 0, NULL, (int) 'g' },
|
||||
{ "line-mode", 0, NULL, (int) 'l' },
|
||||
{ "null", 0, NULL, (int) '0' },
|
||||
{ "interval", 1, NULL, (int) 'i' },
|
||||
@@ -313,7 +314,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
/*@+nullassign@ */
|
||||
int option_index = 0;
|
||||
#endif /* HAVE_GETOPT_LONG */
|
||||
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:l0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:o:"
|
||||
char *short_options = "hVpteIrab8kTA:fvnqcWD:s:gl0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:o:"
|
||||
#ifdef ENABLE_DEBUGGING
|
||||
"!:"
|
||||
#endif
|
||||
@@ -546,6 +547,9 @@ opts_t opts_parse(unsigned int argc, char **argv)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
opts->rate_gauge = true;
|
||||
break;
|
||||
case 'l':
|
||||
opts->linemode = true;
|
||||
break;
|
||||
|
||||
+54
-20
@@ -607,6 +607,7 @@ bool pv_format(pvstate_t state, bool final)
|
||||
size_t segment;
|
||||
size_t new_display_string_len;
|
||||
const char *formatstr;
|
||||
pv__transfercount_t count_type;
|
||||
|
||||
/* Quick safety check - state must exist. */
|
||||
if (NULL == state)
|
||||
@@ -626,6 +627,13 @@ bool pv_format(pvstate_t state, bool final)
|
||||
if (NULL == formatstr)
|
||||
return false;
|
||||
|
||||
/* Determine the type of thing being counted for transfer, rate, etc. */
|
||||
count_type = PV_TRANSFERCOUNT_BYTES;
|
||||
if (state->control.linemode)
|
||||
count_type = PV_TRANSFERCOUNT_LINES;
|
||||
else if (state->control.decimal_units)
|
||||
count_type = PV_TRANSFERCOUNT_DECBYTES;
|
||||
|
||||
/*
|
||||
* Reallocate output buffer if width changes.
|
||||
*/
|
||||
@@ -745,7 +753,6 @@ bool pv_format(pvstate_t state, bool final)
|
||||
time_t then;
|
||||
struct tm *time_ptr;
|
||||
char *time_format;
|
||||
pv__transfercount_t count_type;
|
||||
|
||||
if (!state->display.component[component_type].required)
|
||||
continue;
|
||||
@@ -766,12 +773,6 @@ bool pv_format(pvstate_t state, bool final)
|
||||
component_content[0] = '\0';
|
||||
component_buf_size = PV_SIZEOF_COMPONENT_STR;
|
||||
|
||||
count_type = PV_TRANSFERCOUNT_BYTES;
|
||||
if (state->control.linemode)
|
||||
count_type = PV_TRANSFERCOUNT_LINES;
|
||||
else if (state->control.decimal_units)
|
||||
count_type = PV_TRANSFERCOUNT_DECBYTES;
|
||||
|
||||
switch (component_type) {
|
||||
|
||||
case PV_COMPONENT_STRING:
|
||||
@@ -1034,27 +1035,54 @@ bool pv_format(pvstate_t state, bool final)
|
||||
if (state->display.component[PV_COMPONENT_PROGRESS].required) {
|
||||
char *component_content;
|
||||
size_t component_buf_size;
|
||||
char pct[16]; /* flawfinder: ignore - only populated by pv_snprintf(). */
|
||||
char after_bar[32]; /* flawfinder: ignore - only populated by pv_snprintf(). */
|
||||
int available_width, bar_length, pad_count;
|
||||
|
||||
component_content = state->display.component[PV_COMPONENT_PROGRESS].content;
|
||||
component_content[0] = '\0';
|
||||
component_buf_size = PV_SIZEOF_COMPONENT_STR;
|
||||
|
||||
memset(pct, 0, sizeof(pct));
|
||||
memset(after_bar, 0, sizeof(after_bar));
|
||||
|
||||
/* The opening of the bar area. */
|
||||
(void) pv_snprintf(component_content, component_buf_size, "[");
|
||||
if (state->control.size > 0 || state->control.rate_gauge) {
|
||||
/*
|
||||
* Known size, or rate gauge mode. Show a bar, and
|
||||
* a percentage (size) or max rate (gauge).
|
||||
*/
|
||||
size_t after_bar_width;
|
||||
int bar_percentage;
|
||||
|
||||
if (state->control.size > 0) {
|
||||
/* Known size; show a bar and a percentage. */
|
||||
size_t pct_width;
|
||||
if (state->control.size > 0) {
|
||||
/* Percentage of data transferred. */
|
||||
bar_percentage = state->calc.percentage;
|
||||
(void) pv_snprintf(after_bar, sizeof(after_bar), " %3ld%%", bar_percentage);
|
||||
} else {
|
||||
/* Current rate vs max rate. */
|
||||
bar_percentage = 0;
|
||||
if (state->calc.rate_max > 0) {
|
||||
bar_percentage =
|
||||
(int) (100.0 * state->calc.transfer_rate / state->calc.rate_max);
|
||||
}
|
||||
|
||||
(void) pv_snprintf(pct, sizeof(pct), "%3ld%%", state->calc.percentage);
|
||||
pct_width = strlen(pct); /* flawfinder: ignore */
|
||||
/*@-mustfreefresh @ */
|
||||
if (state->control.bits && !state->control.linemode) {
|
||||
/* bits per second */
|
||||
pv__sizestr(after_bar, sizeof(after_bar), "/%s",
|
||||
8.0 * state->calc.rate_max, "", _("b/s"), count_type);
|
||||
} else {
|
||||
/* bytes or lines per second */
|
||||
pv__sizestr(after_bar, sizeof(after_bar),
|
||||
"/%s", state->calc.rate_max, _("/s"), _("B/s"), count_type);
|
||||
}
|
||||
/*@+mustfreefresh @ */
|
||||
/* splint: see above about gettext(). */
|
||||
}
|
||||
|
||||
after_bar_width = strlen(after_bar); /* flawfinder: ignore */
|
||||
/* flawfinder: always \0-terminated by pv_snprintf() and the earlier memset(). */
|
||||
|
||||
available_width = (int) (state->control.width) - static_portion_size - (int) (pct_width) - 3;
|
||||
available_width =
|
||||
(int) (state->control.width) - static_portion_size - (int) (after_bar_width) - 2;
|
||||
|
||||
if (available_width < 0)
|
||||
available_width = 0;
|
||||
@@ -1062,8 +1090,11 @@ bool pv_format(pvstate_t state, bool final)
|
||||
if (available_width > (int) (component_buf_size) - 16)
|
||||
available_width = (int) (component_buf_size - 16);
|
||||
|
||||
/* The opening of the bar area. */
|
||||
(void) pv_snprintf(component_content, component_buf_size, "[");
|
||||
|
||||
/* The bar portion. */
|
||||
bar_length = (int) ((available_width * state->calc.percentage) / 100 - 1);
|
||||
bar_length = (int) ((available_width * bar_percentage) / 100 - 1);
|
||||
for (pad_count = 0; pad_count < bar_length; pad_count++) {
|
||||
if (pad_count < available_width)
|
||||
(void) pv_strlcat(component_content, "=", component_buf_size);
|
||||
@@ -1081,8 +1112,8 @@ bool pv_format(pvstate_t state, bool final)
|
||||
}
|
||||
|
||||
/* The closure of the bar area, and the percentage. */
|
||||
(void) pv_strlcat(component_content, "] ", component_buf_size);
|
||||
(void) pv_strlcat(component_content, pct, component_buf_size);
|
||||
(void) pv_strlcat(component_content, "]", component_buf_size);
|
||||
(void) pv_strlcat(component_content, after_bar, component_buf_size);
|
||||
|
||||
} else {
|
||||
/* Unknown size; show a moving indicator. */
|
||||
@@ -1109,6 +1140,9 @@ bool pv_format(pvstate_t state, bool final)
|
||||
if (indicator_position > 100)
|
||||
indicator_position = 200 - indicator_position;
|
||||
|
||||
/* The opening of the bar area. */
|
||||
(void) pv_snprintf(component_content, component_buf_size, "[");
|
||||
|
||||
/* The spaces before the indicator. */
|
||||
for (pad_count = 0; pad_count < (available_width * indicator_position) / 100; pad_count++) {
|
||||
if (pad_count < available_width)
|
||||
|
||||
@@ -270,6 +270,11 @@ void pv_state_delay_start_set(pvstate_t state, double val)
|
||||
state->control.delay_start = val;
|
||||
}
|
||||
|
||||
void pv_state_rate_gauge_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.rate_gauge = val;
|
||||
}
|
||||
|
||||
void pv_state_linemode_set(pvstate_t state, bool val)
|
||||
{
|
||||
state->control.linemode = val;
|
||||
|
||||
Reference in New Issue
Block a user