mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 06:58:35 +00:00
vim-patch:7.4.2230 (#6080)
Problem: There is no equivalent of 'smartcase' for a tag search.
Solution: Add value "followscs" and "smart" to 'tagcase'. (Christian
Brabandt, closes vim/vim#712) Turn tagcase test into new style.
66e29d7112
This commit is contained in:

committed by
Justin M. Keyes

parent
039c7ab607
commit
0ef2b07d69
@@ -6273,6 +6273,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
|
||||||
@@ -6290,8 +6293,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)
|
||||||
|
@@ -83,14 +83,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*
|
||||||
@@ -420,13 +429,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
|
||||||
|
@@ -601,11 +601,14 @@ 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'
|
||||||
|
@@ -308,13 +308,19 @@ void free_search_patterns(void)
|
|||||||
*/
|
*/
|
||||||
int ignorecase(char_u *pat)
|
int 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
|
||||||
&& !(ctrl_x_mode && curbuf->b_p_inf)
|
&& !(ctrl_x_mode && curbuf->b_p_inf)
|
||||||
)
|
) {
|
||||||
ic = !pat_has_uppercase(pat);
|
ic = !pat_has_uppercase(pat);
|
||||||
no_smartcase = FALSE;
|
}
|
||||||
|
no_smartcase = false;
|
||||||
|
|
||||||
return ic;
|
return ic;
|
||||||
}
|
}
|
||||||
|
@@ -1164,6 +1164,12 @@ find_tags (
|
|||||||
case TC_MATCH:
|
case TC_MATCH:
|
||||||
p_ic = false;
|
p_ic = false;
|
||||||
break;
|
break;
|
||||||
|
case TC_FOLLOWSCS:
|
||||||
|
p_ic = ignorecase(pat);
|
||||||
|
break;
|
||||||
|
case TC_SMART:
|
||||||
|
p_ic = ignorecase_opt(pat, true, true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
@@ -25,6 +25,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_unlet.vim
|
source test_unlet.vim
|
||||||
source test_window_cmd.vim
|
source test_window_cmd.vim
|
||||||
|
73
src/nvim/testdir/test_tagcase.vim
Normal file
73
src/nvim/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
|
@@ -210,7 +210,7 @@ static int included_patches[] = {
|
|||||||
2233,
|
2233,
|
||||||
// 2232 NA
|
// 2232 NA
|
||||||
// 2231,
|
// 2231,
|
||||||
// 2230,
|
2230,
|
||||||
// 2229,
|
// 2229,
|
||||||
// 2228,
|
// 2228,
|
||||||
2227,
|
2227,
|
||||||
|
Reference in New Issue
Block a user