зеркало из https://github.com/microsoft/git.git
Merge branch 'js/color-diff'
This commit is contained in:
Коммит
edbda4d6af
|
@ -36,6 +36,9 @@
|
|||
Turn off colored diff, even when the configuration file
|
||||
gives the default to color output.
|
||||
|
||||
--color-words::
|
||||
Show colored word diff, i.e. color words which have changed.
|
||||
|
||||
--no-renames::
|
||||
Turn off rename detection, even when the configuration
|
||||
file gives the default to do so.
|
||||
|
|
178
diff.c
178
diff.c
|
@ -358,12 +358,152 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct diff_words_buffer {
|
||||
mmfile_t text;
|
||||
long alloc;
|
||||
long current; /* output pointer */
|
||||
int suppressed_newline;
|
||||
};
|
||||
|
||||
static void diff_words_append(char *line, unsigned long len,
|
||||
struct diff_words_buffer *buffer)
|
||||
{
|
||||
if (buffer->text.size + len > buffer->alloc) {
|
||||
buffer->alloc = (buffer->text.size + len) * 3 / 2;
|
||||
buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc);
|
||||
}
|
||||
line++;
|
||||
len--;
|
||||
memcpy(buffer->text.ptr + buffer->text.size, line, len);
|
||||
buffer->text.size += len;
|
||||
}
|
||||
|
||||
struct diff_words_data {
|
||||
struct xdiff_emit_state xm;
|
||||
struct diff_words_buffer minus, plus;
|
||||
};
|
||||
|
||||
static void print_word(struct diff_words_buffer *buffer, int len, int color,
|
||||
int suppress_newline)
|
||||
{
|
||||
const char *ptr;
|
||||
int eol = 0;
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
ptr = buffer->text.ptr + buffer->current;
|
||||
buffer->current += len;
|
||||
|
||||
if (ptr[len - 1] == '\n') {
|
||||
eol = 1;
|
||||
len--;
|
||||
}
|
||||
|
||||
fputs(diff_get_color(1, color), stdout);
|
||||
fwrite(ptr, len, 1, stdout);
|
||||
fputs(diff_get_color(1, DIFF_RESET), stdout);
|
||||
|
||||
if (eol) {
|
||||
if (suppress_newline)
|
||||
buffer->suppressed_newline = 1;
|
||||
else
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
|
||||
{
|
||||
struct diff_words_data *diff_words = priv;
|
||||
|
||||
if (diff_words->minus.suppressed_newline) {
|
||||
if (line[0] != '+')
|
||||
putchar('\n');
|
||||
diff_words->minus.suppressed_newline = 0;
|
||||
}
|
||||
|
||||
len--;
|
||||
switch (line[0]) {
|
||||
case '-':
|
||||
print_word(&diff_words->minus, len, DIFF_FILE_OLD, 1);
|
||||
break;
|
||||
case '+':
|
||||
print_word(&diff_words->plus, len, DIFF_FILE_NEW, 0);
|
||||
break;
|
||||
case ' ':
|
||||
print_word(&diff_words->plus, len, DIFF_PLAIN, 0);
|
||||
diff_words->minus.current += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this executes the word diff on the accumulated buffers */
|
||||
static void diff_words_show(struct diff_words_data *diff_words)
|
||||
{
|
||||
xpparam_t xpp;
|
||||
xdemitconf_t xecfg;
|
||||
xdemitcb_t ecb;
|
||||
mmfile_t minus, plus;
|
||||
int i;
|
||||
|
||||
minus.size = diff_words->minus.text.size;
|
||||
minus.ptr = xmalloc(minus.size);
|
||||
memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
|
||||
for (i = 0; i < minus.size; i++)
|
||||
if (isspace(minus.ptr[i]))
|
||||
minus.ptr[i] = '\n';
|
||||
diff_words->minus.current = 0;
|
||||
|
||||
plus.size = diff_words->plus.text.size;
|
||||
plus.ptr = xmalloc(plus.size);
|
||||
memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size);
|
||||
for (i = 0; i < plus.size; i++)
|
||||
if (isspace(plus.ptr[i]))
|
||||
plus.ptr[i] = '\n';
|
||||
diff_words->plus.current = 0;
|
||||
|
||||
xpp.flags = XDF_NEED_MINIMAL;
|
||||
xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
|
||||
xecfg.flags = 0;
|
||||
ecb.outf = xdiff_outf;
|
||||
ecb.priv = diff_words;
|
||||
diff_words->xm.consume = fn_out_diff_words_aux;
|
||||
xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb);
|
||||
|
||||
free(minus.ptr);
|
||||
free(plus.ptr);
|
||||
diff_words->minus.text.size = diff_words->plus.text.size = 0;
|
||||
|
||||
if (diff_words->minus.suppressed_newline) {
|
||||
putchar('\n');
|
||||
diff_words->minus.suppressed_newline = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct emit_callback {
|
||||
struct xdiff_emit_state xm;
|
||||
int nparents, color_diff;
|
||||
const char **label_path;
|
||||
struct diff_words_data *diff_words;
|
||||
};
|
||||
|
||||
static void free_diff_words_data(struct emit_callback *ecbdata)
|
||||
{
|
||||
if (ecbdata->diff_words) {
|
||||
/* flush buffers */
|
||||
if (ecbdata->diff_words->minus.text.size ||
|
||||
ecbdata->diff_words->plus.text.size)
|
||||
diff_words_show(ecbdata->diff_words);
|
||||
|
||||
if (ecbdata->diff_words->minus.text.ptr)
|
||||
free (ecbdata->diff_words->minus.text.ptr);
|
||||
if (ecbdata->diff_words->plus.text.ptr)
|
||||
free (ecbdata->diff_words->plus.text.ptr);
|
||||
free(ecbdata->diff_words);
|
||||
ecbdata->diff_words = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const char *diff_get_color(int diff_use_color, enum color_diff ix)
|
||||
{
|
||||
if (diff_use_color)
|
||||
|
@ -398,12 +538,31 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
|
|||
else {
|
||||
int nparents = ecbdata->nparents;
|
||||
int color = DIFF_PLAIN;
|
||||
for (i = 0; i < nparents && len; i++) {
|
||||
if (line[i] == '-')
|
||||
color = DIFF_FILE_OLD;
|
||||
else if (line[i] == '+')
|
||||
color = DIFF_FILE_NEW;
|
||||
}
|
||||
if (ecbdata->diff_words && nparents != 1)
|
||||
/* fall back to normal diff */
|
||||
free_diff_words_data(ecbdata);
|
||||
if (ecbdata->diff_words) {
|
||||
if (line[0] == '-') {
|
||||
diff_words_append(line, len,
|
||||
&ecbdata->diff_words->minus);
|
||||
return;
|
||||
} else if (line[0] == '+') {
|
||||
diff_words_append(line, len,
|
||||
&ecbdata->diff_words->plus);
|
||||
return;
|
||||
}
|
||||
if (ecbdata->diff_words->minus.text.size ||
|
||||
ecbdata->diff_words->plus.text.size)
|
||||
diff_words_show(ecbdata->diff_words);
|
||||
line++;
|
||||
len--;
|
||||
} else
|
||||
for (i = 0; i < nparents && len; i++) {
|
||||
if (line[i] == '-')
|
||||
color = DIFF_FILE_OLD;
|
||||
else if (line[i] == '+')
|
||||
color = DIFF_FILE_NEW;
|
||||
}
|
||||
set = diff_get_color(ecbdata->color_diff, color);
|
||||
}
|
||||
if (len > 0 && line[len-1] == '\n')
|
||||
|
@ -836,7 +995,12 @@ static void builtin_diff(const char *name_a,
|
|||
ecb.outf = xdiff_outf;
|
||||
ecb.priv = &ecbdata;
|
||||
ecbdata.xm.consume = fn_out_consume;
|
||||
if (o->color_diff_words)
|
||||
ecbdata.diff_words =
|
||||
xcalloc(1, sizeof(struct diff_words_data));
|
||||
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
|
||||
if (o->color_diff_words)
|
||||
free_diff_words_data(&ecbdata);
|
||||
}
|
||||
|
||||
free_ab_and_return:
|
||||
|
@ -1697,6 +1861,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
|
|||
options->xdl_opts |= XDF_IGNORE_WHITESPACE;
|
||||
else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
|
||||
options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
|
||||
else if (!strcmp(arg, "--color-words"))
|
||||
options->color_diff = options->color_diff_words = 1;
|
||||
else if (!strcmp(arg, "--no-renames"))
|
||||
options->detect_rename = 0;
|
||||
else
|
||||
|
|
3
diff.h
3
diff.h
|
@ -46,7 +46,8 @@ struct diff_options {
|
|||
full_index:1,
|
||||
silent_on_remove:1,
|
||||
find_copies_harder:1,
|
||||
color_diff:1;
|
||||
color_diff:1,
|
||||
color_diff_words:1;
|
||||
int context;
|
||||
int break_opt;
|
||||
int detect_rename;
|
||||
|
|
Загрузка…
Ссылка в новой задаче