Merge remote-tracking branch 'vim/master'

This commit is contained in:
Yee Cheng Chin
2025-08-14 06:47:32 -07:00
36 changed files with 1577 additions and 1405 deletions
+2
View File
@@ -82,6 +82,7 @@ SRC_ALL = \
src/findfile.c \
src/float.c \
src/fold.c \
src/fuzzy.c \
src/getchar.c \
src/gc.c \
src/globals.h \
@@ -291,6 +292,7 @@ SRC_ALL = \
src/proto/findfile.pro \
src/proto/float.pro \
src/proto/fold.pro \
src/proto/fuzzy.pro \
src/proto/getchar.pro \
src/proto/gc.pro \
src/proto/gui.pro \
@@ -1,5 +1,16 @@
vim9script
# Language: Vim9 script
# Contributers: @lacygoill
# Shane-XB-Qian
# Last Change: 2025 Aug 13
#
# Vim Script to handle
# :import, :packadd and :colorscheme
# lines and allows to easily jump to it using gf
#
# see runtime/ftplugin/vim.vim
# Interface {{{1
export def Find(editcmd: string) #{{{2
var curline: string = getline('.')
@@ -9,6 +20,11 @@ export def Find(editcmd: string) #{{{2
return
endif
if curline =~ '^\s*\%(:\s*\)\=colo\%[rscheme]\s'
HandleColoLine(editcmd, curline)
return
endif
if curline =~ '^\s*\%(:\s*\)\=import\s'
HandleImportLine(editcmd, curline)
return
@@ -23,7 +39,7 @@ enddef
#}}}1
# Core {{{1
def HandlePackaddLine(editcmd: string, curline: string) #{{{2
var pat: string = '^\s*packadd!\=\s\+\zs\S\+$'
var pat: string = '\s*\%(:\s*\)\=packadd!\=\s\+\zs\S\+\>\ze'
var plugin: string = curline
->matchstr(pat)
->substitute('^vim-\|\.vim$', '', 'g')
@@ -37,12 +53,9 @@ def HandlePackaddLine(editcmd: string, curline: string) #{{{2
endtry
else
var split: string = editcmd[0] == 'g' ? 'edit' : editcmd[1] == 'g' ? 'tabedit' : 'split'
# In the past, we passed `runtime` to `getcompletion()`, instead of
# `cmdline`. But the output was tricky to use, because it contained
# paths relative to inconsistent root directories.
var files: list<string> = getcompletion($'edit **/plugin/{plugin}.vim', 'cmdline')
var files: list<string> = getcompletion($'plugin/{plugin}', 'runtime')
->map((_, fname: string) => fname->findfile(&rtp)->fnamemodify(':p'))
->filter((_, path: string): bool => filereadable(path))
->map((_, fname: string) => fname->fnamemodify(':p'))
if empty(files)
echo 'Could not find any plugin file for ' .. string(plugin)
return
@@ -51,9 +64,33 @@ def HandlePackaddLine(editcmd: string, curline: string) #{{{2
endif
enddef
def HandleColoLine(editcmd: string, curline: string) #{{{2
var pat: string = '\s*\%(:\s*\)\=colo\%[rscheme]\s\+\zs\S\+\>\ze'
var colo: string = curline->matchstr(pat)
if colo == ''
try
execute 'normal! ' .. editcmd .. 'zv'
catch
Error(v:exception)
return
endtry
else
var split: string = editcmd[0] == 'g' ? 'edit' : editcmd[1] == 'g' ? 'tabedit' : 'split'
var files: list<string> = getcompletion($'colors/{colo}', 'runtime')
->map((_, fname: string) => fname->findfile(&rtp)->fnamemodify(':p'))
->filter((_, path: string): bool => filereadable(path))
if empty(files)
echo 'Could not find any colorscheme file for ' .. string(colo)
return
endif
files->Open(split)
endif
enddef
def HandleImportLine(editcmd: string, curline: string) #{{{2
var fname: string
var import_cmd: string = '^\s*import\s\+\%(autoload\s\+\)\='
var import_cmd: string = '^\s*\%(:\s*\)\=import\s\+\%(autoload\s\+\)\='
var import_alias: string = '\%(\s\+as\s\+\w\+\)\=$'
var import_string: string = import_cmd .. '\([''"]\)\zs.*\ze\1' .. import_alias
var import_expr: string = import_cmd .. '\zs.*\ze' .. import_alias
@@ -132,3 +169,5 @@ def Error(msg: string) #{{{2
echomsg msg
echohl NONE
enddef
# vim: sw=4 et
+1 -4
View File
@@ -1,4 +1,4 @@
*builtin.txt* For Vim version 9.1. Last change: 2025 Aug 10
*builtin.txt* For Vim version 9.1. Last change: 2025 Aug 12
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -7425,9 +7425,6 @@ matchfuzzy({list}, {str} [, {dict}]) *matchfuzzy()*
given sequence.
limit Maximum number of matches in {list} to be
returned. Zero means no limit.
camelcase Use enhanced camel case scoring making results
better suited for completion related to
programming languages. Defaults to v:true.
If {list} is a list of dictionaries, then the optional {dict}
argument supports the following additional items:
+43 -26
View File
@@ -1,4 +1,4 @@
*pattern.txt* For Vim version 9.1. Last change: 2025 Aug 06
*pattern.txt* For Vim version 9.1. Last change: 2025 Aug 13
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1501,34 +1501,51 @@ Finally, these constructs are unique to Perl:
==============================================================================
11. Fuzzy matching *fuzzy-matching*
Fuzzy matching refers to matching strings using a non-exact search string.
Fuzzy matching will match a string, if all the characters in the search string
are present anywhere in the string in the same order. Case is ignored. In a
matched string, other characters can be present between two consecutive
characters in the search string. If the search string has multiple words, then
each word is matched separately. So the words in the search string can be
present in any order in a string.
Fuzzy matching scores how well a string matches a pattern when the pattern
characters appear in order but not necessarily contiguously.
Fuzzy matching assigns a score for each matched string based on the following
criteria:
- The number of sequentially matching characters.
- The number of characters (distance) between two consecutive matching
characters.
- Matches at the beginning of a word
- Matches at a camel case character (e.g. Case in CamelCase)
- Matches after a path separator or a hyphen.
- The number of unmatched characters in a string.
- A full/exact match is preferred.
The matching string with the highest score is returned first.
Example: >
Pattern: "vim"
Candidates: "vim" -> perfect
"vimeo" -> good (v i m)
"voice mail" -> weaker (v _ i _ _ _ m)
"vintage" -> no match (no "m")
<
If the search string has multiple words, each word is matched separately and
may appear in any order in the candidate. For example "get pat" matches
"GetPattern", "PatternGet", "getPattern", "patGetter", "getSomePattern",
"MatchpatternGet", etc.
For example, when you search for the "get pat" string using fuzzy matching, it
will match the strings "GetPattern", "PatternGet", "getPattern", "patGetter",
"getSomePattern", "MatchpatternGet" etc.
The 'ignorecase' and 'smartcase' options do not apply, case is ignored if the
pattern is all lower case.
The functions |matchfuzzy()| and |matchfuzzypos()| can be used to fuzzy search
a string in a List of strings. The matchfuzzy() function returns a List of
matching strings. The matchfuzzypos() functions returns the List of matches,
the matching positions and the fuzzy match scores.
Vim's implementation is based on the algorithm from the fzy project:
https://github.com/jhawthorn/fzy
It uses dynamic programming to compute an optimal score for a given pattern
and candidate.
The algorithm works in two stages:
1. Forward pass
Scan the candidate left to right, tracking the best score for each
pattern position. Matches score higher when they occur at the start
of the candidate, the start of a word (space, underscore, dash,
camelCase), or directly after the previous match.
2. Backward pass
Start from the best-scoring end position and step back to find match
positions, ensuring the alignment is optimal.
Vim extends the original algorithm to support multibyte codepoints, allowing
correct matching for UTF-8 and other encodings.
Time complexity is O(pattern * candidate). Memory usage is proportional
to the same.
The |matchfuzzy()| and |matchfuzzypos()| functions perform fuzzy searching in
a List of strings. |matchfuzzy()| returns the matching strings, while
|matchfuzzypos()| returns the matches along with their positions and scores.
The "f" flag of `:vimgrep` enables fuzzy matching.
+4 -1
View File
@@ -1,4 +1,4 @@
*version9.txt* For Vim version 9.1. Last change: 2025 Aug 08
*version9.txt* For Vim version 9.1. Last change: 2025 Aug 12
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41723,6 +41723,8 @@ Functions: ~
- Add the optional {opts} |Dict| argument to |getchar()| to control: cursor
behaviour, return type and whether or not to simplify the returned key
- |chdir()| allows to optionally specify a scope argument
- |matchfuzzy()| and |matchfuzzypos()| use an improved fuzzy matching
algorithm (same as fzy).
Others: ~
- the regex engines match correctly case-insensitive multi-byte characters
@@ -41736,6 +41738,7 @@ Others: ~
- |gv| works in operator pending mode and does not abort
- The close button shown in the non-GUI 'tabline' will only be visible if the
'mouse' option contains either "a" or any of the flags "n", "v", or "i".
- |C-indenting| handles compound literals.
*added-9.2*
Added ~
+6 -4
View File
@@ -9,6 +9,7 @@
" Last Change: 2025 Aug 07
" 2025 Aug 06 by Vim Project (add gf maps #17881)
" 2025 Aug 08 by Vim Project (add Vim script complete function #17871)
" 2025 Aug 12 by Vim Project (improve vimgoto script #17970))
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -152,7 +153,7 @@ if !exists("no_plugin_maps") && !exists("no_vim_maps")
nnoremap <silent><buffer> [" :call search('\%(^\s*".*\n\)\%(^\s*"\)\@!', "bW")<CR>
xnoremap <silent><buffer> [" :<C-U>exe "normal! gv"<Bar>call search('\%(^\s*".*\n\)\%(^\s*"\)\@!', "bW")<CR>
" Purpose: Handle `:import` and `:packadd` lines in a smarter way. {{{
" Purpose: Handle :import, :colorscheme and :packadd lines in a smarter way. {{{
"
" `:import` is followed by a filename or filepath. Find it.
"
@@ -171,9 +172,10 @@ if !exists("no_plugin_maps") && !exists("no_vim_maps")
" buffer.
" }}}
" We use the `F` variants, instead of the `f` ones, because they're smarter.
nnoremap <silent><buffer> gf :<C-U>call vim#Find('gF')<CR>
nnoremap <silent><buffer> <C-W>f :<C-U>call vim#Find("\<lt>C-W>F")<CR>
nnoremap <silent><buffer> <C-W>gf :<C-U>call vim#Find("\<lt>C-W>gF")<CR>
" See $VIMRUNTIME/autoload/vimgoto.vim
nnoremap <silent><buffer> gf :<C-U>call vimgoto#Find('gF')<CR>
nnoremap <silent><buffer> <C-W>f :<C-U>call vimgoto#Find("\<lt>C-W>F")<CR>
nnoremap <silent><buffer> <C-W>gf :<C-U>call vimgoto#Find("\<lt>C-W>gF")<CR>
endif
" Let the matchit plugin know what items can be matched.
+6 -1
View File
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Python
" Maintainer: Zvezdan Petkovic <zpetkovic@acm.org>
" Last Change: 2025 Aug 11
" Last Change: 2025 Aug 13
" Credits: Neil Schemenauer <nas@python.ca>
" Dmitry Vasiliev
" Rob B
@@ -113,6 +113,10 @@ syn keyword pythonAsync async await
syn match pythonConditional "^\s*\zscase\%(\s\+.*:.*$\)\@="
syn match pythonConditional "^\s*\zsmatch\%(\s\+.*:\s*\%(#.*\)\=$\)\@="
" These names are special by convention. While they aren't real keywords,
" giving them distinct highlighting provides a nice visual cue.
syn keyword pythonClassVar self cls
" Decorators
" A dot must be allowed because of @MyClass.myfunc decorators.
syn match pythonDecorator "@" display contained
@@ -378,6 +382,7 @@ hi def link pythonOperator Operator
hi def link pythonException Exception
hi def link pythonInclude Include
hi def link pythonAsync Statement
hi def link pythonClassVar Identifier
hi def link pythonDecorator Define
hi def link pythonDecoratorName Function
hi def link pythonClass Structure
+1
View File
@@ -113,6 +113,7 @@ SRC += \
findfile.c \
float.c \
fold.c \
fuzzy.c \
getchar.c \
gc.c \
hardcopy.c \
+1
View File
@@ -823,6 +823,7 @@ OBJ = \
$(OUTDIR)/findfile.o \
$(OUTDIR)/float.o \
$(OUTDIR)/fold.o \
$(OUTDIR)/fuzzy.o \
$(OUTDIR)/getchar.o \
$(OUTDIR)/gc.o \
$(OUTDIR)/gui_xim.o \
+4
View File
@@ -732,6 +732,7 @@ OBJ = \
$(OUTDIR)\findfile.obj \
$(OUTDIR)\float.obj \
$(OUTDIR)\fold.obj \
$(OUTDIR)\fuzzy.obj \
$(OUTDIR)\getchar.obj \
$(OUTDIR)\gc.obj \
$(OUTDIR)\gui_xim.obj \
@@ -1616,6 +1617,8 @@ $(OUTDIR)/float.obj: $(OUTDIR) float.c $(INCL)
$(OUTDIR)/fold.obj: $(OUTDIR) fold.c $(INCL)
$(OUTDIR)/fuzzy.obj: $(OUTDIR) fuzzy.c $(INCL)
$(OUTDIR)/getchar.obj: $(OUTDIR) getchar.c $(INCL)
$(OUTDIR)/gc.obj: $(OUTDIR) gc.c $(INCL)
@@ -1961,6 +1964,7 @@ proto.h: \
proto/filepath.pro \
proto/findfile.pro \
proto/float.pro \
proto/fuzzy.pro \
proto/getchar.pro \
proto/gc.pro \
proto/gui_xim.pro \
+6
View File
@@ -529,6 +529,7 @@ SRC = \
findfile.c \
float.c \
fold.c \
fuzzy.c \
getchar.c \
gc.c \
gui_xim.c \
@@ -665,6 +666,7 @@ OBJ = \
[.$(DEST)]findfile.obj \
[.$(DEST)]float.obj \
[.$(DEST)]fold.obj \
[.$(DEST)]fuzzy.obj \
[.$(DEST)]getchar.obj \
[.$(DEST)]gc.obj \
[.$(DEST)]gui_xim.obj \
@@ -1141,6 +1143,10 @@ lua_env :
[.$(DEST)]fold.obj : fold.c vim.h [.$(DEST)]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h gui.h beval.h \
[.proto]gui_beval.pro option.h ex_cmds.h proto.h errors.h globals.h
[.$(DEST)]fuzzy.obj : fuzzy.c vim.h [.$(DEST)]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
errors.h globals.h
[.$(DEST)]getchar.obj : getchar.c vim.h [.$(DEST)]config.h feature.h os_unix.h \
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
+11
View File
@@ -1542,6 +1542,7 @@ BASIC_SRC = \
findfile.c \
float.c \
fold.c \
fuzzy.c \
getchar.c \
gc.c \
gui_xim.c \
@@ -1720,6 +1721,7 @@ OBJ_COMMON = \
objects/findfile.o \
objects/float.o \
objects/fold.o \
objects/fuzzy.o \
objects/getchar.o \
objects/gc.o \
objects/gui_xim.o \
@@ -1905,6 +1907,7 @@ PRO_AUTO = \
findfile.pro \
float.pro \
fold.pro \
fuzzy.pro \
getchar.pro \
gc.pro \
gui_xim.pro \
@@ -3340,6 +3343,9 @@ objects/float.o: float.c
objects/fold.o: fold.c
$(CCC) -o $@ fold.c
objects/fuzzy.o: fuzzy.c
$(CCC) -o $@ fuzzy.c
objects/getchar.o: getchar.c
$(CCC) -o $@ getchar.c
@@ -4117,6 +4123,11 @@ objects/fold.o: fold.c vim.h protodef.h auto/config.h feature.h os_unix.h \
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
libvterm/include/vterm_keycodes.h xdiff/xdiff.h xdiff/../vim.h alloc.h \
ex_cmds.h spell.h proto.h globals.h errors.h
objects/fuzzy.o: fuzzy.c vim.h protodef.h auto/config.h feature.h os_unix.h \
auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
globals.h errors.h
objects/getchar.o: getchar.c vim.h protodef.h auto/config.h feature.h os_unix.h \
os_mac.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
+1
View File
@@ -48,6 +48,7 @@ fileio.c | reading and writing files
filepath.c | dealing with file names and paths
findfile.c | search for files in 'path'
fold.c | folding
fuzzy.c | fuzzy matching
getchar.c | getting characters and key mapping
gc.c | garbage collection
help.c | vim help related functions
+4 -2
View File
@@ -2949,12 +2949,14 @@ ExpandBufnames(
{
p = NULL;
// first try matching with the short file name
if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0)
if ((score = fuzzy_match_str(buf->b_sfname, pat))
!= FUZZY_SCORE_NONE)
p = buf->b_sfname;
if (p == NULL)
{
// next try matching with the full path file name
if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0)
if ((score = fuzzy_match_str(buf->b_ffname, pat))
!= FUZZY_SCORE_NONE)
p = buf->b_ffname;
}
}
+82 -20
View File
@@ -690,10 +690,9 @@ cin_islabel(void) // XXX
/*
* Return TRUE if string "s" ends with the string "find", possibly followed by
* white space and comments. Skip strings and comments.
* Ignore "ignore" after "find" if it's not NULL.
*/
static int
cin_ends_in(char_u *s, char_u *find, char_u *ignore)
cin_ends_in(char_u *s, char_u *find)
{
char_u *p = s;
char_u *r;
@@ -705,8 +704,6 @@ cin_ends_in(char_u *s, char_u *find, char_u *ignore)
if (STRNCMP(p, find, len) == 0)
{
r = skipwhite(p + len);
if (ignore != NULL && STRNCMP(r, ignore, STRLEN(ignore)) == 0)
r = skipwhite(r + STRLEN(ignore));
if (cin_nocode(r))
return TRUE;
}
@@ -717,9 +714,77 @@ cin_ends_in(char_u *s, char_u *find, char_u *ignore)
}
/*
* Recognize structure initialization and enumerations:
* Strings can be concatenated with comments between:
* "string0" |*comment*| "string1"
*/
static char_u *
cin_skip_comment_and_string(char_u *s)
{
char_u *r = NULL, *p = s;
do
{
r = p;
p = cin_skipcomment(p);
if (*p)
p = skip_string(p);
} while (p != r);
return p;
}
/*
* Recognize structure or compound literal initialization:
* =|return [&][(typecast)] [{]
* The number of opening braces is arbitrary.
*/
static int
cin_is_compound_init(char_u *s)
{
char_u *p = s, *r = NULL;
while (*p)
{
if (*p == '=')
p = r = cin_skipcomment(p + 1);
else if (!STRNCMP(p, "return", 6) && !vim_isIDc(p[6])
&& (p == s || (p > s && !vim_isIDc(p[-1]))))
p = r = cin_skipcomment(p + 6);
else
p = cin_skip_comment_and_string(p + 1);
}
if (!r)
return FALSE;
p = r; // p points now after '=' or "return"
if (cin_nocode(p))
return TRUE;
if (*p == '&')
p = cin_skipcomment(p + 1);
if (*p == '(') // skip a typecast
{
int open_count = 1;
do
{
p = cin_skip_comment_and_string(p + 1);
if (cin_nocode(p))
return TRUE;
open_count += (*p == '(') - (*p == ')');
} while (open_count);
p = cin_skipcomment(p + 1);
if (cin_nocode(p))
return TRUE;
}
while (*p == '{')
p = cin_skipcomment(p + 1);
return cin_nocode(p);
}
/*
* Recognize enumerations:
* "[typedef] [static|public|protected|private] enum"
* "[typedef] [static|public|protected|private] = {"
* Call another function to recognize structure initialization.
*/
static int
cin_isinit(void)
@@ -753,10 +818,7 @@ cin_isinit(void)
if (cin_starts_with(s, "enum"))
return TRUE;
if (cin_ends_in(s, (char_u *)"=", (char_u *)"{"))
return TRUE;
return FALSE;
return cin_is_compound_init(s);
}
// Maximum number of lines to search back for a "namespace" line.
@@ -1634,7 +1696,7 @@ get_baseclass_amount(int col)
if (find_last_paren(ml_get_curline(), '(', ')')
&& (trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL)
amount = get_indent_lnum(trypos->lnum); // XXX
if (!cin_ends_in(ml_get_curline(), (char_u *)",", NULL))
if (!cin_ends_in(ml_get_curline(), (char_u *)","))
amount += curbuf->b_ind_cpp_baseclass;
}
else
@@ -2505,7 +2567,7 @@ get_c_indent(void)
cur_amount = MAXCOL;
l = ml_get(our_paren_pos.lnum);
if (curbuf->b_ind_unclosed_wrapped
&& cin_ends_in(l, (char_u *)"(", NULL))
&& cin_ends_in(l, (char_u *)"("))
{
// look for opening unmatched paren, indent one level
// for each additional level
@@ -3702,8 +3764,8 @@ term_again:
&& !cin_nocode(theline)
&& vim_strchr(theline, '{') == NULL
&& vim_strchr(theline, '}') == NULL
&& !cin_ends_in(theline, (char_u *)":", NULL)
&& !cin_ends_in(theline, (char_u *)",", NULL)
&& !cin_ends_in(theline, (char_u *)":")
&& !cin_ends_in(theline, (char_u *)",")
&& cin_isfuncdecl(NULL, cur_curpos.lnum + 1,
cur_curpos.lnum + 1)
&& !cin_isterminated(theline, FALSE, TRUE))
@@ -3764,7 +3826,7 @@ term_again:
// } foo,
// bar;
n = 0;
if (cin_ends_in(l, (char_u *)",", NULL)
if (cin_ends_in(l, (char_u *)",")
|| (*l != NUL && (n = l[STRLEN(l) - 1]) == '\\'))
{
// take us back to opening paren
@@ -3812,14 +3874,14 @@ term_again:
// comments) align at column 0. For example:
// char *string_array[] = { "foo",
// / * x * / "b};ar" }; / * foobar * /
if (cin_ends_in(l, (char_u *)"};", NULL))
if (cin_ends_in(l, (char_u *)"};"))
break;
// If the previous line ends on '[' we are probably in an
// array constant:
// something = [
// 234, <- extra indent
if (cin_ends_in(l, (char_u *)"[", NULL))
if (cin_ends_in(l, (char_u *)"["))
{
amount = get_indent() + ind_continuation;
break;
@@ -3840,7 +3902,7 @@ term_again:
break;
}
if (curwin->w_cursor.lnum > 0
&& cin_ends_in(look, (char_u *)"}", NULL))
&& cin_ends_in(look, (char_u *)"}"))
break;
curwin->w_cursor = curpos_save;
@@ -3860,10 +3922,10 @@ term_again:
// int foo,
// bar;
// indent_to_0 here;
if (cin_ends_in(l, (char_u *)";", NULL))
if (cin_ends_in(l, (char_u *)";"))
{
l = ml_get(curwin->w_cursor.lnum - 1);
if (cin_ends_in(l, (char_u *)",", NULL)
if (cin_ends_in(l, (char_u *)",")
|| (*l != NUL && l[STRLEN(l) - 1] == '\\'))
break;
l = ml_get_curline();
+2 -2
View File
@@ -3624,7 +3624,7 @@ ExpandGenericExt(
else
{
score = fuzzy_match_str(str, pat);
match = (score != 0);
match = (score != FUZZY_SCORE_NONE);
}
}
else
@@ -4034,7 +4034,7 @@ ExpandUserDefined(
else
{
score = fuzzy_match_str(s, pat);
match = (score != 0);
match = (score != FUZZY_SCORE_NONE);
}
}
else
+5 -5
View File
@@ -9448,8 +9448,8 @@ exec_normal(int was_typed, int use_vpeekc, int may_use_terminal_loop UNUSED)
ex_checkpath(exarg_T *eap)
{
find_pattern_in_path(NULL, 0, 0, FALSE, FALSE, CHECK_PATH, 1L,
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
(linenr_T)1, (linenr_T)MAXLNUM, eap->forceit);
eap->forceit ? ACTION_SHOW_ALL : ACTION_SHOW,
(linenr_T)1, (linenr_T)MAXLNUM, eap->forceit, FALSE);
}
#if defined(FEAT_QUICKFIX)
@@ -9517,9 +9517,9 @@ ex_findpat(exarg_T *eap)
}
if (!eap->skip)
find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
whole, !eap->forceit,
*eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
n, action, eap->line1, eap->line2, eap->forceit);
whole, !eap->forceit,
*eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY, n, action,
eap->line1, eap->line2, eap->forceit, FALSE);
}
#endif
+1 -1
View File
@@ -236,7 +236,7 @@
/*
* +cscope Unix only: Cscope support.
*/
#if defined(UNIX) && defined(FEAT_HUGE) && defined(ENABLE_CSCOPE) && !defined(MACOS_X)
#if defined(UNIX) && defined(FEAT_HUGE) && defined(ENABLE_CSCOPE)
# define FEAT_CSCOPE
#endif
+1152
View File
File diff suppressed because it is too large Load Diff
+23 -25
View File
@@ -966,7 +966,7 @@ ins_compl_add(
// current match in the list of matches .
if (compl_first_match == NULL)
match->cp_next = match->cp_prev = NULL;
else if (cfc_has_mode() && score > 0 && compl_get_longest)
else if (cfc_has_mode() && score != FUZZY_SCORE_NONE && compl_get_longest)
{
current = compl_first_match->cp_next;
prev = compl_first_match;
@@ -1193,7 +1193,8 @@ ins_compl_add_matches(
for (int i = 0; i < num_matches && add_r != FAIL; i++)
{
add_r = ins_compl_add(matches[i], -1, NULL, NULL, NULL, dir,
CP_FAST | (icase ? CP_ICASE : 0), FALSE, NULL, 0);
CP_FAST | (icase ? CP_ICASE : 0), FALSE, NULL,
FUZZY_SCORE_NONE);
if (add_r == OK)
// if dir was BACKWARD then honor it just once
dir = FORWARD;
@@ -1430,7 +1431,7 @@ cp_compare_nearest(const void* a, const void* b)
{
int score_a = ((compl_T*)a)->cp_score;
int score_b = ((compl_T*)b)->cp_score;
if (score_a == 0 || score_b == 0)
if (score_a == FUZZY_SCORE_NONE || score_b == FUZZY_SCORE_NONE)
return 0;
return (score_a > score_b) ? 1 : (score_a < score_b) ? -1 : 0;
}
@@ -1627,7 +1628,7 @@ ins_compl_build_pum(void)
&& (leader->string == NULL
|| ins_compl_equal(compl, leader->string,
(int)leader->length)
|| (fuzzy_filter && compl->cp_score > 0)))
|| (fuzzy_filter && compl->cp_score != FUZZY_SCORE_NONE)))
{
// Limit number of items from each source if max_items is set.
int match_limit_exceeded = FALSE;
@@ -2001,7 +2002,7 @@ thesaurus_add_words_in_line(
if (wstart != skip_word)
{
status = ins_compl_add_infercase(wstart, (int)(ptr - wstart), p_ic,
fname, dir, FALSE, 0);
fname, dir, FALSE, FUZZY_SCORE_NONE);
if (status == FAIL)
break;
}
@@ -2042,8 +2043,7 @@ ins_compl_files(
leader_len = (int)ins_compl_leader_len();
}
for (i = 0; i < count && !got_int && !compl_interrupted
&& !compl_time_slice_expired; i++)
for (i = 0; i < count && !got_int && !ins_compl_interrupted(); i++)
{
fp = mch_fopen((char *)files[i], "r"); // open dictionary file
if (flags != DICT_EXACT && !shortmess(SHM_COMPLETIONSCAN)
@@ -2060,7 +2060,7 @@ ins_compl_files(
// Read dictionary file line by line.
// Check each line for a match.
while (!got_int && !compl_interrupted && !compl_time_slice_expired
while (!got_int && !ins_compl_interrupted()
&& !vim_fgets(buf, LSIZE, fp))
{
ptr = buf;
@@ -2073,7 +2073,7 @@ ins_compl_files(
: find_word_end(ptr);
add_r = ins_compl_add_infercase(regmatch->startp[0],
(int)(ptr - regmatch->startp[0]),
p_ic, files[i], *dir, FALSE, 0);
p_ic, files[i], *dir, FALSE, FUZZY_SCORE_NONE);
if (thesaurus)
{
// For a thesaurus, add all the words in the line
@@ -2297,7 +2297,7 @@ ins_compl_init_get_longest(void)
int
ins_compl_interrupted(void)
{
return compl_interrupted;
return compl_interrupted || compl_time_slice_expired;
}
/*
@@ -3667,7 +3667,7 @@ ins_compl_add_tv(typval_T *tv, int dir, int fast)
return FAIL;
}
status = ins_compl_add(word, -1, NULL, cptext,
&user_data, dir, flags, dup, user_hl, 0);
&user_data, dir, flags, dup, user_hl, FUZZY_SCORE_NONE);
if (status != OK)
clear_tv(&user_data);
return status;
@@ -3762,7 +3762,7 @@ set_completion(colnr_T startcol, list_T *list)
compl_orig_text.length = (size_t)compl_length;
if (ins_compl_add(compl_orig_text.string,
(int)compl_orig_text.length, NULL, NULL, NULL, 0,
flags | CP_FAST, FALSE, NULL, 0) != OK)
flags | CP_FAST, FALSE, NULL, FUZZY_SCORE_NONE) != OK)
return;
ctrl_x_mode = CTRL_X_EVAL;
@@ -3845,10 +3845,7 @@ f_complete_check(typval_T *argvars UNUSED, typval_T *rettv)
RedrawingDisabled = 0;
ins_compl_check_keys(0, TRUE);
if (compl_autocomplete && compl_time_slice_expired)
rettv->vval.v_number = TRUE;
else
rettv->vval.v_number = ins_compl_interrupted();
rettv->vval.v_number = ins_compl_interrupted();
RedrawingDisabled = save_RedrawingDisabled;
}
@@ -4466,7 +4463,7 @@ get_next_include_file_completion(int compl_type)
(compl_type == CTRL_X_PATH_DEFINES
&& !(compl_cont_status & CONT_SOL))
? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
(linenr_T)1, (linenr_T)MAXLNUM, FALSE);
(linenr_T)1, (linenr_T)MAXLNUM, FALSE, compl_autocomplete);
}
#endif
@@ -4755,7 +4752,7 @@ get_next_filename_completion(void)
{
ptr = matches[i];
score = fuzzy_match_str(ptr, leader);
if (score > 0)
if (score != FUZZY_SCORE_NONE)
{
if (ga_grow(&fuzzy_indices, 1) == OK)
{
@@ -4967,7 +4964,7 @@ get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
int in_fuzzy_collect = (cfc_has_mode() && compl_length > 0)
|| ((get_cot_flags() & COT_FUZZY) && compl_autocomplete);
char_u *leader = ins_compl_leader();
int score = 0;
int score = FUZZY_SCORE_NONE;
int in_curbuf = st->ins_buf == curbuf;
// If 'infercase' is set, don't use 'smartcase' here
@@ -5061,7 +5058,6 @@ get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_pos)
score = st->cur_match_pos->lnum - curwin->w_cursor.lnum;
if (score < 0)
score = -score;
score++;
}
if (ins_compl_add_infercase(ptr, len, p_ic,
@@ -5167,7 +5163,7 @@ get_register_completion(void)
compl_orig_text.length) == 0))
{
if (ins_compl_add_infercase(str, str_len, p_ic, NULL,
dir, FALSE, 0) == OK)
dir, FALSE, FUZZY_SCORE_NONE) == OK)
dir = FORWARD;
}
}
@@ -5206,7 +5202,7 @@ get_register_completion(void)
compl_orig_text.length) == 0)))
{
if (ins_compl_add_infercase(p, len, p_ic, NULL,
dir, FALSE, 0) == OK)
dir, FALSE, FUZZY_SCORE_NONE) == OK)
dir = FORWARD;
}
@@ -5576,7 +5572,8 @@ ins_compl_get_exp(pos_T *ini)
// For `^P` completion, reset `compl_curr_match` to the head to avoid
// mixing matches from different sources.
if (!compl_dir_forward())
while (compl_curr_match->cp_prev)
while (compl_curr_match->cp_prev
&& !match_at_original_text(compl_curr_match->cp_prev))
compl_curr_match = compl_curr_match->cp_prev;
}
cpt_sources_index = -1;
@@ -5974,7 +5971,8 @@ find_next_completion_match(
&& leader->string != NULL
&& !ins_compl_equal(compl_shown_match,
leader->string, (int)leader->length)
&& !(compl_fuzzy_match && compl_shown_match->cp_score > 0))
&& !(compl_fuzzy_match
&& compl_shown_match->cp_score != FUZZY_SCORE_NONE))
++todo;
else
// Remember a matching item.
@@ -6955,7 +6953,7 @@ ins_compl_start(void)
if (compl_orig_text.string == NULL
|| ins_compl_add(compl_orig_text.string,
(int)compl_orig_text.length,
NULL, NULL, NULL, 0, flags, FALSE, NULL, 0) != OK)
NULL, NULL, NULL, 0, flags, FALSE, NULL, FUZZY_SCORE_NONE) != OK)
{
VIM_CLEAR_STRING(compl_pattern);
VIM_CLEAR_STRING(compl_orig_text);
+2 -2
View File
@@ -1433,7 +1433,7 @@ ExpandMappings(
else
{
score = fuzzy_match_str(p, pat);
match = (score != 0);
match = (score != FUZZY_SCORE_NONE);
}
if (!match)
@@ -1480,7 +1480,7 @@ ExpandMappings(
else
{
score = fuzzy_match_str(p, pat);
match = (score != 0);
match = (score != FUZZY_SCORE_NONE);
}
if (!match)
+1 -1
View File
@@ -4480,7 +4480,7 @@ nv_brackets(cmdarg_T *cap)
SAFE_islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
(linenr_T)MAXLNUM,
FALSE);
FALSE, FALSE);
vim_free(ptr);
curwin->w_set_curswant = TRUE;
}
+1 -1
View File
@@ -8116,7 +8116,7 @@ match_str(
int score;
score = fuzzy_match_str(str, fuzzystr);
if (score != 0)
if (score != FUZZY_SCORE_NONE)
{
if (!test_only)
{
+1
View File
@@ -188,6 +188,7 @@ void mbyte_im_set_active(int active_arg);
# if defined(FEAT_CRYPT) || defined(FEAT_PERSISTENT_UNDO)
# include "sha256.pro"
# endif
# include "fuzzy.pro"
# include "search.pro"
# ifdef FEAT_SIGNS
# include "sign.pro"
+11
View File
@@ -0,0 +1,11 @@
/* fuzzy.c */
int fuzzy_match(char_u *str, char_u *pat_arg, int matchseq, int *outScore, int_u *matches, int maxMatches);
void f_matchfuzzy(typval_T *argvars, typval_T *rettv);
void f_matchfuzzypos(typval_T *argvars, typval_T *rettv);
int fuzzy_match_str(char_u *str, char_u *pat);
garray_T *fuzzy_match_str_with_pos(char_u *str, char_u *pat);
int fuzzy_match_str_in_line(char_u **ptr, char_u *pat, int *len, pos_T *current_pos, int *score);
int search_for_fuzzy_match(buf_T *buf, pos_T *pos, char_u *pattern, int dir, pos_T *start_pos, int *len, char_u **ptr, int *score);
void fuzmatch_str_free(fuzmatch_str_T *fuzmatch, int count);
int fuzzymatches_to_strmatches(fuzmatch_str_T *fuzmatch, char_u ***matches, int count, int funcsort);
/* vim: set ft=c : */
+1 -10
View File
@@ -33,17 +33,8 @@ int check_linecomment(char_u *line);
void showmatch(int c);
int current_search(long count, int forward);
int linewhite(linenr_T lnum);
void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum, int forceit);
void find_pattern_in_path(char_u *ptr, int dir, int len, int whole, int skip_comments, int type, long count, int action, linenr_T start_lnum, linenr_T end_lnum, int forceit, int silent);
spat_T *get_spat(int idx);
int get_spat_last_idx(void);
void f_searchcount(typval_T *argvars, typval_T *rettv);
int fuzzy_match(char_u *str, char_u *pat_arg, int matchseq, int *outScore, int_u *matches, int maxMatches, int camelcase);
void f_matchfuzzy(typval_T *argvars, typval_T *rettv);
void f_matchfuzzypos(typval_T *argvars, typval_T *rettv);
int fuzzy_match_str(char_u *str, char_u *pat);
garray_T *fuzzy_match_str_with_pos(char_u *str, char_u *pat);
int fuzzy_match_str_in_line(char_u **ptr, char_u *pat, int *len, pos_T *current_pos, int *score);
int search_for_fuzzy_match(buf_T *buf, pos_T *pos, char_u *pattern, int dir, pos_T *start_pos, int *len, char_u **ptr, int *score);
void fuzmatch_str_free(fuzmatch_str_T *fuzmatch, int count);
int fuzzymatches_to_strmatches(fuzmatch_str_T *fuzmatch, char_u ***matches, int count, int funcsort);
/* vim: set ft=c : */
+4 -4
View File
@@ -6429,8 +6429,8 @@ vgr_match_buflines(
long lnum;
colnr_T col;
int pat_len = (int)STRLEN(spat);
if (pat_len > MAX_FUZZY_MATCHES)
pat_len = MAX_FUZZY_MATCHES;
if (pat_len > FUZZY_MATCH_MAX_LEN)
pat_len = FUZZY_MATCH_MAX_LEN;
for (lnum = 1; lnum <= buf->b_ml.ml_line_count && *tomatch > 0; ++lnum)
{
@@ -6483,13 +6483,13 @@ vgr_match_buflines(
char_u *str = ml_get_buf(buf, lnum, FALSE);
colnr_T linelen = ml_get_buf_len(buf, lnum);
int score;
int_u matches[MAX_FUZZY_MATCHES];
int_u matches[FUZZY_MATCH_MAX_LEN];
int_u sz = ARRAY_LENGTH(matches);
// Fuzzy string match
CLEAR_FIELD(matches);
while (fuzzy_match(str + col, spat, FALSE, &score,
matches, sz, TRUE) > 0)
matches, sz) > 0)
{
// Pass the buffer number so that it gets used even for a
// dummy buffer, unless duplicate_name is set, then the
+7 -1203
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -3224,7 +3224,7 @@ func Test_fuzzy_completion_bufname_fullpath()
call assert_equal('"b CmdStateFile', @:)
set wildoptions=fuzzy
call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
call assert_match('Xcmd/Xstate/Xfile.js$', @:)
call assert_equal('"b CmdStateFile', @:)
cd -
set wildoptions&
endfunc
@@ -3502,7 +3502,7 @@ func Test_fuzzy_completion_mapname()
nmap <Plug>state :
nmap <Plug>FendingOff :
call feedkeys(":nmap <Plug>fo\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff <Plug>goformat <Plug>fendoff", @:)
call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff <Plug>fendoff <Plug>goformat", @:)
nunmap <Plug>format
nunmap <Plug>goformat
nunmap <Plug>TestFOrmat
@@ -3674,7 +3674,7 @@ func Test_fuzzy_completion_cmd_sort_results()
command T123FendingOff :
set wildoptions=fuzzy
call feedkeys(":T123fo\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal('"T123format T123TestFOrmat T123FendingOff T123goformat T123fendoff', @:)
call assert_equal('"T123format T123TestFOrmat T123FendingOff T123fendoff T123goformat', @:)
delcommand T123format
delcommand T123goformat
delcommand T123TestFOrmat
+25
View File
@@ -119,6 +119,31 @@ func Test_userlabel_indent()
close!
endfunc
" Test that struct members are aligned
func Test_struct_indent()
new
call setline(1, ['struct a a = {', '1,', '1,'])
normal gg=G
call assert_equal(getline(2), getline(3))
call setline(1, 'a = (struct a) {')
normal gg=G
call assert_equal(getline(2), getline(3))
call setline(1, 'void *ptr = &(static struct a) {{')
normal gg=G
call assert_equal(getline(2), getline(3))
call setline(1, 'a = (macro(arg1, "str)))")) {')
normal gg=G
call assert_equal(getline(2), getline(3))
call setline(1, 'return (struct a) {')
normal gg=G
call assert_equal(getline(2), getline(3))
close!
endfunc
" Test for 'copyindent'
func Test_copyindent()
new
+64 -67
View File
@@ -14,11 +14,11 @@ func Test_matchfuzzy()
call assert_equal(['crayon', 'camera'], matchfuzzy(['camera', 'crayon'], 'cra'))
call assert_equal(['aabbaa', 'aaabbbaaa', 'aaaabbbbaaaa', 'aba'], matchfuzzy(['aba', 'aabbaa', 'aaabbbaaa', 'aaaabbbbaaaa'], 'aa'))
call assert_equal(['one'], matchfuzzy(['one', 'two'], 'one'))
call assert_equal(['oneTwo', 'onetwo'], matchfuzzy(['onetwo', 'oneTwo'], 'oneTwo'))
call assert_equal(['onetwo', 'one_two'], matchfuzzy(['onetwo', 'one_two'], 'oneTwo'))
call assert_equal(['oneTwo'], matchfuzzy(['onetwo', 'oneTwo'], 'oneTwo'))
call assert_equal([], matchfuzzy(['onetwo', 'one_two'], 'oneTwo'))
call assert_equal(['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], matchfuzzy(['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'], 'aa'))
call assert_equal(256, matchfuzzy([repeat('a', 256)], repeat('a', 256))[0]->len())
call assert_equal([], matchfuzzy([repeat('a', 300)], repeat('a', 257)))
call assert_equal([repeat('a', 300)], matchfuzzy([repeat('a', 300)], repeat('a', 257)))
" full match has highest score
call assert_equal(['Cursor', 'lCursor'], matchfuzzy(["hello", "lCursor", "Cursor"], "Cursor"))
" matches with same score should not be reordered
@@ -26,8 +26,7 @@ func Test_matchfuzzy()
call assert_equal(l, l->matchfuzzy('abc'))
" Tests for match preferences
" preference for camel case match
call assert_equal(['oneTwo', 'onetwo'], ['onetwo', 'oneTwo']->matchfuzzy('onetwo'))
call assert_equal(['onetwo', 'oneTwo'], ['onetwo', 'oneTwo']->matchfuzzy('onetwo'))
" preference for match after a separator (_ or space)
call assert_equal(['onetwo', 'one_two', 'one two'], ['onetwo', 'one_two', 'one two']->matchfuzzy('onetwo'))
" preference for leading letter match
@@ -43,7 +42,7 @@ func Test_matchfuzzy()
" gap penalty
call assert_equal(['xxayybxxxx', 'xxayyybxxx', 'xxayyyybxx'], ['xxayyyybxx', 'xxayyybxxx', 'xxayybxxxx']->matchfuzzy('ab'))
" path separator vs word separator
call assert_equal(['color/setup.vim', 'color\\setup.vim', 'color setup.vim', 'color_setup.vim', 'colorsetup.vim'], matchfuzzy(['colorsetup.vim', 'color setup.vim', 'color/setup.vim', 'color_setup.vim', 'color\\setup.vim'], 'setup.vim'))
call assert_equal(['color/setup.vim', 'color setup.vim', 'color_setup.vim', 'colorsetup.vim', 'color\\setup.vim'], matchfuzzy(['colorsetup.vim', 'color setup.vim', 'color/setup.vim', 'color_setup.vim', 'color\\setup.vim'], 'setup.vim'))
" match multiple words (separated by space)
call assert_equal(['foo bar baz'], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzy('baz foo'))
@@ -85,15 +84,16 @@ func Test_matchfuzzy()
call assert_fails("let x = matchfuzzy(l, 'foo', {'key' : 'name'})", 'E730:')
" camelcase
call assert_equal(['lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'Cursor', 'CurSearch', 'CursorLine'],
\ 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}))
\ matchfuzzy(['Cursor', 'lCursor', 'shCurlyIn', 'shCurlyError', 'TracesCursor', 'CurSearch', 'CursorLine'], 'Cur'))
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')
\ matchfuzzy(['things','sThings', 'thisThings'], 'thin'))
call assert_equal(['MyTestCase', 'mytestcase'], matchfuzzy(['mytestcase', 'MyTestCase'], 'mtc'))
call assert_equal(['MyTestCase', 'mytestcase'], matchfuzzy(['MyTestCase', 'mytestcase'], 'mtc'))
call assert_equal(['MyTest'], matchfuzzy(['Mytest', 'mytest', 'MyTest'], 'MyT'))
call assert_equal(['CamelCaseMatchIngAlg'],
\ matchfuzzy(['CamelCaseMatchIngAlg', 'camelCaseMatchingAlg', 'camelcasematchingalg'], 'CamelCase'))
call assert_equal(['SomeWord', 'PrefixSomeWord'], matchfuzzy(['PrefixSomeWord', 'SomeWord'], 'somewor'))
" Test in latin1 encoding
let save_enc = &encoding
@@ -104,50 +104,57 @@ endfunc
" Test for the matchfuzzypos() function
func Test_matchfuzzypos()
call assert_equal([['curl', 'world'], [[2,3], [2,3]], [178, 177]], matchfuzzypos(['world', 'curl'], 'rl'))
call assert_equal([['curl', 'world'], [[2,3], [2,3]], [178, 177]], matchfuzzypos(['world', 'one', 'curl'], 'rl'))
call assert_equal([['curl', 'world'], [[2,3], [2,3]], [990, 985]], matchfuzzypos(['world', 'curl'], 'rl'))
call assert_equal([['curl', 'world'], [[2,3], [2,3]], [990, 985]], matchfuzzypos(['world', 'one', 'curl'], 'rl'))
call assert_equal([['hello', 'hello world hello world'],
\ [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], [500, 382]],
\ [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]], [2147483647, 4810]],
\ matchfuzzypos(['hello world hello world', 'hello', 'world'], 'hello'))
call assert_equal([['aaaaaaa'], [[0, 1, 2]], [266]], matchfuzzypos(['aaaaaaa'], 'aaa'))
call assert_equal([['a b'], [[0, 3]], [269]], matchfuzzypos(['a b'], 'a b'))
call assert_equal([['a b'], [[0, 3]], [269]], matchfuzzypos(['a b'], 'a b'))
call assert_equal([['a b'], [[0]], [137]], matchfuzzypos(['a b'], ' a '))
call assert_equal([['aaaaaaa'], [[0, 1, 2]], [2880]], matchfuzzypos(['aaaaaaa'], 'aaa'))
call assert_equal([['a b'], [[0, 3]], [1670]], matchfuzzypos(['a b'], 'a b'))
call assert_equal([['a b'], [[0, 3]], [1670]], matchfuzzypos(['a b'], 'a b'))
call assert_equal([['a b'], [[0]], [885]], matchfuzzypos(['a b'], ' a '))
call assert_equal([[], [], []], matchfuzzypos(['a b'], ' '))
call assert_equal([[], [], []], matchfuzzypos(['world', 'curl'], 'ab'))
let x = matchfuzzypos([repeat('a', 256)], repeat('a', 256))
call assert_equal(range(256), x[1][0])
call assert_equal([[], [], []], matchfuzzypos([repeat('a', 300)], repeat('a', 257)))
" fuzzy matches limited to 1024 chars
let matches = matchfuzzypos([repeat('a', 1030)], repeat('a', 1025))
call assert_equal([repeat('a', 1030)], matches[0])
call assert_equal(1024, len(matches[1][0]))
call assert_equal(1023, matches[1][0][1023])
call assert_equal([[], [], []], matchfuzzypos([], 'abc'))
call assert_equal([[], [], []], matchfuzzypos(['abc'], ''))
" match in a long string
call assert_equal([[repeat('x', 300) .. 'abc'], [[300, 301, 302]], [155]],
call assert_equal([[repeat('x', 300) .. 'abc'], [[300, 301, 302]], [500]],
\ matchfuzzypos([repeat('x', 300) .. 'abc'], 'abc'))
" preference for camel case match
call assert_equal([['xabcxxaBc'], [[6, 7, 8]], [269]], matchfuzzypos(['xabcxxaBc'], 'abc'))
call assert_equal([['xabcxxaBc'], [[7, 8]], [1665]], matchfuzzypos(['xabcxxaBc'], 'bc'))
" preference for match after a separator (_ or space)
call assert_equal([['xabx_ab'], [[5, 6]], [195]], matchfuzzypos(['xabx_ab'], 'ab'))
call assert_equal([['xabx_ab'], [[5, 6]], [1775]], matchfuzzypos(['xabx_ab'], 'ab'))
" preference for leading letter match
call assert_equal([['abcxabc'], [[0, 1]], [200]], matchfuzzypos(['abcxabc'], 'ab'))
call assert_equal([['abcxabc'], [[0, 1]], [1875]], matchfuzzypos(['abcxabc'], 'ab'))
" preference for sequential match
call assert_equal([['aobncedone'], [[7, 8, 9]], [233]], matchfuzzypos(['aobncedone'], 'one'))
call assert_equal([['aobncedone'], [[7, 8, 9]], [1965]], matchfuzzypos(['aobncedone'], 'one'))
" best recursive match
call assert_equal([['xoone'], [[2, 3, 4]], [243]], matchfuzzypos(['xoone'], 'one'))
call assert_equal([['xoone'], [[2, 3, 4]], [1990]], matchfuzzypos(['xoone'], 'one'))
" match multiple words (separated by space)
call assert_equal([['foo bar baz'], [[8, 9, 10, 0, 1, 2]], [519]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('baz foo'))
call assert_equal([['foo bar baz'], [[8, 9, 10, 0, 1, 2]], [5620]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('baz foo'))
call assert_equal([[], [], []], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('baz foo', {'matchseq': 1}))
call assert_equal([['foo bar baz'], [[0, 1, 2, 8, 9, 10]], [519]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz'))
call assert_equal([['foo bar baz'], [[0, 1, 2, 3, 4, 5, 10]], [476]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz', {'matchseq': 1}))
call assert_equal([['foo bar baz'], [[0, 1, 2, 8, 9, 10]], [5620]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz'))
call assert_equal([['foo bar baz'], [[0, 1, 2, 3, 4, 9, 10]], [6660]], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('foo baz', {'matchseq': 1}))
call assert_equal([[], [], []], ['foo bar baz', 'foo', 'foo bar', 'baz bar']->matchfuzzypos('one two'))
call assert_equal([[], [], []], ['foo bar']->matchfuzzypos(" \t "))
call assert_equal([['grace'], [[1, 2, 3, 4, 2, 3, 4, 0, 1, 2, 3, 4]], [1057]], ['grace']->matchfuzzypos('race ace grace'))
call assert_equal([['grace'], [[1, 2, 3, 4, 2, 3, 4, 0, 1, 2, 3, 4]], [2147483647]], ['grace']->matchfuzzypos('race ace grace'))
let l = [{'id' : 5, 'val' : 'crayon'}, {'id' : 6, 'val' : 'camera'}]
call assert_equal([[{'id' : 6, 'val' : 'camera'}], [[0, 1, 2]], [267]],
call assert_equal([[{'id' : 6, 'val' : 'camera'}], [[0, 1, 2]], [2885]],
\ matchfuzzypos(l, 'cam', {'text_cb' : {v -> v.val}}))
call assert_equal([[{'id' : 6, 'val' : 'camera'}], [[0, 1, 2]], [267]],
call assert_equal([[{'id' : 6, 'val' : 'camera'}], [[0, 1, 2]], [2885]],
\ matchfuzzypos(l, 'cam', {'key' : 'val'}))
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'text_cb' : {v -> v.val}}))
call assert_equal([[], [], []], matchfuzzypos(l, 'day', {'key' : 'val'}))
@@ -164,30 +171,17 @@ func Test_matchfuzzypos()
call assert_fails("let x = matchfuzzypos(l, 'foo', {'text_cb' : test_null_function()})", 'E475:')
" case match
call assert_equal([['Match', 'match'], [[0, 1], [0, 1]], [202, 177]], matchfuzzypos(['match', 'Match'], 'Ma'))
call assert_equal([['match', 'Match'], [[0, 1], [0, 1]], [202, 177]], matchfuzzypos(['Match', 'match'], 'ma'))
" CamelCase has high weight even case match
call assert_equal(['MyTestCase', 'mytestcase'], matchfuzzy(['mytestcase', 'MyTestCase'], 'mtc'))
call assert_equal(['MyTestCase', 'mytestcase'], matchfuzzy(['MyTestCase', 'mytestcase'], 'mtc'))
call assert_equal(['MyTest', 'Mytest', 'mytest', ],matchfuzzy(['Mytest', 'mytest', 'MyTest'], 'MyT'))
call assert_equal(['CamelCaseMatchIngAlg', 'camelCaseMatchingAlg', 'camelcasematchingalg'],
\ matchfuzzy(['CamelCaseMatchIngAlg', 'camelcasematchingalg', 'camelCaseMatchingAlg'], 'CamelCase'))
call assert_equal(['CamelCaseMatchIngAlg', 'camelCaseMatchingAlg', 'camelcasematchingalg'],
\ matchfuzzy(['CamelCaseMatchIngAlg', 'camelcasematchingalg', 'camelCaseMatchingAlg'], 'CamelcaseM'))
call assert_equal([['Match'], [[0, 1]], [1885]], matchfuzzypos(['match', 'Match'], 'Ma'))
call assert_equal([['match', 'Match'], [[0, 1], [0, 1]], [1885, 1885]], matchfuzzypos(['Match', 'match'], 'ma'))
let l = [{'id' : 5, 'name' : 'foo'}, {'id' : 6, 'name' : []}, {'id' : 7}]
call assert_fails("let x = matchfuzzypos(l, 'foo', {'key' : 'name'})", 'E730:')
" 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([['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]], [2885, 2870, 2865, 2680, 2670, 2655, 2655]],
\ 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]],
\ 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]],
\ matchfuzzypos(['things','sThings', 'thisThings'], 'thin', {'camelcase': v:false}))
call assert_fails("let x = matchfuzzypos([], 'foo', {'camelcase': []})", 'E475: Invalid value for argument camelcase')
call assert_equal([['things', 'sThings', 'thisThings'], [[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 6, 7]], [3890, 3685, 3670]],
\ matchfuzzypos(['things','sThings', 'thisThings'], 'thin'))
endfunc
" Test for matchfuzzy() with multibyte characters
@@ -205,9 +199,14 @@ func Test_matchfuzzy_mbyte()
call assert_equal(['세 마리의 작은 돼지'], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzy('돼지 마리의'))
call assert_equal([], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzy('파란 하늘'))
" preference for camel case match
" camel case match
call assert_equal(['oneąwo', 'oneĄwo'],
\ ['oneĄwo', 'oneąwo']->matchfuzzy('oneąwo'))
call assert_equal(['oneĄwo'],
\ ['oneĄwo', 'oneąwo']->matchfuzzy('Ąwo'))
" prefer camelcase when searched first character matches upper case
call assert_equal(['oneĄwo', 'oneąwo'],
\ ['oneąwo', 'oneĄwo']->matchfuzzy('oneąwo'))
\ ['oneĄwo', 'oneąwo']->matchfuzzy('ąw'))
" preference for complete match then match after separator (_ or space)
call assert_equal(['ⅠⅡabㄟㄠ'] + sort(['ⅠⅡa_bㄟㄠ', 'ⅠⅡa bㄟㄠ']),
\ ['ⅠⅡabㄟㄠ', 'ⅠⅡa bㄟㄠ', 'ⅠⅡa_bㄟㄠ']->matchfuzzy('ⅠⅡabㄟㄠ'))
@@ -231,41 +230,39 @@ endfunc
" Test for matchfuzzypos() with multibyte characters
func Test_matchfuzzypos_mbyte()
CheckFeature multi_lang
call assert_equal([['こんにちは世界'], [[0, 1, 2, 3, 4]], [273]],
call assert_equal([['こんにちは世界'], [[0, 1, 2, 3, 4]], [4890]],
\ matchfuzzypos(['こんにちは世界'], 'こんにちは'))
call assert_equal([['ンヹㄇヺヴ'], [[1, 3]], [88]], matchfuzzypos(['ンヹㄇヺヴ'], 'ヹヺ'))
call assert_equal([['ンヹㄇヺヴ'], [[1, 3]], [-20]], matchfuzzypos(['ンヹㄇヺヴ'], 'ヹヺ'))
" reverse the order of characters
call assert_equal([[], [], []], matchfuzzypos(['ンヹㄇヺヴ'], 'ヺヹ'))
call assert_equal([['αβΩxxx', 'xαxβxΩx'], [[0, 1, 2], [1, 3, 5]], [252, 143]],
call assert_equal([['αβΩxxx', 'xαxβxΩx'], [[0, 1, 2], [1, 3, 5]], [2885, 670]],
\ matchfuzzypos(['αβΩxxx', 'xαxβxΩx'], 'αβΩ'))
call assert_equal([['ππbbππ', 'πππbbbπππ', 'ππππbbbbππππ', 'πbπ'],
\ [[0, 1], [0, 1], [0, 1], [0, 2]], [176, 173, 170, 135]],
\ [[0, 1], [0, 1], [0, 1], [0, 2]], [1880, 1865, 1850, 890]],
\ matchfuzzypos(['πbπ', 'ππbbππ', 'πππbbbπππ', 'ππππbbbbππππ'], 'ππ'))
call assert_equal([['ααααααα'], [[0, 1, 2]], [216]],
call assert_equal([['ααααααα'], [[0, 1, 2]], [2880]],
\ matchfuzzypos(['ααααααα'], 'ααα'))
call assert_equal([[], [], []], matchfuzzypos(['ンヹㄇ', 'ŗŝţ'], 'fffifl'))
let x = matchfuzzypos([repeat('Ψ', 256)], repeat('Ψ', 256))
call assert_equal(range(256), x[1][0])
call assert_equal([[], [], []], matchfuzzypos([repeat('✓', 300)], repeat('✓', 257)))
call assert_equal([repeat('✓', 300)], matchfuzzypos([repeat('✓', 300)], repeat('✓', 257))[0])
" match multiple words (separated by space)
call assert_equal([['세 마리의 작은 돼지'], [[9, 10, 2, 3, 4]], [328]], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzypos('돼지 마리의'))
call assert_equal([['세 마리의 작은 돼지'], [[9, 10, 2, 3, 4]], [4515]], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzypos('돼지 마리의'))
call assert_equal([[], [], []], ['세 마리의 작은 돼지', '마리의', '마리의 작은', '작은 돼지']->matchfuzzypos('파란 하늘'))
" match in a long string
call assert_equal([[repeat('ぶ', 300) .. 'ẼẼẼ'], [[300, 301, 302]], [105]],
call assert_equal([[repeat('ぶ', 300) .. 'ẼẼẼ'], [[300, 301, 302]], [500]],
\ matchfuzzypos([repeat('ぶ', 300) .. 'ẼẼẼ'], 'ẼẼẼ'))
" preference for camel case match
call assert_equal([['xѳѵҁxxѳѴҁ'], [[6, 7, 8]], [219]], matchfuzzypos(['xѳѵҁxxѳѴҁ'], 'ѳѵҁ'))
" preference for match after a separator (_ or space)
call assert_equal([['xちだx_ちだ'], [[5, 6]], [145]], matchfuzzypos(['xちだx_ちだ'], 'ちだ'))
call assert_equal([['xちだx_ちだ'], [[5, 6]], [1775]], matchfuzzypos(['xちだx_ちだ'], 'ちだ'))
" preference for leading letter match
call assert_equal([['ѳѵҁxѳѵҁ'], [[0, 1]], [150]], matchfuzzypos(['ѳѵҁxѳѵҁ'], 'ѳѵ'))
call assert_equal([['ѳѵҁxѳѵҁ'], [[0, 1]], [1875]], matchfuzzypos(['ѳѵҁxѳѵҁ'], 'ѳѵ'))
" preference for sequential match
call assert_equal([['aンbヹcㄇdンヹㄇ'], [[7, 8, 9]], [158]], matchfuzzypos(['aンbヹcㄇdンヹㄇ'], 'ンヹㄇ'))
call assert_equal([['aンbヹcㄇdンヹㄇ'], [[7, 8, 9]], [1965]], matchfuzzypos(['aンbヹcㄇdンヹㄇ'], 'ンヹㄇ'))
" best recursive match
call assert_equal([['xффйд'], [[2, 3, 4]], [168]], matchfuzzypos(['xффйд'], 'фйд'))
call assert_equal([['xффйд'], [[2, 3, 4]], [1990]], matchfuzzypos(['xффйд'], 'фйд'))
endfunc
" Test for matchfuzzy() with limit
+17
View File
@@ -3553,4 +3553,21 @@ def Test_generic_enum_constructor_error()
v9.CheckSourceFailure(lines, "E1010: Type not recognized: A", 4)
enddef
" Test for using more than 10 type arguments
def Test_generic_max_type_args()
var lines =<< trim END
vim9script
def Fn<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>(a1: A1): A1
var x: A1 = a1
return x
enddef
assert_equal(10, Fn<number, string, string, string, string, string, string, string, string, string, string, string>(10))
assert_equal('abc', Fn<string, number, number, number, number, number, number, number, number, number, number, number>('abc'))
END
v9.CheckSourceSuccess(lines)
enddef
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+12
View File
@@ -734,6 +734,18 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1629,
/**/
1628,
/**/
1627,
/**/
1626,
/**/
1625,
/**/
1624,
/**/
1623,
/**/
+3 -2
View File
@@ -3041,8 +3041,9 @@ long elapsed(DWORD start_tick);
#define EVAL_VAR_IMPORT 4 // may return special variable for import
#define EVAL_VAR_NO_FUNC 8 // do not look for a function
// Maximum number of characters that can be fuzzy matched
#define MAX_FUZZY_MATCHES 256
// Fuzzy matching
#define FUZZY_MATCH_MAX_LEN 1024 // max characters that can be matched
#define FUZZY_SCORE_NONE INT_MIN // invalid fuzzy score
// flags for equal_type()
#define ETYPE_ARG_UNKNOWN 1
+22 -13
View File
@@ -526,16 +526,6 @@ parse_generic_func_type_params(
if (name_exists)
return NULL;
if (ga_grow(&gfatab->gfat_param_types, 1) == FAIL)
return NULL;
type_T *gt =
&((type_T *)gfatab->gfat_param_types.ga_data)[gfatab->gfat_param_types.ga_len];
gfatab->gfat_param_types.ga_len++;
CLEAR_POINTER(gt);
gt->tt_type = VAR_ANY;
gt->tt_flags = TTFLAG_GENERIC;
if (ga_grow(&gfatab->gfat_args, 1) == FAIL)
return NULL;
generic_T *generic =
@@ -546,7 +536,7 @@ parse_generic_func_type_params(
if (generic->gt_name == NULL)
return NULL;
vim_strncpy(generic->gt_name, name_start, name_len);
generic->gt_type = gt;
generic->gt_type = NULL;
if (VIM_ISWHITE(*p))
{
@@ -572,13 +562,32 @@ parse_generic_func_type_params(
}
if (*p != '>')
return NULL;
p++;
if (generic_func_args_table_size(gfatab) == 0)
int gfat_sz = generic_func_args_table_size(gfatab);
if (gfat_sz == 0)
{
emsg_funcname(e_empty_type_list_for_generic_function_str, func_name);
return NULL;
}
p++;
// set the generic parms to VAR_ANY type
if (ga_grow(&gfatab->gfat_param_types, gfat_sz) == FAIL)
return NULL;
gfatab->gfat_param_types.ga_len = gfat_sz;
for (int i = 0; i < generic_func_args_table_size(gfatab); i++)
{
type_T *gt = &((type_T *)gfatab->gfat_param_types.ga_data)[i];
CLEAR_POINTER(gt);
gt->tt_type = VAR_ANY;
gt->tt_flags = TTFLAG_GENERIC;
generic_T *generic = &((generic_T *)gfatab->gfat_args.ga_data)[i];
generic->gt_type = gt;
}
return p;
}
+2 -1
View File
@@ -698,7 +698,8 @@ wingotofile:
find_pattern_in_path(ptr, 0, len, TRUE,
Prenum == 0 ? TRUE : FALSE, type,
Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM, FALSE);
Prenum1, ACTION_SPLIT, (linenr_T)1, (linenr_T)MAXLNUM,
FALSE, FALSE);
vim_free(ptr);
curwin->w_set_curswant = TRUE;
break;