vim-patch:8.2.4724: current instance of last search pattern not easily spotted

Problem:    Current instance of last search pattern not easily spotted.
Solution:   Add CurSearch highlighting. (closes vim/vim#10133)
a43993897a

This fixes CurSearch highlight for multiline match.
Omit screen redrawing code because Nvim redraws CurSearch differently.
This commit is contained in:
zeertzjq 2022-04-20 20:42:55 +08:00
parent bfd6eb4404
commit 8145357974
5 changed files with 138 additions and 47 deletions

View File

@ -1018,6 +1018,7 @@ typedef struct {
// match (may continue in next line) // match (may continue in next line)
buf_T *buf; // the buffer to search for a match buf_T *buf; // the buffer to search for a match
linenr_T lnum; // the line to search for a match linenr_T lnum; // the line to search for a match
linenr_T lines; // number of lines starting from lnum
int attr; // attributes to be used for a match int attr; // attributes to be used for a match
int attr_cur; // attributes currently active in win_line() int attr_cur; // attributes currently active in win_line()
linenr_T first_lnum; // first lnum to search for multi-line pat linenr_T first_lnum; // first lnum to search for multi-line pat

View File

@ -582,6 +582,7 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char_u **l
} }
shl->startcol = MAXCOL; shl->startcol = MAXCOL;
shl->endcol = MAXCOL; shl->endcol = MAXCOL;
shl->lines = 0;
shl->attr_cur = 0; shl->attr_cur = 0;
shl->is_addpos = false; shl->is_addpos = false;
if (cur != NULL) { if (cur != NULL) {
@ -606,6 +607,11 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char_u **l
} else { } else {
shl->endcol = MAXCOL; shl->endcol = MAXCOL;
} }
if (shl->rm.endpos[0].lnum != shl->rm.startpos[0].lnum) {
shl->lines = shl->rm.endpos[0].lnum - shl->rm.startpos[0].lnum;
} else {
shl->lines = 1;
}
// Highlight one character for an empty match. // Highlight one character for an empty match.
if (shl->startcol == shl->endcol) { if (shl->startcol == shl->endcol) {
if ((*line)[shl->endcol] != NUL) { if ((*line)[shl->endcol] != NUL) {
@ -668,10 +674,12 @@ int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char_u **line, match
if (shl->endcol < next_col) { if (shl->endcol < next_col) {
shl->endcol = next_col; shl->endcol = next_col;
} }
// Use "CurSearch" highlight for current search match // Highlight the match were the cursor is using the CurSearch
// group.
if (shl == search_hl if (shl == search_hl
&& (HL_ATTR(HLF_LC) || wp->w_hl_ids[HLF_LC]) && (HL_ATTR(HLF_LC) || wp->w_hl_ids[HLF_LC])
&& wp->w_cursor.lnum == lnum && wp->w_cursor.lnum == lnum
&& wp->w_cursor.lnum < shl->lnum + shl->lines
&& wp->w_cursor.col >= shl->startcol && wp->w_cursor.col >= shl->startcol
&& wp->w_cursor.col < shl->endcol) { && wp->w_cursor.col < shl->endcol) {
shl->attr_cur = win_hl_attr(wp, HLF_LC) ? win_hl_attr(wp, HLF_LC) : HL_ATTR(HLF_LC); shl->attr_cur = win_hl_attr(wp, HLF_LC) ? win_hl_attr(wp, HLF_LC) : HL_ATTR(HLF_LC);

View File

@ -262,8 +262,8 @@ typedef struct vimoption {
#define HIGHLIGHT_INIT \ #define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
"i:IncSearch,l:Search,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow,N:CursorLineNr," \ "i:IncSearch,l:Search,y:CurSearch,m:MoreMsg,M:ModeMsg,n:LineNr,a:LineNrAbove,b:LineNrBelow," \
"G:CursorLineSign,O:CursorLineFold" \ "N:CursorLineNr,G:CursorLineSign,O:CursorLineFold" \
"r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \ "r:Question,s:StatusLine,S:StatusLineNC,c:VertSplit,t:Title,v:Visual,V:VisualNOS,w:WarningMsg," \
"W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \ "W:WildMenu,f:Folded,F:FoldColumn,A:DiffAdd,C:DiffChange,D:DiffDelete,T:DiffText,>:SignColumn," \
"-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar," \ "-:Conceal,B:SpellBad,P:SpellCap,R:SpellRare,L:SpellLocal,+:Pmenu,=:PmenuSel,x:PmenuSbar," \

View File

@ -946,6 +946,34 @@ func Test_incsearch_substitute()
call Incsearch_cleanup() call Incsearch_cleanup()
endfunc endfunc
func Test_hlsearch_cursearch()
CheckScreendump
let lines =<< trim END
set hlsearch scrolloff=0
call setline(1, ['one', 'foo', 'bar', 'baz', 'foo', 'bar'])
hi Search ctermbg=yellow
hi CurSearch ctermbg=blue
END
call writefile(lines, 'Xhlsearch_cursearch')
let buf = RunVimInTerminal('-S Xhlsearch_cursearch', {'rows': 9, 'cols': 60})
call term_sendkeys(buf, "gg/foo\<CR>")
call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_1', {})
call term_sendkeys(buf, "n")
call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_2', {})
call term_sendkeys(buf, "?\<CR>")
call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_single_line_3', {})
call term_sendkeys(buf, "gg/foo\\nbar\<CR>")
call VerifyScreenDump(buf, 'Test_hlsearch_cursearch_multiple_line', {})
call StopVimInTerminal(buf)
call delete('Xhlsearch_cursearch')
endfunc
" Similar to Test_incsearch_substitute() but with a screendump halfway. " Similar to Test_incsearch_substitute() but with a screendump halfway.
func Test_incsearch_substitute_dump() func Test_incsearch_substitute_dump()
CheckOption incsearch CheckOption incsearch

View File

@ -109,54 +109,108 @@ describe('search highlighting', function()
]]) ]])
end) end)
it('works for match under cursor', function() describe('CurSearch highlight', function()
screen:set_default_attr_ids({ before_each(function()
[1] = {background = Screen.colors.Yellow}, screen:set_default_attr_ids({
[2] = {foreground = Screen.colors.Gray100, background = Screen.colors.Gray0}, [1] = {background = Screen.colors.Yellow}, -- Search
[3] = {foreground = Screen.colors.Red}, [2] = {foreground = Screen.colors.White, background = Screen.colors.Black}, -- CurSearch
}) [3] = {foreground = Screen.colors.Red}, -- WarningMsg
})
command('highlight CurSearch guibg=Black guifg=White')
end)
command('highlight CurSearch guibg=Black guifg=White') it('works for match under cursor', function()
insert([[ insert([[
There is no way that a bee should be There is no way that a bee should be
able to fly. Its wings are too small able to fly. Its wings are too small
to get its fat little body off the to get its fat little body off the
ground. The bee, of course, flies ground. The bee, of course, flies
anyway because bees don't care what anyway because bees don't care what
humans think is impossible.]]) humans think is impossible.]])
feed('/bee<CR>') feed('/bee<CR>')
screen:expect{grid=[[ screen:expect{grid=[[
There is no way that a {2:^bee} should be | There is no way that a {2:^bee} should be |
able to fly. Its wings are too small | able to fly. Its wings are too small |
to get its fat little body off the | to get its fat little body off the |
ground. The {1:bee}, of course, flies | ground. The {1:bee}, of course, flies |
anyway because {1:bee}s don't care what | anyway because {1:bee}s don't care what |
humans think is impossible. | humans think is impossible. |
{3:search hit BOTTOM, continuing at TOP} | {3:search hit BOTTOM, continuing at TOP} |
]]} ]]}
feed('nn') feed('nn')
screen:expect{grid=[[ screen:expect{grid=[[
There is no way that a {1:bee} should be | There is no way that a {1:bee} should be |
able to fly. Its wings are too small | able to fly. Its wings are too small |
to get its fat little body off the | to get its fat little body off the |
ground. The {1:bee}, of course, flies | ground. The {1:bee}, of course, flies |
anyway because {2:^bee}s don't care what | anyway because {2:^bee}s don't care what |
humans think is impossible. | humans think is impossible. |
/bee | /bee |
]]} ]]}
feed('N') feed('N')
screen:expect{grid=[[ screen:expect{grid=[[
There is no way that a {1:bee} should be | There is no way that a {1:bee} should be |
able to fly. Its wings are too small | able to fly. Its wings are too small |
to get its fat little body off the | to get its fat little body off the |
ground. The {2:^bee}, of course, flies | ground. The {2:^bee}, of course, flies |
anyway because {1:bee}s don't care what | anyway because {1:bee}s don't care what |
humans think is impossible. | humans think is impossible. |
?bee | ?bee |
]]} ]]}
end)
it('works for multiline match', function()
insert([[
one
foo
bar
baz
foo
bar]])
feed('gg/foo<CR>')
screen:expect([[
one |
{2:^foo} |
bar |
baz |
{1:foo} |
bar |
/foo |
]])
feed('n')
screen:expect([[
one |
{1:foo} |
bar |
baz |
{2:^foo} |
bar |
/foo |
]])
feed('?<CR>')
screen:expect([[
one |
{2:^foo} |
bar |
baz |
{1:foo} |
bar |
?foo |
]])
feed('gg/foo\\nbar<CR>')
screen:expect([[
one |
{2:^foo} |
{1:bar} |
baz |
{1:foo} |
{1:bar} |
/foo\nbar |
]])
end)
end) end)
it('highlights after EOL', function() it('highlights after EOL', function()