Junio C Hamano <gitster@xxxxxxxxx> writes: > I haven't tested this at all (this is a lunchtime hack) and have a mild > suspicion that it may have corner case miscounting (e.g. I blindly > subtracts 3 from len when dealing with a line that represents a single > token from the internal diff output --- do I always have 3 there even when > the original file ends with an incomplete line? I didn't check), but > other than that I think this is a lot easier to read and follow. And this adds "--color-words -b" support as an example. The second hunk, however, is a bugfix to the previous one. The code wants the LF at the end of the line always returned as a single token. --- diff.c | 30 +++++++++++++++++++++++++++--- 1 files changed, 27 insertions(+), 3 deletions(-) diff --git a/diff.c b/diff.c index 344aaa6..bce0626 100644 --- a/diff.c +++ b/diff.c @@ -357,6 +357,7 @@ struct emit_callback { struct xdiff_emit_state xm; int nparents, color_diff; unsigned ws_rule; + struct diff_options *diffopt; sane_truncate_fn truncate; const char **label_path; struct diff_words_data *diff_words; @@ -378,19 +379,36 @@ static size_t diff_words_tokenize(struct emit_callback *ecbdata, if (!len) return 0; + /* + * Always return LF at the end as a single separate token. + */ + if ((len == 1) && *line == '\n') + return 1; is_space = isspace(*line); while (len && (isspace(*line) == is_space)) { line++; len--; } + if (is_space && !len) + line--; return line - line0; } +static int token_is_ws_only(char *line, size_t len) +{ + while (len--) + if (!isspace(*line)) + return 0; + return 1; +} + static void diff_words_append(struct emit_callback *ecbdata, char *line, unsigned long len, struct strbuf *text) { + struct diff_options *diffopt = ecbdata->diffopt; + /* Skip leading +/- first. */ line++; len--; @@ -407,9 +425,14 @@ static void diff_words_append(struct emit_callback *ecbdata, * so that we can recover the original * end-of-line easily. Stupid, but works. */ - strbuf_add(text, " ", 1); - strbuf_add(text, line, token_len); - strbuf_add(text, "\n", 1); + if ((diffopt->xdl_opts & XDF_IGNORE_WHITESPACE) && + token_is_ws_only(line, token_len)) { + strbuf_add(text, " \n", 3); + } else { + strbuf_add(text, " ", 1); + strbuf_add(text, line, token_len); + strbuf_add(text, "\n", 1); + } len -= token_len; line += token_len; } else { @@ -1447,6 +1470,7 @@ static void builtin_diff(const char *name_a, ecbdata.found_changesp = &o->found_changes; ecbdata.ws_rule = whitespace_rule(name_b ? name_b : name_a); ecbdata.file = o->file; + ecbdata.diffopt = o; xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; -- 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