vim-patch:9.1.1219: Strange error with wrong type for matchfuzzy() "camelcase"

Problem:  Strange error with type for matchfuzzy() "camelcase".
Solution: Show the error "Invalid value for argument camelcase" instead
          of "Invalid argument: camelcase" (zeertzjq).

Note that using tv_get_string() will lead to confusion, as when the
value cannot be converted to a string tv_get_string() will also give an
error about that, but "camelcase" takes a boolean, not a string.  Also
don't use tv_get_string() for the "limit" argument above.

closes: vim/vim#16926

c4815c157b
This commit is contained in:
zeertzjq
2025-03-27 08:21:08 +08:00
parent f9280cde0a
commit 797195e0ea
5 changed files with 19 additions and 9 deletions

View File

@@ -6412,7 +6412,7 @@ matchfuzzy({list}, {str} [, {dict}]) *matchfuzzy()*
returned. Zero means no limit. returned. Zero means no limit.
camelcase Use enhanced camel case scoring making results camelcase Use enhanced camel case scoring making results
better suited for completion related to better suited for completion related to
programming languages. Default is v:true programming languages. Defaults to v:true.
If {list} is a list of dictionaries, then the optional {dict} If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items: argument supports the following additional items:

View File

@@ -5817,7 +5817,7 @@ function vim.fn.matchend(expr, pat, start, count) end
--- returned. Zero means no limit. --- returned. Zero means no limit.
--- camelcase Use enhanced camel case scoring making results --- camelcase Use enhanced camel case scoring making results
--- better suited for completion related to --- better suited for completion related to
--- programming languages. Default is v:true --- programming languages. Defaults to v:true.
--- ---
--- If {list} is a list of dictionaries, then the optional {dict} --- If {list} is a list of dictionaries, then the optional {dict}
--- argument supports the following additional items: --- argument supports the following additional items:

View File

@@ -7152,7 +7152,7 @@ M.funcs = {
returned. Zero means no limit. returned. Zero means no limit.
camelcase Use enhanced camel case scoring making results camelcase Use enhanced camel case scoring making results
better suited for completion related to better suited for completion related to
programming languages. Default is v:true programming languages. Defaults to v:true.
If {list} is a list of dictionaries, then the optional {dict} If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items: argument supports the following additional items:

View File

@@ -3466,7 +3466,7 @@ static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
if ((di = tv_dict_find(d, "key", -1)) != NULL) { if ((di = tv_dict_find(d, "key", -1)) != NULL) {
if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL
|| *di->di_tv.vval.v_string == NUL) { || *di->di_tv.vval.v_string == NUL) {
semsg(_(e_invarg2), tv_get_string(&di->di_tv)); semsg(_(e_invargNval), "key", tv_get_string(&di->di_tv));
return; return;
} }
key = tv_get_string(&di->di_tv); key = tv_get_string(&di->di_tv);
@@ -3477,7 +3477,7 @@ static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
if ((di = tv_dict_find(d, "limit", -1)) != NULL) { if ((di = tv_dict_find(d, "limit", -1)) != NULL) {
if (di->di_tv.v_type != VAR_NUMBER) { if (di->di_tv.v_type != VAR_NUMBER) {
semsg(_(e_invarg2), tv_get_string(&di->di_tv)); semsg(_(e_invargval), "limit");
return; return;
} }
max_matches = (int)tv_get_number_chk(&di->di_tv, NULL); max_matches = (int)tv_get_number_chk(&di->di_tv, NULL);
@@ -3485,7 +3485,7 @@ static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
if ((di = tv_dict_find(d, "camelcase", -1)) != NULL) { if ((di = tv_dict_find(d, "camelcase", -1)) != NULL) {
if (di->di_tv.v_type != VAR_BOOL) { if (di->di_tv.v_type != VAR_BOOL) {
semsg(_(e_invarg2), "camelcase"); semsg(_(e_invargval), "camelcase");
return; return;
} }
camelcase = tv_get_bool_chk(&di->di_tv, NULL); camelcase = tv_get_bool_chk(&di->di_tv, NULL);

View File

@@ -78,6 +78,7 @@ func Test_matchfuzzy()
" Nvim's callback implementation is different, so E6000 is expected instead, " Nvim's callback implementation is different, so E6000 is expected instead,
" call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E921:') " call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E921:')
call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E6000:') call assert_fails("let x = matchfuzzy(l, 'cam', {'text_cb' : []})", 'E6000:')
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 123})", 'E475: Invalid value for argument key: 123')
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : []})", 'E730:') call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : []})", 'E730:')
call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E1297:') call assert_fails("let x = matchfuzzy(l, 'cam', v:_null_dict)", 'E1297:')
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : v:_null_string})", 'E475:') call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : v:_null_string})", 'E475:')
@@ -91,10 +92,15 @@ func Test_matchfuzzy()
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 'name'})", 'E730:') call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 'name'})", 'E730:')
" camelcase " camelcase
call assert_equal(['Cursor', 'CurSearch', 'CursorLine', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor'],
\ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:false}))
call assert_equal(['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'], call assert_equal(['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'],
\ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur')) \ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur'))
call assert_equal(['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'],
\ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:true}))
call assert_equal(['Cursor', 'CurSearch', 'CursorLine', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor'],
\ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:false}))
call assert_equal(['things', 'sThings', 'thisThings'],
\ matchfuzzy(['things','sThings', 'thisThings'], 'thin', {'camelcase': v:false}))
call assert_fails("let x = matchfuzzy([], 'foo', {'camelcase': []})", 'E475: Invalid value for argument camelcase')
" Test in latin1 encoding " Test in latin1 encoding
let save_enc = &encoding let save_enc = &encoding
@@ -161,6 +167,7 @@ func Test_matchfuzzypos()
" Nvim's callback implementation is different, so E6000 is expected instead, " Nvim's callback implementation is different, so E6000 is expected instead,
" call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E921:') " call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E921:')
call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E6000:') call assert_fails("let x = matchfuzzypos(l, 'cam', {'text_cb' : []})", 'E6000:')
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : 123})", 'E475: Invalid value for argument key: 123')
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : []})", 'E730:') call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : []})", 'E730:')
call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E1297:') call assert_fails("let x = matchfuzzypos(l, 'cam', v:_null_dict)", 'E1297:')
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : v:_null_string})", 'E475:') call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : v:_null_string})", 'E475:')
@@ -185,11 +192,13 @@ func Test_matchfuzzypos()
" camelcase " camelcase
call assert_equal([['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'], [[1, 2, 3], [2, 3, 4], [2, 3, 4], [6, 7, 8], [0, 1, 2], [0, 1, 2], [0, 1, 2]], [318, 311, 308, 303, 267, 264, 263]], call assert_equal([['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'], [[1, 2, 3], [2, 3, 4], [2, 3, 4], [6, 7, 8], [0, 1, 2], [0, 1, 2], [0, 1, 2]], [318, 311, 308, 303, 267, 264, 263]],
\ matchfuzzypos(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur')) \ matchfuzzypos(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur'))
call assert_equal([['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'], [[1, 2, 3], [2, 3, 4], [2, 3, 4], [6, 7, 8], [0, 1, 2], [0, 1, 2], [0, 1, 2]], [318, 311, 308, 303, 267, 264, 263]],
\ matchfuzzypos(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:true}))
call assert_equal([['Cursor', 'CurSearch', 'CursorLine', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor'], [[0, 1, 2], [0, 1, 2], [0, 1, 2], [1, 2, 3], [2, 3, 4], [2, 3, 4], [6, 7, 8]], [267, 264, 263, 246, 239, 236, 231]], call assert_equal([['Cursor', 'CurSearch', 'CursorLine', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor'], [[0, 1, 2], [0, 1, 2], [0, 1, 2], [1, 2, 3], [2, 3, 4], [2, 3, 4], [6, 7, 8]], [267, 264, 263, 246, 239, 236, 231]],
\ matchfuzzypos(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:false})) \ matchfuzzypos(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur', {"camelcase": v:false}))
call assert_equal([['things', 'sThings', 'thisThings'], [[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2, 7]], [333, 287, 279]], call assert_equal([['things', 'sThings', 'thisThings'], [[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2, 7]], [333, 287, 279]],
\ matchfuzzypos(['things','sThings', 'thisThings'], 'thin', {'camelcase': v:false})) \ matchfuzzypos(['things','sThings', 'thisThings'], 'thin', {'camelcase': v:false}))
call assert_fails("let x = matchfuzzypos([], 'foo', {'camelcase': []})", 'E475: Invalid value for argument camelcase')
endfunc endfunc
" Test for matchfuzzy() with multibyte characters " Test for matchfuzzy() with multibyte characters
@@ -280,6 +289,7 @@ func Test_matchfuzzy_limit()
call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 2})) call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 2}))
call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 3})) call assert_equal(['2', '2'], x->matchfuzzy('2', #{limit: 3}))
call assert_fails("call matchfuzzy(x, '2', #{limit: '2'})", 'E475:') call assert_fails("call matchfuzzy(x, '2', #{limit: '2'})", 'E475:')
call assert_fails("call matchfuzzy(x, '2', #{limit: []})", 'E475:')
let l = [{'id': 5, 'val': 'crayon'}, {'id': 6, 'val': 'camera'}] let l = [{'id': 5, 'val': 'crayon'}, {'id': 6, 'val': 'camera'}]
call assert_equal([{'id': 5, 'val': 'crayon'}, {'id': 6, 'val': 'camera'}], l->matchfuzzy('c', #{text_cb: {v -> v.val}})) call assert_equal([{'id': 5, 'val': 'crayon'}, {'id': 6, 'val': 'camera'}], l->matchfuzzy('c', #{text_cb: {v -> v.val}}))