On Mon, Jul 20, 2015 at 10:59 PM, Junio C Hamano <gitster@xxxxxxxxx> wrote: > Junio C Hamano <gitster@xxxxxxxxx> writes: > >> Your caller is iterating over the elements in a format string, >> e.g. 'A %(align:20)%(foo) B %(bar) C', and its caller is iterating >> over a list of refs, e.g. 'maint', 'master' branches. With that >> format string, as long as %(foo) does not expand to something that >> exceeds 20 display places or so, I'd expect literal 'B' for all refs >> to align, but I do not think this code gives me that; what happens >> if '%(foo)' happens to be an empty string for 'maint' but is a >> string, say 'x', for 'master'? > > Having looked at the caller once again, I have to say that the > interface to this function is poorly designed. 'info' might have > been a convenient place to keep the "formatting state" during this > loop (e.g. "was the previous atom tell us to format this atom in a > special way and if so how?"), but that state does not belong to the > 'info' thing we are getting from our caller. It is something we'd > want to clear before we come into the for() loop, and mutate and > utilize while in the loop. For example, if the caller ever wants > to show the same ref twice by calling this function with the same > ref twice, and if the format string ended with %(align:N), you do > not want that leftover state to right-pad the first atom in the > second invocation. You do have a point, my current implementation won't work with the scenario you just mentioned. > > Imagine that in the future you might want to affect how things are > formatted based on how much we have already output for the ref so > far (e.g. limiting the total line length). Where would you implement > such a feature and hook it in this loop? > > I'd imagine that a sensible way to organize and structure the > codeflow to support this "align" and related enhancement we may want > to have in the future cleanly would be to teach "print_value" about > the "formatting state" and share it with this loop. Roughly... > >> void show_ref_array_item(struct ref_array_item *info, const char *format, int quote_style) >> { >> const char *cp, *sp, *ep; >> > > Insert something like this here: > > struct ref_formatting_state state; > > memset(&state, 0, sizeof(state)); > state.quote_style = quote_style; > >> for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) { >> struct atom_value *atomv; >> + int parsed_atom; >> >> ep = strchr(sp, ')'); >> if (cp < sp) >> emit(cp, sp); >> - get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv); >> + parsed_atom = parse_ref_filter_atom(sp + 2, ep); >> + get_ref_atom_value(info, parsed_atom, &atomv); >> + assign_formating(info, parsed_atom, atomv); >> print_value(atomv, quote_style); > > and replace all of the above with something like this (a separate > variable parsed_atom may not be necessary): > > get_ref_atom_value(&state, info, > parse_ref_filter_atom(sp + 2, ep), &atomv); > print_value(&state, atomv); > > Things like %(align:20) are not really atoms in the sense that they > are not used as placeholders for attributes that refs being printed > have, but they are there solely in order to affect the "formating > state". Introduce a new field "struct atom_value.pseudo_atom" to > tell print_value() that fact from get_ref_atom_value(), e.g. > > static void print_value(struct ref_formatting_state *state, > struct atom_value *v) > { > struct strbuf value = STRBUF_INIT; > struct strbuf formatted = STRBUF_INIT; > > if (v->pseudo_atom) > return; > if (state->pad_to_right) { > strbuf_addf(&value, "%.*s", state->pad_to_right, v->s); > state->pad_to_right = 0; > } > switch (state->quote_style) { > case QUOTE_SHELL: > sq_quote_buf(&formatted, value.buf); > break; > ... > } > fputs(formatted.buf, stdout); > strbuf_release(&value); > strbuf_release(&formatted); > } > > or something like that. As this print_value() knows everything that > happens to a single output line during that loop and is allowed to > keep track of what it sees in 'state', this would give a natural and > codeflow to add 'limit the total line length' and things like that > if desired. This implementation looks good. Will include this, thanks a bunch. > > We may want to further clean up to update %(color) thing to clarify > that it is a pseudo atom. I suspect %(align:20)%(color:blue) would > do a wrong thing with the current code, and it would be a reasonable > thing to allow both of these interchangeably: > > %(align:20)%(color:blue)%(refname:short)%(color:reset) > %(color:blue)%(align:20)%(refname:short)%(color:reset) > > and implementation of that would become more obvious once you have a > more explicit "formatting state" that is known to and shared among > get_value(), the for() loop that walks the format string, and > print_value(). Yup! ill put in a fix for %(color:<color>) with this patch. Thanks a lot. -- Regards, Karthik Nayak -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html