commit c9d8468020308fc7a77ad8930292e16cec2bf1b7
parent 9784bc134624ff6dcf2e59e3c3998e206d2adad7
Author: Christian Clason <c.clason@uni-graz.at>
Date: Sat, 10 May 2025 12:26:56 +0200
feat(search): increase `MAX_COUNT` to 999
Problem: "99 searchcount ought to be enough for anyone."
Solution: Increase `SEARCH_STAT_DEF_MAX_COUNT` to 999, which I'm sure
will suffice for the next twenty years.
Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Diffstat:
8 files changed, 54 insertions(+), 40 deletions(-)
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
@@ -8415,11 +8415,11 @@ searchcount([{options}]) *searchcount()*
To get the last search count when |n| or |N| was pressed, call
this function with `recompute: 0` . This sometimes returns
- wrong information because |n| and |N|'s maximum count is 99.
- If it exceeded 99 the result must be max count + 1 (100). If
+ wrong information because |n| and |N|'s maximum count is 999.
+ If it exceeded 999 the result must be max count + 1 (1000). If
you want to get correct information, specify `recompute: 1`: >vim
- " result == maxcount + 1 (100) when many matches
+ " result == maxcount + 1 (1000) when many matches
let result = searchcount(#{recompute: 0})
" Below returns correct result (recompute defaults
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -227,6 +227,7 @@ These existing features changed their behavior.
• 'spellfile' location defaults to `stdpath("data").."/site/spell/"` instead of
the first writable directory in 'runtimepath'.
• |vim.version.range()| doesn't exclude `to` if it is equal to `from`.
+• |searchcount()|'s maximal value is raised from 99 to 999.
==============================================================================
REMOVED FEATURES *news-removed*
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
@@ -327,6 +327,7 @@ Functions:
- |matchadd()| can be called before highlight group is defined
- |tempname()| tries to recover if the Nvim |tempdir| disappears.
- |writefile()| with "p" flag creates parent directories.
+- |searchcount()|'s maximal value is raised from 99 to 999.
Highlight groups:
- |highlight-blend| controls blend level for a highlight group
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
@@ -7664,11 +7664,11 @@ function vim.fn.search(pattern, flags, stopline, timeout, skip) end
---
--- To get the last search count when |n| or |N| was pressed, call
--- this function with `recompute: 0` . This sometimes returns
---- wrong information because |n| and |N|'s maximum count is 99.
---- If it exceeded 99 the result must be max count + 1 (100). If
+--- wrong information because |n| and |N|'s maximum count is 999.
+--- If it exceeded 999 the result must be max count + 1 (1000). If
--- you want to get correct information, specify `recompute: 1`: >vim
---
---- " result == maxcount + 1 (100) when many matches
+--- " result == maxcount + 1 (1000) when many matches
--- let result = searchcount(#{recompute: 0})
---
--- " Below returns correct result (recompute defaults
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
@@ -9319,11 +9319,11 @@ M.funcs = {
To get the last search count when |n| or |N| was pressed, call
this function with `recompute: 0` . This sometimes returns
- wrong information because |n| and |N|'s maximum count is 99.
- If it exceeded 99 the result must be max count + 1 (100). If
+ wrong information because |n| and |N|'s maximum count is 999.
+ If it exceeded 999 the result must be max count + 1 (1000). If
you want to get correct information, specify `recompute: 1`: >vim
- " result == maxcount + 1 (100) when many matches
+ " result == maxcount + 1 (1000) when many matches
let result = searchcount(#{recompute: 0})
" Below returns correct result (recompute defaults
diff --git a/src/nvim/search.h b/src/nvim/search.h
@@ -63,8 +63,8 @@ enum {
// Values for searchcount()
enum { SEARCH_STAT_DEF_TIMEOUT = 40, };
-enum { SEARCH_STAT_DEF_MAX_COUNT = 99, };
-enum { SEARCH_STAT_BUF_LEN = 12, };
+enum { SEARCH_STAT_DEF_MAX_COUNT = 999, };
+enum { SEARCH_STAT_BUF_LEN = 14, };
enum {
/// Maximum number of characters that can be fuzzy matched
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
@@ -731,7 +731,7 @@ describe('ui/ext_messages', function()
]],
cmdline = { { abort = false } },
messages = {
- { content = { { '/line W [1/2]' } }, kind = 'search_count' },
+ { content = { { '/line W [1/2]' } }, kind = 'search_count' },
},
}
@@ -743,7 +743,7 @@ describe('ui/ext_messages', function()
{1:~ }|*3
]],
messages = {
- { content = { { '/line [2/2]' } }, kind = 'search_count' },
+ { content = { { '/line [2/2]' } }, kind = 'search_count' },
},
}
end)
diff --git a/test/old/testdir/test_search_stat.vim b/test/old/testdir/test_search_stat.vim
@@ -16,27 +16,27 @@ func Test_search_stat()
" but setting @/ should also work (even 'n' nor 'N' was executed)
" recompute the count when the last position is different.
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 40, incomplete: 0, maxcount: 99},
+ \ #{current: 1, exact_match: 1, total: 40, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'foo'}))
call assert_equal(
- \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar'}))
call assert_equal(
- \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 0, exact_match: 0, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar', pos: [2, 1, 0]}))
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar', pos: [3, 1, 0]}))
" on last char of match
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 1, exact_match: 1, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar', pos: [3, 9, 0]}))
" on char after match
call assert_equal(
- \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar', pos: [3, 10, 0]}))
call assert_equal(
- \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 99},
+ \ #{current: 1, exact_match: 0, total: 10, incomplete: 0, maxcount: 999},
\ searchcount(#{pattern: 'fooooobar', pos: [4, 1, 0]}))
call assert_equal(
\ #{current: 1, exact_match: 0, total: 2, incomplete: 2, maxcount: 1},
@@ -53,7 +53,7 @@ func Test_search_stat()
let pat = escape(@/, '()*?'). '\s\+'
call assert_match(pat .. stat, g:a)
call assert_equal(
- \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
+ \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 999},
\ searchcount(#{recompute: 0}))
" didn't get added to message history
call assert_equal(messages_before, execute('messages'))
@@ -64,7 +64,7 @@ func Test_search_stat()
let stat = '\[50/50\]'
call assert_match(pat .. stat, g:a)
call assert_equal(
- \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
+ \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 999},
\ searchcount(#{recompute: 0}))
" No search stat
@@ -75,53 +75,65 @@ func Test_search_stat()
call assert_notmatch(pat .. stat, g:a)
" n does not update search stat
call assert_equal(
- \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
+ \ #{current: 50, exact_match: 1, total: 50, incomplete: 0, maxcount: 999},
\ searchcount(#{recompute: 0}))
call assert_equal(
- \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 99},
+ \ #{current: 2, exact_match: 1, total: 50, incomplete: 0, maxcount: 999},
\ searchcount(#{recompute: v:true}))
set shortmess-=S
+ " Nvim: max search count is 999; append more lines to surpass it.
+ " Create a new undo block so we can revert the change later.
+ " Also allow "[?/??]" in case of timeouts from the increased max, but set a
+ " larger timeout for the recomputing searchcount()s.
+ let &l:undolevels = &l:undolevels
+ call append(0, repeat(['foobar', 'foo', 'fooooobar', 'foba', 'foobar'], 99))
+
" Many matches
call cursor(line('$')-2, 1)
let @/ = '.'
let pat = escape(@/, '()*?'). '\s\+'
let g:a = execute(':unsilent :norm! n')
- let stat = '\[>99/>99\]'
+ let stat = '\[\%(>999/>999\|?/??\)\]'
call assert_match(pat .. stat, g:a)
call assert_equal(
- \ #{current: 100, exact_match: 0, total: 100, incomplete: 2, maxcount: 99},
- \ searchcount(#{recompute: 0}))
+ \ #{current: 1000, exact_match: 0, total: 1000, incomplete: 2, maxcount: 999},
+ "\ Nvim: must recompute if the previous search timed out.
+ \ searchcount(#{recompute: (g:a =~# pat .. '\[?/??\]'), timeout: 500}))
call assert_equal(
- \ #{current: 272, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
- \ searchcount(#{recompute: v:true, maxcount: 0, timeout: 200}))
+ \ #{current: 3044, exact_match: 1, total: 3052, incomplete: 0, maxcount: 0},
+ \ searchcount(#{recompute: v:true, maxcount: 0, timeout: 500}))
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
- \ searchcount(#{recompute: 1, maxcount: 0, pos: [1, 1, 0], timeout: 200}))
+ \ #{current: 1, exact_match: 1, total: 3052, incomplete: 0, maxcount: 0},
+ \ searchcount(#{recompute: 1, maxcount: 0, pos: [1, 1, 0], timeout: 500}))
call cursor(line('$'), 1)
let g:a = execute(':unsilent :norm! n')
- let stat = 'W \[1/>99\]'
+ let stat = 'W \[\%(1/>999\|?/??\)\]'
call assert_match(pat .. stat, g:a)
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 100, incomplete: 2, maxcount: 99},
- \ searchcount(#{recompute: 0}))
+ \ #{current: 1, exact_match: 1, total: 1000, incomplete: 2, maxcount: 999},
+ "\ Nvim: must recompute if the previous search timed out.
+ \ searchcount(#{recompute: (g:a =~# pat .. '\[?/??\]'), timeout: 500}))
call assert_equal(
- \ #{current: 1, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
- \ searchcount(#{recompute: 1, maxcount: 0, timeout: 200}))
+ \ #{current: 1, exact_match: 1, total: 3052, incomplete: 0, maxcount: 0},
+ \ searchcount(#{recompute: 1, maxcount: 0, timeout: 500}))
call assert_equal(
- \ #{current: 271, exact_match: 1, total: 280, incomplete: 0, maxcount: 0},
- \ searchcount(#{recompute: 1, maxcount: 0, pos: [line('$')-2, 1, 0], timeout: 200}))
+ \ #{current: 3043, exact_match: 1, total: 3052, incomplete: 0, maxcount: 0},
+ \ searchcount(#{recompute: 1, maxcount: 0, pos: [line('$')-2, 1, 0], timeout: 500}))
" Many matches
call cursor(1, 1)
let g:a = execute(':unsilent :norm! n')
- let stat = '\[2/>99\]'
+ let stat = '\[\%(2/>999\|?/??\)\]'
call assert_match(pat .. stat, g:a)
call cursor(1, 1)
let g:a = execute(':unsilent :norm! N')
- let stat = 'W \[>99/>99\]'
+ let stat = 'W \[\%(>999/>999\|?/??\)\]'
call assert_match(pat .. stat, g:a)
+ " Nvim: undo the extra lines.
+ undo
+
" right-left
if exists("+rightleft")
set rl