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