mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 7.4.2230
Problem: There is no equivalent of 'smartcase' for a tag search. Solution: Add value "followscs" and "smart" to 'tagcase'. (Christian Brabandt, closes #712) Turn tagcase test into new style.
This commit is contained in:
parent
f04507d132
commit
66e29d7112
@ -7417,6 +7417,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
By default, tag searches are case-sensitive. Case is ignored when
|
By default, tag searches are case-sensitive. Case is ignored when
|
||||||
'ignorecase' is set and 'tagcase' is "followic", or when 'tagcase' is
|
'ignorecase' is set and 'tagcase' is "followic", or when 'tagcase' is
|
||||||
"ignore".
|
"ignore".
|
||||||
|
Also when 'tagcase' is "followscs" and 'smartcase' is set, or
|
||||||
|
'tagcase' is "smart", and the pattern contains only lowercase
|
||||||
|
characters.
|
||||||
|
|
||||||
When 'tagbsearch' is off, tags searching is slower when a full match
|
When 'tagbsearch' is off, tags searching is slower when a full match
|
||||||
exists, but faster when no full match exists. Tags in unsorted tags
|
exists, but faster when no full match exists. Tags in unsorted tags
|
||||||
@ -7435,8 +7438,10 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
This option specifies how case is handled when searching the tags
|
This option specifies how case is handled when searching the tags
|
||||||
file:
|
file:
|
||||||
followic Follow the 'ignorecase' option
|
followic Follow the 'ignorecase' option
|
||||||
|
followscs Follow the 'smartcase' and 'ignorecase' options
|
||||||
ignore Ignore case
|
ignore Ignore case
|
||||||
match Match case
|
match Match case
|
||||||
|
smart Ignore case unless an upper case letter is used
|
||||||
|
|
||||||
*'taglength'* *'tl'*
|
*'taglength'* *'tl'*
|
||||||
'taglength' 'tl' number (default 0)
|
'taglength' 'tl' number (default 0)
|
||||||
|
@ -84,14 +84,23 @@ Note that when the current file changes, the priority list is mostly not
|
|||||||
changed, to avoid confusion when using ":tnext". It is changed when using
|
changed, to avoid confusion when using ":tnext". It is changed when using
|
||||||
":tag {ident}".
|
":tag {ident}".
|
||||||
|
|
||||||
The ignore-case matches are not found for a ":tag" command when the
|
The ignore-case matches are not found for a ":tag" command when:
|
||||||
'ignorecase' option is off and 'tagcase' is "followic" or when 'tagcase' is
|
- the 'ignorecase' option is off and 'tagcase' is "followic"
|
||||||
"match". They are found when a pattern is used (starting with a "/") and for
|
- 'tagcase' is "match"
|
||||||
":tselect", also when 'ignorecase' is off and 'tagcase' is "followic" or when
|
- 'tagcase' is "smart" and the pattern contains an upper case character.
|
||||||
'tagcase' is "match". Note that using ignore-case tag searching disables
|
- 'tagcase' is "followscs" and 'smartcase' option is on and the pattern
|
||||||
binary searching in the tags file, which causes a slowdown. This can be
|
contains an upper case character.
|
||||||
avoided by fold-case sorting the tag file. See the 'tagbsearch' option for an
|
|
||||||
explanation.
|
The gnore-case matches are found when:
|
||||||
|
- a pattern is used (starting with a "/")
|
||||||
|
- for ":tselect"
|
||||||
|
- when 'tagcase' is "followic" and 'ignorecase' is off
|
||||||
|
- when 'tagcase' is "match"
|
||||||
|
- when 'tagcase' is "followscs" and the 'smartcase' option is off
|
||||||
|
|
||||||
|
Note that using ignore-case tag searching disables binary searching in the
|
||||||
|
tags file, which causes a slowdown. This can be avoided by fold-case sorting
|
||||||
|
the tag file. See the 'tagbsearch' option for an explanation.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
2. Tag stack *tag-stack* *tagstack* *E425*
|
2. Tag stack *tag-stack* *tagstack* *E425*
|
||||||
@ -442,13 +451,18 @@ file "tags". It can also be used to access a common tags file.
|
|||||||
The next file in the list is not used when:
|
The next file in the list is not used when:
|
||||||
- A matching static tag for the current buffer has been found.
|
- A matching static tag for the current buffer has been found.
|
||||||
- A matching global tag has been found.
|
- A matching global tag has been found.
|
||||||
This also depends on whether case is ignored. Case is ignored when
|
This also depends on whether case is ignored. Case is ignored when:
|
||||||
'ignorecase' is set and 'tagcase' is "followic", or when 'tagcase' is
|
- 'tagcase' is "followic" and 'ignorecase' is set
|
||||||
"ignore". If case is not ignored, and the tags file only has a match without
|
- 'tagcase' is "ignore"
|
||||||
matching case, the next tags file is searched for a match with matching case.
|
- 'tagcase' is "smart" and and the pattern only contains lower case
|
||||||
If no tag with matching case is found, the first match without matching case
|
characters.
|
||||||
is used. If case is ignored, and a matching global tag with or without
|
- 'tagcase' is "followscs" and 'smartcase' is set and and the pattern only
|
||||||
matching case is found, this one is used, no further tags files are searched.
|
contains lower case characters.
|
||||||
|
If case is not ignored, and the tags file only has a match without matching
|
||||||
|
case, the next tags file is searched for a match with matching case. If no
|
||||||
|
tag with matching case is found, the first match without matching case is
|
||||||
|
used. If case is ignored, and a matching global tag with or without matching
|
||||||
|
case is found, this one is used, no further tags files are searched.
|
||||||
|
|
||||||
When a tag file name starts with "./", the '.' is replaced with the path of
|
When a tag file name starts with "./", the '.' is replaced with the path of
|
||||||
the current file. This makes it possible to use a tags file in the directory
|
the current file. This makes it possible to use a tags file in the directory
|
||||||
|
@ -2031,7 +2031,6 @@ test1 \
|
|||||||
test_marks \
|
test_marks \
|
||||||
test_nested_function \
|
test_nested_function \
|
||||||
test_search_mbyte \
|
test_search_mbyte \
|
||||||
test_tagcase \
|
|
||||||
test_utf8 \
|
test_utf8 \
|
||||||
test_wordcount \
|
test_wordcount \
|
||||||
test_writefile \
|
test_writefile \
|
||||||
@ -2123,6 +2122,7 @@ test_arglist \
|
|||||||
test_syntax \
|
test_syntax \
|
||||||
test_tabline \
|
test_tabline \
|
||||||
test_tabpage \
|
test_tabpage \
|
||||||
|
test_tagcase \
|
||||||
test_tagjump \
|
test_tagjump \
|
||||||
test_textobjects \
|
test_textobjects \
|
||||||
test_timers \
|
test_timers \
|
||||||
|
@ -822,11 +822,13 @@ EXTERN int p_tbs; /* 'tagbsearch' */
|
|||||||
EXTERN char_u *p_tc; /* 'tagcase' */
|
EXTERN char_u *p_tc; /* 'tagcase' */
|
||||||
EXTERN unsigned tc_flags; /* flags from 'tagcase' */
|
EXTERN unsigned tc_flags; /* flags from 'tagcase' */
|
||||||
#ifdef IN_OPTION_C
|
#ifdef IN_OPTION_C
|
||||||
static char *(p_tc_values[]) = {"followic", "ignore", "match", NULL};
|
static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL};
|
||||||
#endif
|
#endif
|
||||||
#define TC_FOLLOWIC 0x01
|
#define TC_FOLLOWIC 0x01
|
||||||
#define TC_IGNORE 0x02
|
#define TC_IGNORE 0x02
|
||||||
#define TC_MATCH 0x04
|
#define TC_MATCH 0x04
|
||||||
|
#define TC_FOLLOWSCS 0x08
|
||||||
|
#define TC_SMART 0x10
|
||||||
EXTERN long p_tl; /* 'taglength' */
|
EXTERN long p_tl; /* 'taglength' */
|
||||||
EXTERN int p_tr; /* 'tagrelative' */
|
EXTERN int p_tr; /* 'tagrelative' */
|
||||||
EXTERN char_u *p_tags; /* 'tags' */
|
EXTERN char_u *p_tags; /* 'tags' */
|
||||||
|
@ -7,6 +7,7 @@ void save_search_patterns(void);
|
|||||||
void restore_search_patterns(void);
|
void restore_search_patterns(void);
|
||||||
void free_search_patterns(void);
|
void free_search_patterns(void);
|
||||||
int ignorecase(char_u *pat);
|
int ignorecase(char_u *pat);
|
||||||
|
int ignorecase_opt(char_u *pat, int ic_in, int scs);
|
||||||
int pat_has_uppercase(char_u *pat);
|
int pat_has_uppercase(char_u *pat);
|
||||||
char_u *last_csearch(void);
|
char_u *last_csearch(void);
|
||||||
int last_csearch_forward(void);
|
int last_csearch_forward(void);
|
||||||
|
13
src/search.c
13
src/search.c
@ -367,9 +367,18 @@ free_search_patterns(void)
|
|||||||
int
|
int
|
||||||
ignorecase(char_u *pat)
|
ignorecase(char_u *pat)
|
||||||
{
|
{
|
||||||
int ic = p_ic;
|
return ignorecase_opt(pat, p_ic, p_scs);
|
||||||
|
}
|
||||||
|
|
||||||
if (ic && !no_smartcase && p_scs
|
/*
|
||||||
|
* As ignorecase() put pass the "ic" and "scs" flags.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ignorecase_opt(char_u *pat, int ic_in, int scs)
|
||||||
|
{
|
||||||
|
int ic = ic_in;
|
||||||
|
|
||||||
|
if (ic && !no_smartcase && scs
|
||||||
#ifdef FEAT_INS_EXPAND
|
#ifdef FEAT_INS_EXPAND
|
||||||
&& !(ctrl_x_mode && curbuf->b_p_inf)
|
&& !(ctrl_x_mode && curbuf->b_p_inf)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1388,6 +1388,8 @@ find_tags(
|
|||||||
case TC_FOLLOWIC: break;
|
case TC_FOLLOWIC: break;
|
||||||
case TC_IGNORE: p_ic = TRUE; break;
|
case TC_IGNORE: p_ic = TRUE; break;
|
||||||
case TC_MATCH: p_ic = FALSE; break;
|
case TC_MATCH: p_ic = FALSE; break;
|
||||||
|
case TC_FOLLOWSCS: p_ic = ignorecase(pat); break;
|
||||||
|
case TC_SMART: p_ic = ignorecase_opt(pat, TRUE, TRUE); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
help_save = curbuf->b_help;
|
help_save = curbuf->b_help;
|
||||||
|
@ -100,7 +100,6 @@ SCRIPTS_ALL = \
|
|||||||
test_marks.out \
|
test_marks.out \
|
||||||
test_nested_function.out \
|
test_nested_function.out \
|
||||||
test_search_mbyte.out \
|
test_search_mbyte.out \
|
||||||
test_tagcase.out \
|
|
||||||
test_utf8.out \
|
test_utf8.out \
|
||||||
test_wordcount.out \
|
test_wordcount.out \
|
||||||
test_writefile.out
|
test_writefile.out
|
||||||
|
@ -35,6 +35,7 @@ source test_statusline.vim
|
|||||||
source test_syn_attr.vim
|
source test_syn_attr.vim
|
||||||
source test_tabline.vim
|
source test_tabline.vim
|
||||||
source test_tabpage.vim
|
source test_tabpage.vim
|
||||||
|
source test_tagcase.vim
|
||||||
source test_tagjump.vim
|
source test_tagjump.vim
|
||||||
source test_timers.vim
|
source test_timers.vim
|
||||||
source test_true_false.vim
|
source test_true_false.vim
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
Tests for 'tagcase' option
|
|
||||||
|
|
||||||
STARTTEST
|
|
||||||
:so small.vim
|
|
||||||
:lang mess C
|
|
||||||
:/^start text$/+1,/^end text$/w! Xtext
|
|
||||||
:/^start tags$/+1,/^end tags$/-1w! Xtags
|
|
||||||
:set tags=Xtags
|
|
||||||
:e Xtext
|
|
||||||
:"
|
|
||||||
:" Verify default values.
|
|
||||||
:set ic& | setg tc& | setl tc&
|
|
||||||
:call append('$', "ic=".&ic." g:tc=".&g:tc." l:tc=".&l:tc." tc=".&tc)
|
|
||||||
:"
|
|
||||||
:" Verify that the local setting accepts <empty> but that the global setting
|
|
||||||
:" does not. The first of these (setting the local value to <empty>) should
|
|
||||||
:" succeed; the other two should fail.
|
|
||||||
:let v:errmsg = ""
|
|
||||||
:setl tc=
|
|
||||||
:call append('$', v:errmsg)
|
|
||||||
:let v:errmsg = ""
|
|
||||||
:setg tc=
|
|
||||||
:call append('$', v:errmsg)
|
|
||||||
:let v:errmsg = ""
|
|
||||||
:set tc=
|
|
||||||
:call append('$', v:errmsg)
|
|
||||||
:"
|
|
||||||
:" Verify that the correct number of matching tags is found for all values of
|
|
||||||
:" 'ignorecase' and global and local values 'tagcase', in all combinations.
|
|
||||||
:for &ic in [0, 1]
|
|
||||||
: for &g:tc in ["followic", "ignore", "match"]
|
|
||||||
: for &l:tc in ["", "followic", "ignore", "match"]
|
|
||||||
: call append('$', "ic=".&ic." g:tc=".&g:tc." l:tc=".&l:tc." tc=".&tc)
|
|
||||||
: call append('$', len(taglist("^foo$")))
|
|
||||||
: call append('$', len(taglist("^Foo$")))
|
|
||||||
: endfor
|
|
||||||
: endfor
|
|
||||||
:endfor
|
|
||||||
:"
|
|
||||||
:1,/^end text$/d
|
|
||||||
:w! test.out
|
|
||||||
:qa!
|
|
||||||
ENDTEST
|
|
||||||
|
|
||||||
start text
|
|
||||||
|
|
||||||
Foo
|
|
||||||
Bar
|
|
||||||
foo
|
|
||||||
|
|
||||||
end text
|
|
||||||
|
|
||||||
start tags
|
|
||||||
Bar Xtext 3
|
|
||||||
Foo Xtext 2
|
|
||||||
foo Xtext 4
|
|
||||||
end tags
|
|
@ -1,76 +0,0 @@
|
|||||||
ic=0 g:tc=followic l:tc=followic tc=followic
|
|
||||||
|
|
||||||
E474: Invalid argument: tc=
|
|
||||||
E474: Invalid argument: tc=
|
|
||||||
ic=0 g:tc=followic l:tc= tc=followic
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=followic l:tc=followic tc=followic
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=followic l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=0 g:tc=followic l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=ignore l:tc= tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=0 g:tc=ignore l:tc=followic tc=followic
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=ignore l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=0 g:tc=ignore l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=match l:tc= tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=match l:tc=followic tc=followic
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=0 g:tc=match l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=0 g:tc=match l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=1 g:tc=followic l:tc= tc=followic
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=followic l:tc=followic tc=followic
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=followic l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=followic l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=1 g:tc=ignore l:tc= tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=ignore l:tc=followic tc=followic
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=ignore l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=ignore l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=1 g:tc=match l:tc= tc=match
|
|
||||||
1
|
|
||||||
1
|
|
||||||
ic=1 g:tc=match l:tc=followic tc=followic
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=match l:tc=ignore tc=ignore
|
|
||||||
2
|
|
||||||
2
|
|
||||||
ic=1 g:tc=match l:tc=match tc=match
|
|
||||||
1
|
|
||||||
1
|
|
73
src/testdir/test_tagcase.vim
Normal file
73
src/testdir/test_tagcase.vim
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
" test 'tagcase' option
|
||||||
|
|
||||||
|
func Test_tagcase()
|
||||||
|
call writefile(["Bar\tXtext\t3", "Foo\tXtext\t2", "foo\tXtext\t4"], 'Xtags')
|
||||||
|
set tags=Xtags
|
||||||
|
e Xtext
|
||||||
|
|
||||||
|
for &ic in [0, 1]
|
||||||
|
for &scs in [0, 1]
|
||||||
|
for &g:tc in ["followic", "ignore", "match", "followscs", "smart"]
|
||||||
|
for &l:tc in ["", "followic", "ignore", "match", "followscs", "smart"]
|
||||||
|
let smart = 0
|
||||||
|
if &l:tc != ''
|
||||||
|
let tc = &l:tc
|
||||||
|
else
|
||||||
|
let tc = &g:tc
|
||||||
|
endif
|
||||||
|
if tc == 'followic'
|
||||||
|
let ic = &ic
|
||||||
|
elseif tc == 'ignore'
|
||||||
|
let ic = 1
|
||||||
|
elseif tc == 'followscs'
|
||||||
|
let ic = &ic
|
||||||
|
let smart = &scs
|
||||||
|
elseif tc == 'smart'
|
||||||
|
let ic = 1
|
||||||
|
let smart = 1
|
||||||
|
else
|
||||||
|
let ic = 0
|
||||||
|
endif
|
||||||
|
if ic && smart
|
||||||
|
call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name}))
|
||||||
|
call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name}))
|
||||||
|
elseif ic
|
||||||
|
call assert_equal(['foo', 'Foo'], map(taglist("^foo$"), {i, v -> v.name}))
|
||||||
|
call assert_equal(['Foo', 'foo'], map(taglist("^Foo$"), {i, v -> v.name}))
|
||||||
|
else
|
||||||
|
call assert_equal(['foo'], map(taglist("^foo$"), {i, v -> v.name}))
|
||||||
|
call assert_equal(['Foo'], map(taglist("^Foo$"), {i, v -> v.name}))
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call delete('Xtags')
|
||||||
|
set ic&
|
||||||
|
setg tc&
|
||||||
|
setl tc&
|
||||||
|
set scs&
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func Test_set_tagcase()
|
||||||
|
" Verify default values.
|
||||||
|
set ic&
|
||||||
|
setg tc&
|
||||||
|
setl tc&
|
||||||
|
call assert_equal(0, &ic)
|
||||||
|
call assert_equal('followic', &g:tc)
|
||||||
|
call assert_equal('followic', &l:tc)
|
||||||
|
call assert_equal('followic', &tc)
|
||||||
|
|
||||||
|
" Verify that the local setting accepts <empty> but that the global setting
|
||||||
|
" does not. The first of these (setting the local value to <empty>) should
|
||||||
|
" succeed; the other two should fail.
|
||||||
|
setl tc=
|
||||||
|
call assert_fails('setg tc=', 'E474:')
|
||||||
|
call assert_fails('set tc=', 'E474:')
|
||||||
|
|
||||||
|
set ic&
|
||||||
|
setg tc&
|
||||||
|
setl tc&
|
||||||
|
endfunc
|
@ -763,6 +763,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 */
|
||||||
|
/**/
|
||||||
|
2230,
|
||||||
/**/
|
/**/
|
||||||
2229,
|
2229,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user