Mercurial > vim
comparison src/diff.c @ 34324:6d9f59e88fc2 v9.1.0096
patch 9.1.0096: diff() function uses 'diffexpr'
Commit: https://github.com/vim/vim/commit/be156a31c5400eb12025e480c477b1df88244801
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sun Feb 11 17:08:29 2024 +0100
patch 9.1.0096: diff() function uses 'diffexpr'
Problem: diff() function uses 'diffexpr'
(rickhowe)
Solution: Make diff() always use internal diff(), add support for
unified diff context length, sort diff() options in help
(Yegappan Lakshmanan)
fixes: #13989
closes: #14010
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 11 Feb 2024 17:15:05 +0100 |
parents | 3a5750596c3d |
children | 7ccaadd7cf0b |
comparison
equal
deleted
inserted
replaced
34323:857f6a19ca6a | 34324:6d9f59e88fc2 |
---|---|
40 #define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL) | 40 #define ALL_WHITE_DIFF (DIFF_IWHITE | DIFF_IWHITEALL | DIFF_IWHITEEOL) |
41 static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF; | 41 static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF; |
42 | 42 |
43 static long diff_algorithm = 0; | 43 static long diff_algorithm = 0; |
44 | 44 |
45 #define DIFF_INTERNAL_OUTPUT_UNIFIED 1 | |
46 #define DIFF_INTERNAL_OUTPUT_INDICES 2 | |
47 static int diff_internal_output_fmt = DIFF_INTERNAL_OUTPUT_INDICES; | |
48 | |
49 #define LBUFLEN 50 // length of line in diff file | 45 #define LBUFLEN 50 // length of line in diff file |
50 | 46 |
51 static int diff_a_works = MAYBE; // TRUE when "diff -a" works, FALSE when it | 47 static int diff_a_works = MAYBE; // TRUE when "diff -a" works, FALSE when it |
52 // doesn't work, MAYBE when not checked yet | 48 // doesn't work, MAYBE when not checked yet |
53 #if defined(MSWIN) | 49 #if defined(MSWIN) |
74 long count_orig; | 70 long count_orig; |
75 linenr_T lnum_new; | 71 linenr_T lnum_new; |
76 long count_new; | 72 long count_new; |
77 } diffhunk_T; | 73 } diffhunk_T; |
78 | 74 |
75 typedef enum { | |
76 DIO_OUTPUT_INDICES = 0, // default | |
77 DIO_OUTPUT_UNIFIED = 1 // unified diff format | |
78 } dio_outfmt_T; | |
79 | |
79 // two diff inputs and one result | 80 // two diff inputs and one result |
80 typedef struct { | 81 typedef struct { |
81 diffin_T dio_orig; // original file input | 82 diffin_T dio_orig; // original file input |
82 diffin_T dio_new; // new file input | 83 diffin_T dio_new; // new file input |
83 diffout_T dio_diff; // diff result | 84 diffout_T dio_diff; // diff result |
84 int dio_internal; // using internal diff | 85 int dio_internal; // using internal diff |
86 dio_outfmt_T dio_outfmt; // internal diff output format | |
87 int dio_ctxlen; // unified diff context length | |
85 } diffio_T; | 88 } diffio_T; |
86 | 89 |
87 static int diff_buf_idx(buf_T *buf); | 90 static int diff_buf_idx(buf_T *buf); |
88 static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp); | 91 static int diff_buf_idx_tp(buf_T *buf, tabpage_T *tp); |
89 static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, long amount_after); | 92 static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T line2, long amount, long amount_after); |
1143 if (diff_flags & DIFF_IWHITEEOL) | 1146 if (diff_flags & DIFF_IWHITEEOL) |
1144 param.flags |= XDF_IGNORE_WHITESPACE_AT_EOL; | 1147 param.flags |= XDF_IGNORE_WHITESPACE_AT_EOL; |
1145 if (diff_flags & DIFF_IBLANK) | 1148 if (diff_flags & DIFF_IBLANK) |
1146 param.flags |= XDF_IGNORE_BLANK_LINES; | 1149 param.flags |= XDF_IGNORE_BLANK_LINES; |
1147 | 1150 |
1148 emit_cfg.ctxlen = 0; // don't need any diff_context here | 1151 emit_cfg.ctxlen = diffio->dio_ctxlen; |
1149 emit_cb.priv = &diffio->dio_diff; | 1152 emit_cb.priv = &diffio->dio_diff; |
1150 if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES) | 1153 if (diffio->dio_outfmt == DIO_OUTPUT_INDICES) |
1151 emit_cfg.hunk_func = xdiff_out_indices; | 1154 emit_cfg.hunk_func = xdiff_out_indices; |
1152 else | 1155 else |
1153 emit_cb.out_line = xdiff_out_unified; | 1156 emit_cb.out_line = xdiff_out_unified; |
1154 if (xdl_diff(&diffio->dio_orig.din_mmfile, | 1157 if (xdl_diff(&diffio->dio_orig.din_mmfile, |
1155 &diffio->dio_new.din_mmfile, | 1158 &diffio->dio_new.din_mmfile, |
3471 * Parse the diff options passed in "optarg" to the diff() function and return | 3474 * Parse the diff options passed in "optarg" to the diff() function and return |
3472 * the options in "diffopts" and the diff algorithm in "diffalgo". | 3475 * the options in "diffopts" and the diff algorithm in "diffalgo". |
3473 */ | 3476 */ |
3474 static int | 3477 static int |
3475 parse_diff_optarg( | 3478 parse_diff_optarg( |
3476 typval_T *opts, | 3479 typval_T *opts, |
3477 int *diffopts, | 3480 int *diffopts, |
3478 long *diffalgo, | 3481 long *diffalgo, |
3479 int *diff_output_fmt) | 3482 dio_outfmt_T *diff_output_fmt, |
3483 int *diff_ctxlen) | |
3480 { | 3484 { |
3481 dict_T *d = opts->vval.v_dict; | 3485 dict_T *d = opts->vval.v_dict; |
3482 | 3486 |
3483 char_u *algo = dict_get_string(d, "algorithm", FALSE); | 3487 char_u *algo = dict_get_string(d, "algorithm", FALSE); |
3484 if (algo != NULL) | 3488 if (algo != NULL) |
3495 | 3499 |
3496 char_u *output_fmt = dict_get_string(d, "output", FALSE); | 3500 char_u *output_fmt = dict_get_string(d, "output", FALSE); |
3497 if (output_fmt != NULL) | 3501 if (output_fmt != NULL) |
3498 { | 3502 { |
3499 if (STRNCMP(output_fmt, "unified", 7) == 0) | 3503 if (STRNCMP(output_fmt, "unified", 7) == 0) |
3500 *diff_output_fmt = DIFF_INTERNAL_OUTPUT_UNIFIED; | 3504 *diff_output_fmt = DIO_OUTPUT_UNIFIED; |
3501 else if (STRNCMP(output_fmt, "indices", 7) == 0) | 3505 else if (STRNCMP(output_fmt, "indices", 7) == 0) |
3502 *diff_output_fmt = DIFF_INTERNAL_OUTPUT_INDICES; | 3506 *diff_output_fmt = DIO_OUTPUT_INDICES; |
3503 else | 3507 else |
3504 { | 3508 { |
3505 semsg(_(e_unsupported_diff_output_format_str), output_fmt); | 3509 semsg(_(e_unsupported_diff_output_format_str), output_fmt); |
3506 return FAIL; | 3510 return FAIL; |
3507 } | 3511 } |
3508 } | 3512 } |
3513 | |
3514 *diff_ctxlen = dict_get_number_def(d, "context", 1); | |
3515 if (*diff_ctxlen < 0) | |
3516 *diff_ctxlen = 1; | |
3509 | 3517 |
3510 if (dict_get_bool(d, "iblank", FALSE)) | 3518 if (dict_get_bool(d, "iblank", FALSE)) |
3511 *diffopts |= DIFF_IBLANK; | 3519 *diffopts |= DIFF_IBLANK; |
3512 if (dict_get_bool(d, "icase", FALSE)) | 3520 if (dict_get_bool(d, "icase", FALSE)) |
3513 *diffopts |= DIFF_ICASE; | 3521 *diffopts |= DIFF_ICASE; |
3600 list_T *new_list = argvars[1].vval.v_list; | 3608 list_T *new_list = argvars[1].vval.v_list; |
3601 | 3609 |
3602 // Save the 'diffopt' option value and restore it after getting the diff. | 3610 // Save the 'diffopt' option value and restore it after getting the diff. |
3603 int save_diff_flags = diff_flags; | 3611 int save_diff_flags = diff_flags; |
3604 long save_diff_algorithm = diff_algorithm; | 3612 long save_diff_algorithm = diff_algorithm; |
3605 long save_diff_output_fmt = diff_internal_output_fmt; | |
3606 diff_flags = DIFF_INTERNAL; | 3613 diff_flags = DIFF_INTERNAL; |
3607 diff_algorithm = 0; | 3614 diff_algorithm = 0; |
3608 diff_internal_output_fmt = DIFF_INTERNAL_OUTPUT_UNIFIED; | 3615 dio.dio_outfmt = DIO_OUTPUT_UNIFIED; |
3609 if (argvars[2].v_type != VAR_UNKNOWN) | 3616 if (argvars[2].v_type != VAR_UNKNOWN) |
3610 if (parse_diff_optarg(&argvars[2], &diff_flags, &diff_algorithm, | 3617 if (parse_diff_optarg(&argvars[2], &diff_flags, &diff_algorithm, |
3611 &diff_internal_output_fmt) == FAIL) | 3618 &dio.dio_outfmt, &dio.dio_ctxlen) == FAIL) |
3612 { | |
3613 diff_internal_output_fmt = save_diff_output_fmt; | |
3614 return; | 3619 return; |
3615 } | |
3616 | 3620 |
3617 // Concatenate the List of strings into a single string using newline | 3621 // Concatenate the List of strings into a single string using newline |
3618 // separator. Internal diff library expects a single string. | 3622 // separator. Internal diff library expects a single string. |
3619 list_to_diffin(orig_list, &dio.dio_orig, diff_flags & DIFF_ICASE); | 3623 list_to_diffin(orig_list, &dio.dio_orig, diff_flags & DIFF_ICASE); |
3620 list_to_diffin(new_list, &dio.dio_new, diff_flags & DIFF_ICASE); | 3624 list_to_diffin(new_list, &dio.dio_new, diff_flags & DIFF_ICASE); |
3621 | 3625 |
3626 // If 'diffexpr' is set, then the internal diff is not used. Set | |
3627 // 'diffexpr' to an empty string temporarily. | |
3628 int restore_diffexpr = FALSE; | |
3629 char_u cc = *p_dex; | |
3630 if (*p_dex != NUL) | |
3631 { | |
3632 restore_diffexpr = TRUE; | |
3633 *p_dex = NUL; | |
3634 } | |
3635 | |
3622 // Compute the diff | 3636 // Compute the diff |
3623 int diff_status = diff_file(&dio); | 3637 int diff_status = diff_file(&dio); |
3624 | 3638 |
3639 // restore 'diffexpr' | |
3640 if (restore_diffexpr) | |
3641 *p_dex = cc; | |
3642 | |
3625 if (diff_status == FAIL) | 3643 if (diff_status == FAIL) |
3626 goto done; | 3644 goto done; |
3627 | 3645 |
3628 int hunk_idx = 0; | 3646 int hunk_idx = 0; |
3629 dict_T *hunk_dict; | 3647 dict_T *hunk_dict; |
3630 | 3648 |
3631 if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES) | 3649 if (dio.dio_outfmt == DIO_OUTPUT_INDICES) |
3632 { | 3650 { |
3633 if (rettv_list_alloc(rettv) != OK) | 3651 if (rettv_list_alloc(rettv) != OK) |
3634 goto done; | 3652 goto done; |
3635 list_T *l = rettv->vval.v_list; | 3653 list_T *l = rettv->vval.v_list; |
3636 | 3654 |
3655 vim_strsave((char_u *)dio.dio_diff.dout_ga.ga_data); | 3673 vim_strsave((char_u *)dio.dio_diff.dout_ga.ga_data); |
3656 } | 3674 } |
3657 | 3675 |
3658 done: | 3676 done: |
3659 clear_diffin(&dio.dio_new); | 3677 clear_diffin(&dio.dio_new); |
3660 if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES) | 3678 if (dio.dio_outfmt == DIO_OUTPUT_INDICES) |
3661 clear_diffout(&dio.dio_diff); | 3679 clear_diffout(&dio.dio_diff); |
3662 else | 3680 else |
3663 ga_clear(&dio.dio_diff.dout_ga); | 3681 ga_clear(&dio.dio_diff.dout_ga); |
3664 clear_diffin(&dio.dio_orig); | 3682 clear_diffin(&dio.dio_orig); |
3665 // Restore the 'diffopt' option value. | 3683 // Restore the 'diffopt' option value. |
3666 diff_flags = save_diff_flags; | 3684 diff_flags = save_diff_flags; |
3667 diff_algorithm = save_diff_algorithm; | 3685 diff_algorithm = save_diff_algorithm; |
3668 diff_internal_output_fmt = save_diff_output_fmt; | |
3669 # endif | 3686 # endif |
3670 } | 3687 } |
3671 | 3688 |
3672 #endif | 3689 #endif |