ref-filter: introduce ref_formatting_state and ref_formatting_stack

Introduce ref_formatting_state which will hold the formatted output strbuf instead of directly printing to stdout. This will help us in creating modifier atoms which modify the format specified before printing to stdout. Implement a stack machinery for ref_formatting_state, this allows us to push and pop elements onto the stack. Whenever we pop an element from the stack, the strbuf from that element is appended to the strbuf of the next element on the stack, this will allow us to support nesting of modifier atoms. Rename some functions to reflect the changes made: print_value() -> append_atom() emit() -> append_literal() Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored-by: Matthieu Moy <matthieu.moy@grenoble-inp.fr> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Karthik Nayak committed Sep 10, 2015 at 21:18 UTC 574e96a2418cce16934f2b6e20a0af5ff5f85c92
1 file changed +59 -19
ref-filter.c
+59 -19
@@ -55,6 +55,18 @@ static struct {
55 { "color" },
56 };
57
58 +#define REF_FORMATTING_STATE_INIT { 0, NULL }
59 +
60 +struct ref_formatting_stack {
61 + struct ref_formatting_stack *prev;
62 + struct strbuf output;
63 +};
64 +
65 +struct ref_formatting_state {
66 + int quote_style;
67 + struct ref_formatting_stack *stack;
68 +};
69 +
70 struct atom_value {
71 const char *s;
72 unsigned long ul; /* used for sorting when not FIELD_STR */
@@ -129,6 +141,27 @@ int parse_ref_filter_atom(const char *atom, const char *ep)
141 return at;
142 }
143
144 +static void push_stack_element(struct ref_formatting_stack **stack)
145 +{
146 + struct ref_formatting_stack *s = xcalloc(1, sizeof(struct ref_formatting_stack));
147 +
148 + strbuf_init(&s->output, 0);
149 + s->prev = *stack;
150 + *stack = s;
151 +}
152 +
153 +static void pop_stack_element(struct ref_formatting_stack **stack)
154 +{
155 + struct ref_formatting_stack *current = *stack;
156 + struct ref_formatting_stack *prev = current->prev;
157 +
158 + if (prev)
159 + strbuf_addbuf(&prev->output, &current->output);
160 + strbuf_release(&current->output);
161 + free(current);
162 + *stack = prev;
163 +}
164 +
165 /*
166 * In a format string, find the next occurrence of %(atom).
167 */
@@ -1195,30 +1228,27 @@ void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array)
1228 qsort(array->items, array->nr, sizeof(struct ref_array_item *), compare_refs);
1229 }
1230
1198 -static void print_value(struct atom_value *v, int quote_style)
1231 +static void append_atom(struct atom_value *v, struct ref_formatting_state *state)
1232 {
1200 - struct strbuf sb = STRBUF_INIT;
1201 - switch (quote_style) {
1233 + struct strbuf *s = &state->stack->output;
1234 +
1235 + switch (state->quote_style) {
1236 case QUOTE_NONE:
1203 - fputs(v->s, stdout);
1237 + strbuf_addstr(s, v->s);
1238 break;
1239 case QUOTE_SHELL:
1206 - sq_quote_buf(&sb, v->s);
1240 + sq_quote_buf(s, v->s);
1241 break;
1242 case QUOTE_PERL:
1209 - perl_quote_buf(&sb, v->s);
1243 + perl_quote_buf(s, v->s);
1244 break;
1245 case QUOTE_PYTHON:
1212 - python_quote_buf(&sb, v->s);
1246 + python_quote_buf(s, v->s);
1247 break;
1248 case QUOTE_TCL:
1215 - tcl_quote_buf(&sb, v->s);
1249 + tcl_quote_buf(s, v->s);
1250 break;
1251 }
1218 - if (quote_style != QUOTE_NONE) {
1219 - fputs(sb.buf, stdout);
1220 - strbuf_release(&sb);
1221 - }
1252 }
1253
1254 static int hex1(char ch)
@@ -1239,8 +1269,10 @@ static int hex2(const char *cp)
1269 return -1;
1270 }
1271
1242 -static void emit(const char *cp, const char *ep)
1272 +static void append_literal(const char *cp, const char *ep, struct ref_formatting_state *state)
1273 {
1274 + struct strbuf *s = &state->stack->output;
1275 +
1276 while (*cp && (!ep || cp < ep)) {
1277 if (*cp == '%') {
1278 if (cp[1] == '%')
@@ -1248,13 +1280,13 @@ static void emit(const char *cp, const char *ep)
1280 else {
1281 int ch = hex2(cp + 1);
1282 if (0 <= ch) {
1251 - putchar(ch);
1283 + strbuf_addch(s, ch);
1284 cp += 3;
1285 continue;
1286 }
1287 }
1288 }
1257 - putchar(*cp);
1289 + strbuf_addch(s, *cp);
1290 cp++;
1291 }
1292 }
@@ -1262,19 +1294,24 @@ static void emit(const char *cp, const char *ep)
1294 void show_ref_array_item(struct ref_array_item *info, const char *format, int quote_style)
1295 {
1296 const char *cp, *sp, *ep;
1297 + struct strbuf *final_buf;
1298 + struct ref_formatting_state state = REF_FORMATTING_STATE_INIT;
1299 +
1300 + state.quote_style = quote_style;
1301 + push_stack_element(&state.stack);
1302
1303 for (cp = format; *cp && (sp = find_next(cp)); cp = ep + 1) {
1304 struct atom_value *atomv;
1305
1306 ep = strchr(sp, ')');
1307 if (cp < sp)
1271 - emit(cp, sp);
1308 + append_literal(cp, sp, &state);
1309 get_ref_atom_value(info, parse_ref_filter_atom(sp + 2, ep), &atomv);
1273 - print_value(atomv, quote_style);
1310 + append_atom(atomv, &state);
1311 }
1312 if (*cp) {
1313 sp = cp + strlen(cp);
1277 - emit(cp, sp);
1314 + append_literal(cp, sp, &state);
1315 }
1316 if (need_color_reset_at_eol) {
1317 struct atom_value resetv;
@@ -1283,8 +1320,11 @@ void show_ref_array_item(struct ref_array_item *info, const char *format, int qu
1320 if (color_parse("reset", color) < 0)
1321 die("BUG: couldn't parse 'reset' as a color");
1322 resetv.s = color;
1286 - print_value(&resetv, quote_style);
1323 + append_atom(&resetv, &state);
1324 }
1325 + final_buf = &state.stack->output;
1326 + fwrite(final_buf->buf, 1, final_buf->len, stdout);
1327 + pop_stack_element(&state.stack);
1328 putchar('\n');
1329 }
1330