forked from aniani/vim
patch 9.1.0071: Need a diff() Vim script function
Problem: Need a diff() Vim script function Solution: Add the diff() Vim script function using the xdiff internal diff library, add support for "unified" and "indices" mode. (Yegappan Lakshmanan) fixes: #4241 closes: #12321 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
1226b0584a
commit
fa37835b8c
@@ -1,4 +1,4 @@
|
|||||||
*builtin.txt* For Vim version 9.1. Last change: 2024 Jan 29
|
*builtin.txt* For Vim version 9.1. Last change: 2024 Feb 01
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -147,6 +147,8 @@ delete({fname} [, {flags}]) Number delete the file or directory {fname}
|
|||||||
deletebufline({buf}, {first} [, {last}])
|
deletebufline({buf}, {first} [, {last}])
|
||||||
Number delete lines from buffer {buf}
|
Number delete lines from buffer {buf}
|
||||||
did_filetype() Number |TRUE| if FileType autocmd event used
|
did_filetype() Number |TRUE| if FileType autocmd event used
|
||||||
|
diff({fromlist}, {tolist} [, {options}])
|
||||||
|
List diff two Lists of strings
|
||||||
diff_filler({lnum}) Number diff filler lines about {lnum}
|
diff_filler({lnum}) Number diff filler lines about {lnum}
|
||||||
diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col}
|
diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col}
|
||||||
digraph_get({chars}) String get the |digraph| of {chars}
|
digraph_get({chars}) String get the |digraph| of {chars}
|
||||||
@@ -2046,6 +2048,67 @@ did_filetype() Returns |TRUE| when autocommands are being executed and the
|
|||||||
editing another buffer to set 'filetype' and load a syntax
|
editing another buffer to set 'filetype' and load a syntax
|
||||||
file.
|
file.
|
||||||
|
|
||||||
|
diff({fromlist}, {tolist} [, {options}]) *diff()*
|
||||||
|
Returns a String or a List containing the diff between the
|
||||||
|
strings in {fromlist} and {tolist}. Uses the Vim internal
|
||||||
|
diff library to compute the diff.
|
||||||
|
|
||||||
|
*E106*
|
||||||
|
The optional "output" item in {options} specifies the returned
|
||||||
|
diff format. The following values are supported:
|
||||||
|
indices Return a List of the starting and ending
|
||||||
|
indices and a count of the strings in each
|
||||||
|
diff hunk.
|
||||||
|
unified Return the unified diff output as a String.
|
||||||
|
This is the default.
|
||||||
|
|
||||||
|
If the "output" item in {options} is "indices", then a List is
|
||||||
|
returned. Each List item contains a Dict with the following
|
||||||
|
items for each diff hunk:
|
||||||
|
from_idx start index in {fromlist} for this diff hunk.
|
||||||
|
from_count number of strings in {fromlist} that are
|
||||||
|
added/removed/modified in this diff hunk.
|
||||||
|
to_idx start index in {tolist} for this diff hunk.
|
||||||
|
to_count number of strings in {tolist} that are
|
||||||
|
added/removed/modified in this diff hunk.
|
||||||
|
|
||||||
|
The {options} Dict argument also specifies diff options
|
||||||
|
(similar to 'diffopt') and supports the following items:
|
||||||
|
iblank ignore changes where lines are all
|
||||||
|
blank.
|
||||||
|
icase ignore changes in case of text.
|
||||||
|
iwhite ignore changes in amount of white
|
||||||
|
space.
|
||||||
|
iwhiteall ignore all white space changes.
|
||||||
|
iwhiteeol ignore white space changes at end of
|
||||||
|
line.
|
||||||
|
indent-heuristic use the indent heuristic for the
|
||||||
|
internal diff library.
|
||||||
|
algorithm Dict specifying the diff algorithm to
|
||||||
|
use. Supported boolean items are
|
||||||
|
"myers", "minimal", "patience" and
|
||||||
|
"histogram".
|
||||||
|
For more information about these options, refer to 'diffopt'.
|
||||||
|
|
||||||
|
Returns an empty List or String if {fromlist} and {tolist} are
|
||||||
|
identical.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
:echo diff(['abc'], ['xxx'])
|
||||||
|
@@ -1 +1 @@
|
||||||
|
-abc
|
||||||
|
+xxx
|
||||||
|
|
||||||
|
:echo diff(['abc'], ['xxx'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1}]
|
||||||
|
:echo diff(readfile('oldfile'), readfile('newfile'))
|
||||||
|
:echo diff(getbufline(5, 1, '$'), getbufline(6, 1, '$'))
|
||||||
|
|
||||||
|
For more examples, refer to |diff-func-examples|
|
||||||
|
|
||||||
|
Can also be used as a |method|: >
|
||||||
|
GetFromList->diff(to_list)
|
||||||
|
<
|
||||||
diff_filler({lnum}) *diff_filler()*
|
diff_filler({lnum}) *diff_filler()*
|
||||||
Returns the number of filler lines above line {lnum}.
|
Returns the number of filler lines above line {lnum}.
|
||||||
These are the lines that were inserted at this point in
|
These are the lines that were inserted at this point in
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
*diff.txt* For Vim version 9.1. Last change: 2023 Apr 04
|
*diff.txt* For Vim version 9.1. Last change: 2024 Feb 01
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -476,4 +476,43 @@ Otherwise, the expression is evaluated in the context of the script where the
|
|||||||
option was set, thus script-local items are available.
|
option was set, thus script-local items are available.
|
||||||
|
|
||||||
|
|
||||||
|
DIFF FUNCTION EXAMPLES *diff-func-examples*
|
||||||
|
|
||||||
|
Some examples for using the |diff()| function to compute the diff indices
|
||||||
|
between two Lists of strings are below.
|
||||||
|
>
|
||||||
|
" some lines are changed
|
||||||
|
:echo diff(['abc', 'def', 'ghi'], ['abx', 'rrr', 'xhi'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 0, 'from_count': 3, 'to_idx': 0, 'to_count': 3}]
|
||||||
|
|
||||||
|
" few lines added at the beginning
|
||||||
|
:echo diff(['ghi'], ['abc', 'def', 'ghi'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 0, 'from_count': 0, 'to_idx': 0, 'to_count': 2}]
|
||||||
|
|
||||||
|
" few lines removed from the beginning
|
||||||
|
:echo diff(['abc', 'def', 'ghi'], ['ghi'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 0, 'from_count': 2, 'to_idx': 0, 'to_count': 0}]
|
||||||
|
|
||||||
|
" few lines added in the middle
|
||||||
|
:echo diff(['abc', 'jkl'], ['abc', 'def', 'ghi', 'jkl'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}]
|
||||||
|
|
||||||
|
" few lines removed in the middle
|
||||||
|
:echo diff(['abc', 'def', 'ghi', 'jkl'], ['abc', 'jkl'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 1, 'from_count': 2, 'to_idx': 1, 'to_count': 0}]
|
||||||
|
|
||||||
|
" few lines added at the end
|
||||||
|
:echo diff(['abc'], ['abc', 'def', 'ghi'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}]
|
||||||
|
|
||||||
|
" few lines removed from the end
|
||||||
|
:echo diff(['abc', 'def', 'ghi'], ['abc'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 1, 'from_count': 2, 'to_idx': 1, 'to_count': 0}]
|
||||||
|
|
||||||
|
" disjointed changes
|
||||||
|
:echo diff(['ab', 'def', 'ghi', 'jkl'], ['abc', 'def', 'ghi', 'jk'], {'output': 'indices'})
|
||||||
|
[{'from_idx': 0, 'from_count': 1, 'to_idx': 0, 'to_count': 1},
|
||||||
|
{'from_idx': 3, 'from_count': 1, 'to_idx': 3, 'to_count': 1}]
|
||||||
|
<
|
||||||
|
|
||||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||||
|
@@ -4137,6 +4137,7 @@ E1056 vim9.txt /*E1056*
|
|||||||
E1057 vim9.txt /*E1057*
|
E1057 vim9.txt /*E1057*
|
||||||
E1058 vim9.txt /*E1058*
|
E1058 vim9.txt /*E1058*
|
||||||
E1059 vim9.txt /*E1059*
|
E1059 vim9.txt /*E1059*
|
||||||
|
E106 builtin.txt /*E106*
|
||||||
E1060 vim9.txt /*E1060*
|
E1060 vim9.txt /*E1060*
|
||||||
E1061 vim9.txt /*E1061*
|
E1061 vim9.txt /*E1061*
|
||||||
E1062 eval.txt /*E1062*
|
E1062 eval.txt /*E1062*
|
||||||
@@ -6759,7 +6760,9 @@ dict-identity eval.txt /*dict-identity*
|
|||||||
dict-modification eval.txt /*dict-modification*
|
dict-modification eval.txt /*dict-modification*
|
||||||
did_filetype() builtin.txt /*did_filetype()*
|
did_filetype() builtin.txt /*did_filetype()*
|
||||||
diff diff.txt /*diff*
|
diff diff.txt /*diff*
|
||||||
|
diff() builtin.txt /*diff()*
|
||||||
diff-diffexpr diff.txt /*diff-diffexpr*
|
diff-diffexpr diff.txt /*diff-diffexpr*
|
||||||
|
diff-func-examples diff.txt /*diff-func-examples*
|
||||||
diff-mode diff.txt /*diff-mode*
|
diff-mode diff.txt /*diff-mode*
|
||||||
diff-options diff.txt /*diff-options*
|
diff-options diff.txt /*diff-options*
|
||||||
diff-original-file diff.txt /*diff-original-file*
|
diff-original-file diff.txt /*diff-original-file*
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
*todo.txt* For Vim version 9.1. Last change: 2024 Jan 14
|
*todo.txt* For Vim version 9.1. Last change: 2024 Feb 01
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -956,9 +956,6 @@ When 'sidescrolloff' is set, using "zl" to go to the end of the line, suddenly
|
|||||||
scrolls back. Should allow for this scrolling, like 'scrolloff' does when
|
scrolls back. Should allow for this scrolling, like 'scrolloff' does when
|
||||||
using CTRL-E. (Yee Cheng Chin, #3721)
|
using CTRL-E. (Yee Cheng Chin, #3721)
|
||||||
|
|
||||||
Add function to make use of internal diff, working on two lists and returning
|
|
||||||
unified diff (list of lines).
|
|
||||||
|
|
||||||
When splitting a window with few text lines, the relative cursor position is
|
When splitting a window with few text lines, the relative cursor position is
|
||||||
kept, which means part of the text isn't displayed. Better show all the text
|
kept, which means part of the text isn't displayed. Better show all the text
|
||||||
when possible. (Dylan Lloyd, #3973)
|
when possible. (Dylan Lloyd, #3973)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
*usr_41.txt* For Vim version 9.1. Last change: 2024 Jan 13
|
*usr_41.txt* For Vim version 9.1. Last change: 2024 Feb 01
|
||||||
|
|
||||||
VIM USER MANUAL - by Bram Moolenaar
|
VIM USER MANUAL - by Bram Moolenaar
|
||||||
|
|
||||||
@@ -1368,6 +1368,7 @@ Various: *various-functions*
|
|||||||
changenr() return number of most recent change
|
changenr() return number of most recent change
|
||||||
cscope_connection() check if a cscope connection exists
|
cscope_connection() check if a cscope connection exists
|
||||||
did_filetype() check if a FileType autocommand was used
|
did_filetype() check if a FileType autocommand was used
|
||||||
|
diff() diff two Lists of strings
|
||||||
eventhandler() check if invoked by an event handler
|
eventhandler() check if invoked by an event handler
|
||||||
getpid() get process ID of Vim
|
getpid() get process ID of Vim
|
||||||
getscriptinfo() get list of sourced vim scripts
|
getscriptinfo() get list of sourced vim scripts
|
||||||
|
236
src/diff.c
236
src/diff.c
@@ -42,6 +42,10 @@ static int diff_flags = DIFF_INTERNAL | DIFF_FILLER | DIFF_CLOSE_OFF;
|
|||||||
|
|
||||||
static long diff_algorithm = 0;
|
static long diff_algorithm = 0;
|
||||||
|
|
||||||
|
#define DIFF_INTERNAL_OUTPUT_UNIFIED 1
|
||||||
|
#define DIFF_INTERNAL_OUTPUT_INDICES 2
|
||||||
|
static int diff_internal_output_fmt = DIFF_INTERNAL_OUTPUT_INDICES;
|
||||||
|
|
||||||
#define LBUFLEN 50 // length of line in diff file
|
#define LBUFLEN 50 // length of line in diff file
|
||||||
|
|
||||||
static int diff_a_works = MAYBE; // TRUE when "diff -a" works, FALSE when it
|
static int diff_a_works = MAYBE; // TRUE when "diff -a" works, FALSE when it
|
||||||
@@ -97,7 +101,8 @@ static void diff_copy_entry(diff_T *dprev, diff_T *dp, int idx_orig, int idx_new
|
|||||||
static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp);
|
static diff_T *diff_alloc_new(tabpage_T *tp, diff_T *dprev, diff_T *dp);
|
||||||
static int parse_diff_ed(char_u *line, diffhunk_T *hunk);
|
static int parse_diff_ed(char_u *line, diffhunk_T *hunk);
|
||||||
static int parse_diff_unified(char_u *line, diffhunk_T *hunk);
|
static int parse_diff_unified(char_u *line, diffhunk_T *hunk);
|
||||||
static int xdiff_out(long start_a, long count_a, long start_b, long count_b, void *priv);
|
static int xdiff_out_indices(long start_a, long count_a, long start_b, long count_b, void *priv);
|
||||||
|
static int xdiff_out_unified(void *priv, mmbuffer_t *mb, int nbuf);
|
||||||
|
|
||||||
#define FOR_ALL_DIFFBLOCKS_IN_TAB(tp, dp) \
|
#define FOR_ALL_DIFFBLOCKS_IN_TAB(tp, dp) \
|
||||||
for ((dp) = (tp)->tp_first_diff; (dp) != NULL; (dp) = (dp)->df_next)
|
for ((dp) = (tp)->tp_first_diff; (dp) != NULL; (dp) = (dp)->df_next)
|
||||||
@@ -1142,7 +1147,10 @@ diff_file_internal(diffio_T *diffio)
|
|||||||
|
|
||||||
emit_cfg.ctxlen = 0; // don't need any diff_context here
|
emit_cfg.ctxlen = 0; // don't need any diff_context here
|
||||||
emit_cb.priv = &diffio->dio_diff;
|
emit_cb.priv = &diffio->dio_diff;
|
||||||
emit_cfg.hunk_func = xdiff_out;
|
if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES)
|
||||||
|
emit_cfg.hunk_func = xdiff_out_indices;
|
||||||
|
else
|
||||||
|
emit_cb.out_line = xdiff_out_unified;
|
||||||
if (xdl_diff(&diffio->dio_orig.din_mmfile,
|
if (xdl_diff(&diffio->dio_orig.din_mmfile,
|
||||||
&diffio->dio_new.din_mmfile,
|
&diffio->dio_new.din_mmfile,
|
||||||
¶m, &emit_cfg, &emit_cb) < 0)
|
¶m, &emit_cfg, &emit_cb) < 0)
|
||||||
@@ -3327,10 +3335,10 @@ parse_diff_unified(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Callback function for the xdl_diff() function.
|
* Callback function for the xdl_diff() function.
|
||||||
* Stores the diff output in a grow array.
|
* Stores the diff output (indices) in a grow array.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xdiff_out(
|
xdiff_out_indices(
|
||||||
long start_a,
|
long start_a,
|
||||||
long count_a,
|
long count_a,
|
||||||
long start_b,
|
long start_b,
|
||||||
@@ -3357,6 +3365,25 @@ xdiff_out(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback function for the xdl_diff() function.
|
||||||
|
* Stores the unified diff output in a grow array.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xdiff_out_unified(
|
||||||
|
void *priv,
|
||||||
|
mmbuffer_t *mb,
|
||||||
|
int nbuf)
|
||||||
|
{
|
||||||
|
diffout_T *dout = (diffout_T *)priv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < nbuf; i++)
|
||||||
|
ga_concat_len(&dout->dout_ga, (char_u *)mb[i].ptr, mb[i].size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // FEAT_DIFF
|
#endif // FEAT_DIFF
|
||||||
|
|
||||||
#if defined(FEAT_EVAL) || defined(PROTO)
|
#if defined(FEAT_EVAL) || defined(PROTO)
|
||||||
@@ -3439,4 +3466,205 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the diff options passed in "optarg" to the diff() function and return
|
||||||
|
* the options in "diffopts" and the diff algorithm in "diffalgo".
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parse_diff_optarg(
|
||||||
|
typval_T *opts,
|
||||||
|
int *diffopts,
|
||||||
|
long *diffalgo,
|
||||||
|
int *diff_output_fmt)
|
||||||
|
{
|
||||||
|
dict_T *d = opts->vval.v_dict;
|
||||||
|
|
||||||
|
char_u *algo = dict_get_string(d, "algorithm", FALSE);
|
||||||
|
if (algo != NULL)
|
||||||
|
{
|
||||||
|
if (STRNCMP(algo, "myers", 5) == 0)
|
||||||
|
*diffalgo = 0;
|
||||||
|
else if (STRNCMP(algo, "minimal", 7) == 0)
|
||||||
|
*diffalgo = XDF_NEED_MINIMAL;
|
||||||
|
else if (STRNCMP(algo, "patience", 8) == 0)
|
||||||
|
*diffalgo = XDF_PATIENCE_DIFF;
|
||||||
|
else if (STRNCMP(algo, "histogram", 9) == 0)
|
||||||
|
*diffalgo = XDF_HISTOGRAM_DIFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
char_u *output_fmt = dict_get_string(d, "output", FALSE);
|
||||||
|
if (output_fmt != NULL)
|
||||||
|
{
|
||||||
|
if (STRNCMP(output_fmt, "unified", 7) == 0)
|
||||||
|
*diff_output_fmt = DIFF_INTERNAL_OUTPUT_UNIFIED;
|
||||||
|
else if (STRNCMP(output_fmt, "indices", 7) == 0)
|
||||||
|
*diff_output_fmt = DIFF_INTERNAL_OUTPUT_INDICES;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semsg(_(e_unsupported_diff_output_format_str), output_fmt);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict_get_bool(d, "iblank", FALSE))
|
||||||
|
*diffopts |= DIFF_IBLANK;
|
||||||
|
if (dict_get_bool(d, "icase", FALSE))
|
||||||
|
*diffopts |= DIFF_ICASE;
|
||||||
|
if (dict_get_bool(d, "iwhite", FALSE))
|
||||||
|
*diffopts |= DIFF_IWHITE;
|
||||||
|
if (dict_get_bool(d, "iwhiteall", FALSE))
|
||||||
|
*diffopts |= DIFF_IWHITEALL;
|
||||||
|
if (dict_get_bool(d, "iwhiteeol", FALSE))
|
||||||
|
*diffopts |= DIFF_IWHITEEOL;
|
||||||
|
if (dict_get_bool(d, "indent-heuristic", FALSE))
|
||||||
|
*diffalgo |= XDF_INDENT_HEURISTIC;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Concatenate the List of strings in "l" and store the result in
|
||||||
|
* "din->din_mmfile.ptr" and the length in "din->din_mmfile.size".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
list_to_diffin(list_T *l, diffin_T *din, int icase)
|
||||||
|
{
|
||||||
|
garray_T ga;
|
||||||
|
listitem_T *li;
|
||||||
|
char_u *str;
|
||||||
|
|
||||||
|
ga_init2(&ga, 512, 4);
|
||||||
|
|
||||||
|
FOR_ALL_LIST_ITEMS(l, li)
|
||||||
|
{
|
||||||
|
str = tv_get_string(&li->li_tv);
|
||||||
|
if (icase)
|
||||||
|
{
|
||||||
|
str = strlow_save(str);
|
||||||
|
if (str == NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ga_concat(&ga, str);
|
||||||
|
ga_concat(&ga, (char_u *)NL_STR);
|
||||||
|
if (icase)
|
||||||
|
vim_free(str);
|
||||||
|
}
|
||||||
|
if (ga.ga_len > 0)
|
||||||
|
((char *)ga.ga_data)[ga.ga_len] = NUL;
|
||||||
|
|
||||||
|
din->din_mmfile.ptr = (char *)ga.ga_data;
|
||||||
|
din->din_mmfile.size = ga.ga_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the start and end indices from the diff "hunk".
|
||||||
|
*/
|
||||||
|
static dict_T *
|
||||||
|
get_diff_hunk_indices(diffhunk_T *hunk)
|
||||||
|
{
|
||||||
|
dict_T *hunk_dict;
|
||||||
|
|
||||||
|
hunk_dict = dict_alloc();
|
||||||
|
if (hunk_dict == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dict_add_number(hunk_dict, "from_idx", hunk->lnum_orig - 1);
|
||||||
|
dict_add_number(hunk_dict, "from_count", hunk->count_orig);
|
||||||
|
dict_add_number(hunk_dict, "to_idx", hunk->lnum_new - 1);
|
||||||
|
dict_add_number(hunk_dict, "to_count", hunk->count_new);
|
||||||
|
|
||||||
|
return hunk_dict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* "diff()" function
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
f_diff(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
|
||||||
|
{
|
||||||
|
#ifdef FEAT_DIFF
|
||||||
|
diffio_T dio;
|
||||||
|
|
||||||
|
if (check_for_nonnull_list_arg(argvars, 0) == FAIL
|
||||||
|
|| check_for_nonnull_list_arg(argvars, 1) == FAIL
|
||||||
|
|| check_for_opt_nonnull_dict_arg(argvars, 2) == FAIL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CLEAR_FIELD(dio);
|
||||||
|
dio.dio_internal = TRUE;
|
||||||
|
ga_init2(&dio.dio_diff.dout_ga, sizeof(char *), 1000);
|
||||||
|
|
||||||
|
list_T *orig_list = argvars[0].vval.v_list;
|
||||||
|
list_T *new_list = argvars[1].vval.v_list;
|
||||||
|
|
||||||
|
// Save the 'diffopt' option value and restore it after getting the diff.
|
||||||
|
int save_diff_flags = diff_flags;
|
||||||
|
long save_diff_algorithm = diff_algorithm;
|
||||||
|
long save_diff_output_fmt = diff_internal_output_fmt;
|
||||||
|
diff_flags = DIFF_INTERNAL;
|
||||||
|
diff_algorithm = 0;
|
||||||
|
diff_internal_output_fmt = DIFF_INTERNAL_OUTPUT_UNIFIED;
|
||||||
|
if (argvars[2].v_type != VAR_UNKNOWN)
|
||||||
|
if (parse_diff_optarg(&argvars[2], &diff_flags, &diff_algorithm,
|
||||||
|
&diff_internal_output_fmt) == FAIL)
|
||||||
|
{
|
||||||
|
diff_internal_output_fmt = save_diff_output_fmt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concatenate the List of strings into a single string using newline
|
||||||
|
// separator. Internal diff library expects a single string.
|
||||||
|
list_to_diffin(orig_list, &dio.dio_orig, diff_flags & DIFF_ICASE);
|
||||||
|
list_to_diffin(new_list, &dio.dio_new, diff_flags & DIFF_ICASE);
|
||||||
|
|
||||||
|
// Compute the diff
|
||||||
|
int diff_status = diff_file(&dio);
|
||||||
|
|
||||||
|
if (diff_status == FAIL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
int hunk_idx = 0;
|
||||||
|
dict_T *hunk_dict;
|
||||||
|
|
||||||
|
if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES)
|
||||||
|
{
|
||||||
|
if (rettv_list_alloc(rettv) != OK)
|
||||||
|
goto done;
|
||||||
|
list_T *l = rettv->vval.v_list;
|
||||||
|
|
||||||
|
// Process each diff hunk
|
||||||
|
diffhunk_T *hunk = NULL;
|
||||||
|
while (hunk_idx < dio.dio_diff.dout_ga.ga_len)
|
||||||
|
{
|
||||||
|
hunk = ((diffhunk_T **)dio.dio_diff.dout_ga.ga_data)[hunk_idx++];
|
||||||
|
|
||||||
|
hunk_dict = get_diff_hunk_indices(hunk);
|
||||||
|
if (hunk_dict == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
list_append_dict(l, hunk_dict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ga_append(&dio.dio_diff.dout_ga, NUL);
|
||||||
|
rettv->v_type = VAR_STRING;
|
||||||
|
rettv->vval.v_string =
|
||||||
|
vim_strsave((char_u *)dio.dio_diff.dout_ga.ga_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
clear_diffin(&dio.dio_new);
|
||||||
|
if (diff_internal_output_fmt == DIFF_INTERNAL_OUTPUT_INDICES)
|
||||||
|
clear_diffout(&dio.dio_diff);
|
||||||
|
else
|
||||||
|
ga_clear(&dio.dio_diff.dout_ga);
|
||||||
|
clear_diffin(&dio.dio_orig);
|
||||||
|
// Restore the 'diffopt' option value.
|
||||||
|
diff_flags = save_diff_flags;
|
||||||
|
diff_algorithm = save_diff_algorithm;
|
||||||
|
diff_internal_output_fmt = save_diff_output_fmt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -258,8 +258,9 @@ EXTERN char e_escape_not_allowed_in_digraph[]
|
|||||||
EXTERN char e_using_loadkeymap_not_in_sourced_file[]
|
EXTERN char e_using_loadkeymap_not_in_sourced_file[]
|
||||||
INIT(= N_("E105: Using :loadkeymap not in a sourced file"));
|
INIT(= N_("E105: Using :loadkeymap not in a sourced file"));
|
||||||
#endif
|
#endif
|
||||||
// E106 unused
|
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
|
EXTERN char e_unsupported_diff_output_format_str[]
|
||||||
|
INIT(= N_("E106: Unsupported diff output format: %s"));
|
||||||
EXTERN char e_missing_parenthesis_str[]
|
EXTERN char e_missing_parenthesis_str[]
|
||||||
INIT(= N_("E107: Missing parentheses: %s"));
|
INIT(= N_("E107: Missing parentheses: %s"));
|
||||||
EXTERN char e_no_such_variable_str[]
|
EXTERN char e_no_such_variable_str[]
|
||||||
|
@@ -1148,6 +1148,7 @@ static argcheck_T arg3_buffer_number_number[] = {arg_buffer, arg_number, arg_num
|
|||||||
static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, arg_any};
|
static argcheck_T arg3_buffer_string_any[] = {arg_buffer, arg_string, arg_any};
|
||||||
static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any};
|
static argcheck_T arg3_buffer_string_dict[] = {arg_buffer, arg_string, arg_dict_any};
|
||||||
static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number};
|
static argcheck_T arg3_dict_number_number[] = {arg_dict_any, arg_number, arg_number};
|
||||||
|
static argcheck_T arg3_diff[] = {arg_list_string, arg_list_string, arg_dict_any};
|
||||||
static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any};
|
static argcheck_T arg3_list_string_dict[] = {arg_list_any, arg_string, arg_dict_any};
|
||||||
static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
|
static argcheck_T arg3_lnum_number_bool[] = {arg_lnum, arg_number, arg_bool};
|
||||||
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
|
static argcheck_T arg3_number[] = {arg_number, arg_number, arg_number};
|
||||||
@@ -1950,6 +1951,8 @@ static funcentry_T global_functions[] =
|
|||||||
ret_number_bool, f_deletebufline},
|
ret_number_bool, f_deletebufline},
|
||||||
{"did_filetype", 0, 0, 0, NULL,
|
{"did_filetype", 0, 0, 0, NULL,
|
||||||
ret_number_bool, f_did_filetype},
|
ret_number_bool, f_did_filetype},
|
||||||
|
{"diff", 2, 3, FEARG_1, arg3_diff,
|
||||||
|
ret_list_dict_any, f_diff},
|
||||||
{"diff_filler", 1, 1, FEARG_1, arg1_lnum,
|
{"diff_filler", 1, 1, FEARG_1, arg1_lnum,
|
||||||
ret_number, f_diff_filler},
|
ret_number, f_diff_filler},
|
||||||
{"diff_hlID", 2, 2, FEARG_1, arg2_lnum_number,
|
{"diff_hlID", 2, 2, FEARG_1, arg2_lnum_number,
|
||||||
|
@@ -30,4 +30,5 @@ linenr_T diff_get_corresponding_line(buf_T *buf1, linenr_T lnum1);
|
|||||||
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp);
|
linenr_T diff_lnum_win(linenr_T lnum, win_T *wp);
|
||||||
void f_diff_filler(typval_T *argvars, typval_T *rettv);
|
void f_diff_filler(typval_T *argvars, typval_T *rettv);
|
||||||
void f_diff_hlID(typval_T *argvars, typval_T *rettv);
|
void f_diff_hlID(typval_T *argvars, typval_T *rettv);
|
||||||
|
void f_diff(typval_T *argvars, typval_T *rettv);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -26,6 +26,7 @@ int check_for_opt_list_arg(typval_T *args, int idx);
|
|||||||
int check_for_dict_arg(typval_T *args, int idx);
|
int check_for_dict_arg(typval_T *args, int idx);
|
||||||
int check_for_nonnull_dict_arg(typval_T *args, int idx);
|
int check_for_nonnull_dict_arg(typval_T *args, int idx);
|
||||||
int check_for_opt_dict_arg(typval_T *args, int idx);
|
int check_for_opt_dict_arg(typval_T *args, int idx);
|
||||||
|
int check_for_opt_nonnull_dict_arg(typval_T *args, int idx);
|
||||||
int check_for_chan_or_job_arg(typval_T *args, int idx);
|
int check_for_chan_or_job_arg(typval_T *args, int idx);
|
||||||
int check_for_opt_chan_or_job_arg(typval_T *args, int idx);
|
int check_for_opt_chan_or_job_arg(typval_T *args, int idx);
|
||||||
int check_for_job_arg(typval_T *args, int idx);
|
int check_for_job_arg(typval_T *args, int idx);
|
||||||
|
@@ -1716,5 +1716,182 @@ func Test_diff_put_and_undo()
|
|||||||
|
|
||||||
bwipe!
|
bwipe!
|
||||||
bwipe!
|
bwipe!
|
||||||
|
set nodiff
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for the diff() function
|
||||||
|
def Test_diff_func()
|
||||||
|
# string is added/removed/modified at the beginning
|
||||||
|
assert_equal("@@ -0,0 +1 @@\n+abc\n",
|
||||||
|
diff(['def'], ['abc', 'def'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['def'], ['abc', 'def'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +0,0 @@\n-abc\n",
|
||||||
|
diff(['abc', 'def'], ['def'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 0}],
|
||||||
|
diff(['abc', 'def'], ['def'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
|
||||||
|
diff(['abc', 'def'], ['abx', 'def'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abc', 'def'], ['abx', 'def'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# string is added/removed/modified at the end
|
||||||
|
assert_equal("@@ -1,0 +2 @@\n+def\n",
|
||||||
|
diff(['abc'], ['abc', 'def'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 1, from_count: 0, to_idx: 1, to_count: 1}],
|
||||||
|
diff(['abc'], ['abc', 'def'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -2 +1,0 @@\n-def\n",
|
||||||
|
diff(['abc', 'def'], ['abc'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 0}],
|
||||||
|
diff(['abc', 'def'], ['abc'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -2 +2 @@\n-def\n+xef\n",
|
||||||
|
diff(['abc', 'def'], ['abc', 'xef'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 1, from_count: 1, to_idx: 1, to_count: 1}],
|
||||||
|
diff(['abc', 'def'], ['abc', 'xef'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# string is added/removed/modified in the middle
|
||||||
|
assert_equal("@@ -2,0 +3 @@\n+xxx\n",
|
||||||
|
diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 2, from_count: 0, to_idx: 2, to_count: 1}],
|
||||||
|
diff(['111', '222', '333'], ['111', '222', 'xxx', '333'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -3 +2,0 @@\n-333\n",
|
||||||
|
diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 0}],
|
||||||
|
diff(['111', '222', '333', '444'], ['111', '222', '444'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -3 +3 @@\n-333\n+xxx\n",
|
||||||
|
diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
|
||||||
|
diff(['111', '222', '333', '444'], ['111', '222', 'xxx', '444'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# new strings are added to an empty List
|
||||||
|
assert_equal("@@ -0,0 +1,2 @@\n+abc\n+def\n",
|
||||||
|
diff([], ['abc', 'def'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 0, to_idx: 0, to_count: 2}],
|
||||||
|
diff([], ['abc', 'def'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# all the strings are removed from a List
|
||||||
|
assert_equal("@@ -1,2 +0,0 @@\n-abc\n-def\n",
|
||||||
|
diff(['abc', 'def'], [], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 2, to_idx: 0, to_count: 0}],
|
||||||
|
diff(['abc', 'def'], [], {output: 'indices'}))
|
||||||
|
|
||||||
|
# First character is added/removed/different
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc\n+bc\n",
|
||||||
|
diff(['abc'], ['bc'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abc'], ['bc'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-bc\n+abc\n",
|
||||||
|
diff(['bc'], ['abc'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['bc'], ['abc'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc\n+xbc\n",
|
||||||
|
diff(['abc'], ['xbc'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abc'], ['xbc'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# Last character is added/removed/different
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc\n+abcd\n",
|
||||||
|
diff(['abc'], ['abcd'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abc'], ['abcd'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abcd\n+abc\n",
|
||||||
|
diff(['abcd'], ['abc'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abcd'], ['abc'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc\n+abx\n",
|
||||||
|
diff(['abc'], ['abx'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff(['abc'], ['abx'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# partial string modification at the start and at the end.
|
||||||
|
var fromlist =<< trim END
|
||||||
|
one two
|
||||||
|
three four
|
||||||
|
five six
|
||||||
|
END
|
||||||
|
var tolist =<< trim END
|
||||||
|
one
|
||||||
|
six
|
||||||
|
END
|
||||||
|
assert_equal("@@ -1,3 +1,2 @@\n-one two\n-three four\n-five six\n+one\n+six\n", diff(fromlist, tolist, {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 3, to_idx: 0, to_count: 2}],
|
||||||
|
diff(fromlist, tolist, {output: 'indices'}))
|
||||||
|
|
||||||
|
# non-contiguous modifications
|
||||||
|
fromlist =<< trim END
|
||||||
|
one two
|
||||||
|
three four
|
||||||
|
five abc six
|
||||||
|
END
|
||||||
|
tolist =<< trim END
|
||||||
|
one abc two
|
||||||
|
three four
|
||||||
|
five six
|
||||||
|
END
|
||||||
|
assert_equal("@@ -1 +1 @@\n-one two\n+one abc two\n@@ -3 +3 @@\n-five abc six\n+five six\n",
|
||||||
|
diff(fromlist, tolist, {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1},
|
||||||
|
{from_idx: 2, from_count: 1, to_idx: 2, to_count: 1}],
|
||||||
|
diff(fromlist, tolist, {output: 'indices'}))
|
||||||
|
|
||||||
|
# add/remove blank lines
|
||||||
|
assert_equal("@@ -2,2 +1,0 @@\n-\n-\n",
|
||||||
|
diff(['one', '', '', 'two'], ['one', 'two'], {output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 1, from_count: 2, to_idx: 1, to_count: 0}],
|
||||||
|
diff(['one', '', '', 'two'], ['one', 'two'], {output: 'indices'}))
|
||||||
|
assert_equal("@@ -1,0 +2,2 @@\n+\n+\n",
|
||||||
|
diff(['one', 'two'], ['one', '', '', 'two'], {output: 'unified'}))
|
||||||
|
assert_equal([{'from_idx': 1, 'from_count': 0, 'to_idx': 1, 'to_count': 2}],
|
||||||
|
diff(['one', 'two'], ['one', '', '', 'two'], {output: 'indices'}))
|
||||||
|
|
||||||
|
# diff ignoring case
|
||||||
|
assert_equal('', diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'unified'}))
|
||||||
|
assert_equal([], diff(['abc', 'def'], ['ABC', 'DEF'], {icase: true, output: 'indices'}))
|
||||||
|
|
||||||
|
# diff ignoring all whitespace changes except leading whitespace changes
|
||||||
|
assert_equal('', diff(['abc def'], ['abc def '], {iwhite: true}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:true}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc\n+ xxx\n", diff([' abc'], [' xxx'], {iwhite: v:false}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:true}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n-abc \n+xxx \n", diff(['abc '], ['xxx '], {iwhite: v:false}))
|
||||||
|
|
||||||
|
# diff ignoring all whitespace changes
|
||||||
|
assert_equal('', diff(['abc def'], [' abc def '], {iwhiteall: true}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:true}))
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n", diff([' abc '], [' xxx '], {iwhiteall: v:false}))
|
||||||
|
|
||||||
|
# diff ignoring trailing whitespace changes
|
||||||
|
assert_equal('', diff(['abc'], ['abc '], {iwhiteeol: true}))
|
||||||
|
|
||||||
|
# diff ignoring blank lines
|
||||||
|
assert_equal('', diff(['one', '', '', 'two'], ['one', 'two'], {iblank: true}))
|
||||||
|
assert_equal('', diff(['one', 'two'], ['one', '', '', 'two'], {iblank: true}))
|
||||||
|
|
||||||
|
# same string
|
||||||
|
assert_equal('', diff(['abc', 'def', 'ghi'], ['abc', 'def', 'ghi']))
|
||||||
|
assert_equal('', diff([''], ['']))
|
||||||
|
assert_equal('', diff([], []))
|
||||||
|
|
||||||
|
# different xdiff algorithms
|
||||||
|
for algo in ['myers', 'minimal', 'patience', 'histogram']
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
|
||||||
|
diff([' abc '], [' xxx '], {algorithm: algo, output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff([' abc '], [' xxx '], {algorithm: algo, output: 'indices'}))
|
||||||
|
endfor
|
||||||
|
assert_equal("@@ -1 +1 @@\n- abc \n+ xxx \n",
|
||||||
|
diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'unified'}))
|
||||||
|
assert_equal([{from_idx: 0, from_count: 1, to_idx: 0, to_count: 1}],
|
||||||
|
diff([' abc '], [' xxx '], {indent-heuristic: true, output: 'indices'}))
|
||||||
|
|
||||||
|
# identical strings
|
||||||
|
assert_equal('', diff(['111', '222'], ['111', '222'], {output: 'unified'}))
|
||||||
|
assert_equal([], diff(['111', '222'], ['111', '222'], {output: 'indices'}))
|
||||||
|
assert_equal('', diff([], [], {output: 'unified'}))
|
||||||
|
assert_equal([], diff([], [], {output: 'indices'}))
|
||||||
|
|
||||||
|
# Error cases
|
||||||
|
assert_fails('call diff({}, ["a"])', 'E1211:')
|
||||||
|
assert_fails('call diff(["a"], {})', 'E1211:')
|
||||||
assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
|
assert_fails('call diff(["a"], ["a"], [])', 'E1206:')
|
||||||
assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
|
assert_fails('call diff(["a"], ["a"], {output: "xyz"})', 'E106: Unsupported diff output format: xyz')
|
||||||
|
10
src/typval.c
10
src/typval.c
@@ -623,6 +623,16 @@ check_for_opt_dict_arg(typval_T *args, int idx)
|
|||||||
|| check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
|
|| check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for an optional non-NULL dict argument at 'idx'
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_for_opt_nonnull_dict_arg(typval_T *args, int idx)
|
||||||
|
{
|
||||||
|
return (args[idx].v_type == VAR_UNKNOWN
|
||||||
|
|| check_for_nonnull_dict_arg(args, idx) != FAIL) ? OK : FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
|
#if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
|
||||||
/*
|
/*
|
||||||
* Give an error and return FAIL unless "args[idx]" is a channel or a job.
|
* Give an error and return FAIL unless "args[idx]" is a channel or a job.
|
||||||
|
@@ -704,6 +704,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
71,
|
||||||
/**/
|
/**/
|
||||||
70,
|
70,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user