git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).