diff --git a/docs/ACKNOWLEDGEMENTS.md b/docs/ACKNOWLEDGEMENTS.md index 781d458..5fa3381 100644 --- a/docs/ACKNOWLEDGEMENTS.md +++ b/docs/ACKNOWLEDGEMENTS.md @@ -98,5 +98,6 @@ is acknowledged and greatly appreciated: * [jettero](https://codeberg.org/jettero) - reported double-free coredump when using "`--watchfd`" after 1.8.10 ([#96](https://codeberg.org/a-j-wood/pv/issues/96)) * Hartmut Goebel - provided a full set of new German translations ([#98](https://codeberg.org/a-j-wood/pv/pulls/98)) * Venky.N.Iyer - suggested "`--stats`" ([#49](https://codeberg.org/a-j-wood/pv/issues/49)) + * Roland Kletzing - suggested "`--rate`" with "`--numeric`" ([#17](https://codeberg.org/a-j-wood/pv/issues/17)) --- diff --git a/docs/NEWS.md b/docs/NEWS.md index 51480de..66e0423 100644 --- a/docs/NEWS.md +++ b/docs/NEWS.md @@ -1,6 +1,7 @@ ### UNRELEASED * feature: new "`--stats`" option to show transfer stats at the end, like "`ping`" ([#49](https://codeberg.org/a-j-wood/pv/issues/49)) + * feature: "`--rate`" can now be used with "`--numeric`" ([#17](https://codeberg.org/a-j-wood/pv/issues/17)) * i18n: complete set of German translations supplied by Hartmut Goebel ([#98](https://codeberg.org/a-j-wood/pv/pulls/98)) * fix: resume stopped pipelines when running in the background (part of [#56](https://codeberg.org/a-j-wood/pv/issues/56)) * fix: write UTC timestamps in debugging mode to avoid lockups in signal handlers diff --git a/docs/pv.1 b/docs/pv.1 index a84f905..534ae68 100644 --- a/docs/pv.1 +++ b/docs/pv.1 @@ -214,7 +214,7 @@ is not required if is being used. .TP .B "" -Note that if +If .B \-\-numeric is in use, then adding .B \-\-bytes @@ -226,12 +226,16 @@ is also in use as well as and .BR \-\-numeric , then instead of bytes or a percentage, the number of lines -so far is output. And finally, if +so far is output. If +.B \-\-rate +is added, then the transfer rate is also output (if +.B \-\-bytes +is in use as well, the rate comes after the byte/line count). +If .B \-\-timer -is added to -.BR \-\-numeric , -then each output line is prefixed with the elapsed time -so far, as a decimal number of seconds. +is also added, then each output line is +.I prefixed +with the elapsed time so far, as a decimal number of seconds. .TP .B \-q, \-\-quiet No output. Useful if the diff --git a/docs/pv.1.md b/docs/pv.1.md index 4d87e34..40e61ef 100644 --- a/docs/pv.1.md +++ b/docs/pv.1.md @@ -158,14 +158,15 @@ that are explicitly switched on will be shown. **dialog**(1). Note that **-f** is not required if **-n** is being used. -: Note that if **\--numeric** is in use, then adding **\--bytes** will - cause the number of bytes processed so far to be output instead of a +: If **\--numeric** is in use, then adding **\--bytes** will cause the + number of bytes processed so far to be output instead of a percentage; if **\--line-mode** is also in use as well as **\--bytes** and **\--numeric**, then instead of bytes or a - percentage, the number of lines so far is output. And finally, if - **\--timer** is added to **\--numeric**, then each output line is - prefixed with the elapsed time so far, as a decimal number of - seconds. + percentage, the number of lines so far is output. If **\--rate** is + added, then the transfer rate is also output (if **\--bytes** is in + use as well, the rate comes after the byte/line count). If + **\--timer** is also added, then each output line is *prefixed* with + the elapsed time so far, as a decimal number of seconds. **-q, \--quiet** diff --git a/src/pv/display.c b/src/pv/display.c index dbc1de1..8e2d1c7 100644 --- a/src/pv/display.c +++ b/src/pv/display.c @@ -662,40 +662,67 @@ bool pv_format(pvstate_t state, bool final) } /* - * In numeric output mode, our output is just a number. + * In numeric output mode, our output is just the percentage + * completion, as a number by itself. * - * Patch from Sami Liedes: - * With --timer we prefix the output with the elapsed time. - * With --bytes we output the bytes transferred so far instead - * of the percentage. (Or lines, if --lines was given with --bytes). + * With --timer, we prefix the output with the elapsed time. + * + * With --bytes, we output the bytes transferred so far instead of + * the percentage (or we output the number lines transferred, if + * --lines was given with --bytes). + * + * With --rate was given, we output the current transfer rate + * instead of the percentage. With --bytes as well, the rate is + * given after the bytes/lines. */ if (state->control.numeric) { - char numericprefix[128]; /* flawfinder: ignore - only populated by pv_snprintf(). */ + char msg_timer[128]; /* flawfinder: ignore */ + char msg_bytes[128]; /* flawfinder: ignore */ + char msg_rate[128]; /* flawfinder: ignore */ + char msg_percent[128]; /* flawfinder: ignore */ + bool first_item, show_percentage; - numericprefix[0] = '\0'; + /* flawfinder: each buffer is kept safe by pv_snprintf(). */ - if (state->display.component[PV_COMPONENT_TIMER].required) - (void) pv_snprintf(numericprefix, sizeof(numericprefix), "%.4Lf ", + first_item = true; + show_percentage = true; + + msg_timer[0] = '\0'; + if (state->display.component[PV_COMPONENT_TIMER].required) { + (void) pv_snprintf(msg_timer, sizeof(msg_timer), "%s%.4Lf", first_item ? "" : " ", state->transfer.elapsed_seconds); - - if (state->display.component[PV_COMPONENT_BYTES].required) { - if (state->control.bits) { - (void) pv_snprintf(state->display.display_buffer, - state->display.display_buffer_size, - "%.99s%lld\n", numericprefix, - (long long) (8 * state->transfer.total_written)); - } else { - (void) pv_snprintf(state->display.display_buffer, - state->display.display_buffer_size, - "%.99s%lld\n", numericprefix, - (long long) (state->transfer.total_written)); - } - } else { - (void) pv_snprintf(state->display.display_buffer, - state->display.display_buffer_size, "%.99s%ld\n", numericprefix, - (long) (state->calc.percentage)); + first_item = false; } + msg_bytes[0] = '\0'; + if (state->display.component[PV_COMPONENT_BYTES].required) { + (void) pv_snprintf(msg_bytes, sizeof(msg_bytes), + "%s%lld", first_item ? "" : " ", + (long long) ((state->control.bits ? 8 : 1) * state->transfer.total_written)); + first_item = false; + show_percentage = false; + } + + msg_rate[0] = '\0'; + if (state->display.component[PV_COMPONENT_RATE].required) { + (void) pv_snprintf(msg_rate, sizeof(msg_rate), + "%s%.4Lf", first_item ? "" : " ", + ((state->control.bits ? 8.0 : 1.0) * state->calc.transfer_rate)); + first_item = false; + show_percentage = false; + } + + msg_percent[0] = '\0'; + if (show_percentage) { + (void) pv_snprintf(msg_percent, sizeof(msg_percent), + "%s%d", first_item ? "" : " ", state->calc.percentage); + first_item = false; + } + + (void) pv_snprintf(state->display.display_buffer, + state->display.display_buffer_size, "%.39s%.39s%.39s%.39s\n", msg_timer, msg_bytes, + msg_rate, msg_percent); + state->display.display_string_len = strlen(state->display.display_buffer); /* flawfinder: ignore */ /* flawfinder: always \0 terminated by pv_snprintf(). */ @@ -953,10 +980,10 @@ bool pv_format(pvstate_t state, bool final) /* Transfer buffer percentage utilisation. */ if (state->transfer.buffer_size > 0) { int pct_used = pv_percentage((off_t) - (state->transfer.read_position - - state->transfer.write_position), - (off_t) - (state->transfer.buffer_size)); + (state->transfer.read_position - + state->transfer.write_position), + (off_t) + (state->transfer.buffer_size)); (void) pv_snprintf(component_content, component_buf_size, "{%3d%%}", pct_used); } #ifdef HAVE_SPLICE