diff.c: convert word diffing to use emit_diff_symbol

The word diffing is not line oriented and would need some serious effort to be transformed into a line oriented approach, so just go with a symbol DIFF_SYMBOL_WORD_DIFF that is a partial line. Signed-off-by: Stefan Beller <sbeller@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Stefan Beller committed Jun 29, 2017 at 17:07 UTC bd033291d5a3e62979e28fd939dcd8caad510e9c
1 file changed +46 -33
diff.c
+46 -33
@@ -570,6 +570,7 @@ enum diff_symbol {
570 DIFF_SYMBOL_STATS_SUMMARY_ABBREV,
571 DIFF_SYMBOL_STATS_SUMMARY_INSERTS_DELETES,
572 DIFF_SYMBOL_STATS_LINE,
573 + DIFF_SYMBOL_WORD_DIFF,
574 DIFF_SYMBOL_SUBMODULE_ADD,
575 DIFF_SYMBOL_SUBMODULE_DEL,
576 DIFF_SYMBOL_SUBMODULE_UNTRACKED,
@@ -762,6 +763,9 @@ static void emit_diff_symbol(struct diff_options *o, enum diff_symbol s,
763 case DIFF_SYMBOL_STATS_SUMMARY_ABBREV:
764 emit_line(o, "", "", " ...\n", strlen(" ...\n"));
765 break;
766 + case DIFF_SYMBOL_WORD_DIFF:
767 + fprintf(o->file, "%.*s", len, line);
768 + break;
769 default:
770 die("BUG: unknown diff symbol");
771 }
@@ -1092,37 +1096,49 @@ struct diff_words_data {
1096 struct diff_words_style *style;
1097 };
1098
1095 -static int fn_out_diff_words_write_helper(FILE *fp,
1099 +static int fn_out_diff_words_write_helper(struct diff_options *o,
1100 struct diff_words_style_elem *st_el,
1101 const char *newline,
1098 - size_t count, const char *buf,
1099 - const char *line_prefix)
1102 + size_t count, const char *buf)
1103 {
1104 int print = 0;
1105 + struct strbuf sb = STRBUF_INIT;
1106
1107 while (count) {
1108 char *p = memchr(buf, '\n', count);
1109 if (print)
1106 - fputs(line_prefix, fp);
1110 + strbuf_addstr(&sb, diff_line_prefix(o));
1111 +
1112 if (p != buf) {
1108 - if (st_el->color && fputs(st_el->color, fp) < 0)
1109 - return -1;
1110 - if (fputs(st_el->prefix, fp) < 0 ||
1111 - fwrite(buf, p ? p - buf : count, 1, fp) != 1 ||
1112 - fputs(st_el->suffix, fp) < 0)
1113 - return -1;
1114 - if (st_el->color && *st_el->color
1115 - && fputs(GIT_COLOR_RESET, fp) < 0)
1116 - return -1;
1113 + const char *reset = st_el->color && *st_el->color ?
1114 + GIT_COLOR_RESET : NULL;
1115 + if (st_el->color && *st_el->color)
1116 + strbuf_addstr(&sb, st_el->color);
1117 + strbuf_addstr(&sb, st_el->prefix);
1118 + strbuf_add(&sb, buf, p ? p - buf : count);
1119 + strbuf_addstr(&sb, st_el->suffix);
1120 + if (reset)
1121 + strbuf_addstr(&sb, reset);
1122 }
1123 if (!p)
1119 - return 0;
1120 - if (fputs(newline, fp) < 0)
1121 - return -1;
1124 + goto out;
1125 +
1126 + strbuf_addstr(&sb, newline);
1127 count -= p + 1 - buf;
1128 buf = p + 1;
1129 print = 1;
1130 + if (count) {
1131 + emit_diff_symbol(o, DIFF_SYMBOL_WORD_DIFF,
1132 + sb.buf, sb.len, 0);
1133 + strbuf_reset(&sb);
1134 + }
1135 }
1136 +
1137 +out:
1138 + if (sb.len)
1139 + emit_diff_symbol(o, DIFF_SYMBOL_WORD_DIFF,
1140 + sb.buf, sb.len, 0);
1141 + strbuf_release(&sb);
1142 return 0;
1143 }
1144
@@ -1204,24 +1220,20 @@ static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
1220 fputs(line_prefix, diff_words->opt->file);
1221 }
1222 if (diff_words->current_plus != plus_begin) {
1207 - fn_out_diff_words_write_helper(diff_words->opt->file,
1223 + fn_out_diff_words_write_helper(diff_words->opt,
1224 &style->ctx, style->newline,
1225 plus_begin - diff_words->current_plus,
1210 - diff_words->current_plus, line_prefix);
1211 - if (*(plus_begin - 1) == '\n')
1212 - fputs(line_prefix, diff_words->opt->file);
1226 + diff_words->current_plus);
1227 }
1228 if (minus_begin != minus_end) {
1215 - fn_out_diff_words_write_helper(diff_words->opt->file,
1229 + fn_out_diff_words_write_helper(diff_words->opt,
1230 &style->old, style->newline,
1217 - minus_end - minus_begin, minus_begin,
1218 - line_prefix);
1231 + minus_end - minus_begin, minus_begin);
1232 }
1233 if (plus_begin != plus_end) {
1221 - fn_out_diff_words_write_helper(diff_words->opt->file,
1234 + fn_out_diff_words_write_helper(diff_words->opt,
1235 &style->new, style->newline,
1223 - plus_end - plus_begin, plus_begin,
1224 - line_prefix);
1236 + plus_end - plus_begin, plus_begin);
1237 }
1238
1239 diff_words->current_plus = plus_end;
@@ -1315,11 +1327,12 @@ static void diff_words_show(struct diff_words_data *diff_words)
1327
1328 /* special case: only removal */
1329 if (!diff_words->plus.text.size) {
1318 - fputs(line_prefix, diff_words->opt->file);
1319 - fn_out_diff_words_write_helper(diff_words->opt->file,
1330 + emit_diff_symbol(diff_words->opt, DIFF_SYMBOL_WORD_DIFF,
1331 + line_prefix, strlen(line_prefix), 0);
1332 + fn_out_diff_words_write_helper(diff_words->opt,
1333 &style->old, style->newline,
1334 diff_words->minus.text.size,
1322 - diff_words->minus.text.ptr, line_prefix);
1335 + diff_words->minus.text.ptr);
1336 diff_words->minus.text.size = 0;
1337 return;
1338 }
@@ -1342,12 +1355,12 @@ static void diff_words_show(struct diff_words_data *diff_words)
1355 if (diff_words->current_plus != diff_words->plus.text.ptr +
1356 diff_words->plus.text.size) {
1357 if (color_words_output_graph_prefix(diff_words))
1345 - fputs(line_prefix, diff_words->opt->file);
1346 - fn_out_diff_words_write_helper(diff_words->opt->file,
1358 + emit_diff_symbol(diff_words->opt, DIFF_SYMBOL_WORD_DIFF,
1359 + line_prefix, strlen(line_prefix), 0);
1360 + fn_out_diff_words_write_helper(diff_words->opt,
1361 &style->ctx, style->newline,
1362 diff_words->plus.text.ptr + diff_words->plus.text.size
1349 - - diff_words->current_plus, diff_words->current_plus,
1350 - line_prefix);
1363 + - diff_words->current_plus, diff_words->current_plus);
1364 }
1365 diff_words->minus.text.size = diff_words->plus.text.size = 0;
1366 }