From: "Zbigniew Jędrzejewski-Szmek" <zbyszek@in.waw.pl>
To: Lucian Poston <lucian.poston@gmail.com>
Cc: git@vger.kernel.org, Junio C Hamano <gitster@pobox.com>
Subject: Re: [PATCH v2 2/3] Adjust stat width calculations to take --graph output into account
Date: Thu, 12 Apr 2012 12:17:11 +0200 [thread overview]
Message-ID: <4F86ABA7.8080703@in.waw.pl> (raw)
In-Reply-To: <CACz_eyc0AjvU0U2FGzqhUTZ_nncuFoAxZ6VGw0=7LVXH4SLqwA@mail.gmail.com>
On 04/12/2012 09:47 AM, Lucian Poston wrote:
> On Fri, Mar 23, 2012 at 03:12, Zbigniew Jędrzejewski-Szmek
> <zbyszek@in.waw.pl> wrote:
>> On 03/23/2012 06:54 AM, Lucian Poston wrote:
>>
>>> diff --git a/diff.c b/diff.c
>>> index 377ec1e..31ba10c 100644
>>> --- a/diff.c
>>> +++ b/diff.c
>>> @@ -1383,6 +1383,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>>> int width, name_width, graph_width, number_width = 4, count;
>>> const char *reset, *add_c, *del_c;
>>> const char *line_prefix = "";
>>> + int line_prefix_length = 0;
>>> + int reserved_character_count;
>>> int extra_shown = 0;
>>> struct strbuf *msg = NULL;
>>>
>>> @@ -1392,6 +1394,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>>> if (options->output_prefix) {
>>> msg = options->output_prefix(options, options->output_prefix_data);
>>> line_prefix = msg->buf;
>>> + line_prefix_length = options->output_prefix_length;
>>> }
>> Hi,
>> line_prefix will only be used once. And options->output_prefix_length will
>> be 0 if !options->output_prefix, so line_prefix variable can be eliminated
>> and options->output_prefix_length used directly instead.
>
> Rather than adding the line_prefix_length variable, the next patch
> will use options->output_prefix_length directly.
>
>>> count = options->stat_count ? options->stat_count : data->nr;
>>> @@ -1427,37 +1430,46 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>>> * We have width = stat_width or term_columns() columns total.
>>> * We want a maximum of min(max_len, stat_name_width) for the name part.
>>> * We want a maximum of min(max_change, stat_graph_width) for the +- part.
>>> - * We also need 1 for " " and 4 + decimal_width(max_change)
>>> - * for " | NNNN " and one the empty column at the end, altogether
>>> + * Each line needs space for the following characters:
>>> + * - 1 for the initial " "
>>> + * - 4 + decimal_width(max_change) for " | NNNN "
>>> + * - 1 for the empty column at the end,
>>> + * Altogether, the reserved_character_count totals
>>> * 6 + decimal_width(max_change).
>>> *
>>> - * If there's not enough space, we will use the smaller of
>>> - * stat_name_width (if set) and 5/8*width for the filename,
>>> - * and the rest for constant elements + graph part, but no more
>>> - * than stat_graph_width for the graph part.
>>> - * (5/8 gives 50 for filename and 30 for the constant parts + graph
>>> - * for the standard terminal size).
>>> + * Additionally, there may be a line_prefix, which reduces the available
>>> + * width by line_prefix_length.
>>> + *
>>> + * If there's not enough space, we will use the smaller of stat_name_width
>>> + * (if set) and 5/8*width for the filename, and the rest for the graph
>>> + * part, but no more than stat_graph_width for the graph part.
>>> + * Assuming the line prefix is empty, on a standard 80 column terminal
>>> + * this ratio results in 50 characters for the filename and 20 characters
>>> + * for the graph (plus the 10 reserved characters).
>>> *
>>> * In other words: stat_width limits the maximum width, and
>>> * stat_name_width fixes the maximum width of the filename,
>>> * and is also used to divide available columns if there
>>> * aren't enough.
>>> */
>>> + reserved_character_count = 6 + number_width;
>>>
>>> if (options->stat_width == -1)
>>> width = term_columns();
>>> else
>>> width = options->stat_width ? options->stat_width : 80;
>>>
>>> + width -= line_prefix_length;
>>> +
>>> if (options->stat_graph_width == -1)
>>> options->stat_graph_width = diff_stat_graph_width;
>>>
>>> /*
>>> - * Guarantee 3/8*16==6 for the graph part
>>> - * and 5/8*16==10 for the filename part
>>> + * Guarantees at least 6 characters for the graph part [16 * 3/8]
>>> + * and at least 10 for the filename part [16 * 5/8]
>>> */
>>> - if (width< 16 + 6 + number_width)
>>> - width = 16 + 6 + number_width;
>>> + if (width< 16 + reserved_character_count)
>>> + width = 16 + reserved_character_count;
>>>
>>> /*
>>> * First assign sizes that are wanted, ignoring available width.
>>> @@ -1472,16 +1484,36 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
>>> /*
>>> * Adjust adjustable widths not to exceed maximum width
>>> */
>>
>> In this part below, you add gratuitous braces around single line if-blocks.
>> This makes the code (and the diff) longer with no gain.
>
> I prefer gratuitous braces, particularly when conditionals are nested
> as they are here. It helps later when maintaining the code if someone
> wants to add a debug statement or comment out a line.
>
> I'll remove braces from single line conditionals to keep with the
> existing conventions.
Thanks.
>>> - if (name_width + number_width + 6 + graph_width> width) {
>>> - if (graph_width> width * 3/8 - number_width - 6)
>>> - graph_width = width * 3/8 - number_width - 6;
>>> + if (reserved_character_count + name_width + graph_width> width) {
>>> + /*
>>> + * Reduce graph_width to be at most 3/8 of the unreserved space and no
>>> + * less than 6, which leaves at least 5/8 for the filename.
>>> + */
>>> + if (graph_width> width * 3/8 - reserved_character_count) {
>>> + graph_width = width * 3/8 - reserved_character_count;
>>> + if (graph_width< 6) {
>>> + graph_width = 6;
>>> + }
>>> + }
>> This extra test is not necessary. Above, after /* Guarantees at least 6 characters
>> for the graph part [16 * 3/8] ... */, this should already by so that
>> (width * 3/8 - reserved_character_count) is at least 6.
>
> Ahh, this is because the calculations go haywire when the number of
> columns is small. I briefly mentioned it here:
> http://thread.gmane.org/gmane.comp.version-control.git/193694/focus=193744
>
> graph_width actually can have a negative value under certain
> conditions, and this check compensates for that edge case. My earlier
> patches took a less conservative approach and adjusted the
> calculations so that the value of graph_width would be at least 6, but
> it caused several tests to regress. Since the intention of the
> original graph_width calculation was place a lower bound of 6 on its
> value, I simply enforce that here without affecting the general cases,
> which will remain unmodified in order to prevent test regressions.
>
>>> +
>>> + /*
>>> + * If the remaining unreserved space will not accomodate the
>>> + * filenames, adjust name_width to use all available remaining space.
>>> + * Otherwise, assign any extra space to graph_width.
>>> + */
>>> + if (name_width> width - reserved_character_count - graph_width) {
>>> + name_width = width - reserved_character_count - graph_width;
>>> + } else {
>>> + graph_width = width - reserved_character_count - name_width;
>>> + }
>>> +
>>> + /*
>>> + * If stat-graph-width was specified, limit graph_width to its value.
>>> + */
>>> if (options->stat_graph_width&&
>>> - graph_width> options->stat_graph_width)
>>> + graph_width> options->stat_graph_width) {
>>> graph_width = options->stat_graph_width;
>>> - if (name_width> width - number_width - 6 - graph_width)
>>> - name_width = width - number_width - 6 - graph_width;
>>> - else
>>> - graph_width = width - number_width - 6 - name_width;
>>> + }
>> Here, the order of the two tests
>> (1) if (options->stat_graph_width&& graph_width> options->stat_graph_width)
>> (2) if (name_width> width - number_width - 6 - graph_width)
>> is reversed. This is not OK, because this means that
>> options->stat_graph_width will be used unconditionally, while
>> before it was subject to limiting by total width.
>
> If options->stat_graph_width is specified, it should always limit the
> value of graph_width, correct? Since (1) is the last test, it can only
> decrease the value of graph_width, which would already be limited by
> the total width.
Right, but the way the tests are ordered now, we could end up decreasing
name_width first (after (2)) and then graph_width (after (1)), actually
using less than full width.
> I just noticed that name_width isn't being limited to stat_name_width,
> if it is specified. I'll add a check for that.
Sounds good.
>> The tests:
>> After the new tests are added, I see:
>>
>> ok 53 - format-patch ignores COLUMNS (long filename)
>> ok 54 - diff respects COLUMNS (long filename)
>> ok 55 - show respects COLUMNS (long filename)
>> ok 56 - log respects COLUMNS (long filename)
>> ok 57 - show respects 80 COLUMNS (long filename)<=======
>> ok 58 - log respects 80 COLUMNS (long filename)<-------
>> ok 59 - show respects 80 COLUMNS (long filename)<=======
>> ok 60 - log respects 80 COLUMNS (long filename)<-------
>>
>> So some tests descriptions are duplicated. Also it would be
>> nice to test with --graph in more places. I'm attaching a
>> replacement patch which adds more tests. It should go *before*
>> your series, and your series should tweak the tests to pass,
>> showing what changed.
>
> Thanks, I'll add these.
Regards,
Zbyszek
next prev parent reply other threads:[~2012-04-12 10:17 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-22 19:27 [PATCH v2 1/3] Add output_prefix_length to diff_options Lucian Poston
2012-03-22 19:27 ` [PATCH v2 2/3] Adjust stat width calculations to take --graph output into account Lucian Poston
2012-03-22 20:28 ` Zbigniew Jędrzejewski-Szmek
2012-03-23 4:38 ` Lucian Poston
2012-03-22 20:45 ` Junio C Hamano
2012-03-23 4:44 ` Lucian Poston
2012-03-23 5:54 ` Lucian Poston
2012-03-23 10:12 ` Zbigniew Jędrzejewski-Szmek
2012-04-12 7:47 ` Lucian Poston
2012-04-12 10:17 ` Zbigniew Jędrzejewski-Szmek [this message]
2012-04-16 11:04 ` Lucian Poston
2012-03-23 18:13 ` Junio C Hamano
2012-04-12 8:35 ` Lucian Poston
2012-03-22 19:27 ` [PATCH v2 3/3] t4052: Test that stat width is adjusted for prefixes Lucian Poston
2012-03-23 5:57 ` Lucian Poston
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4F86ABA7.8080703@in.waw.pl \
--to=zbyszek@in.waw.pl \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=lucian.poston@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.