If your Vim binary includes the patch 8.2.0877, you can get the search statistics via the searchcount()
function. And the latter is not limited to 99 matches.
You can invoke it right after a /
search with a CmdlineLeave
autocmd, and right after a n
motion by installing a wrapper mapping around the latter.
Example:
const s:MAXCOUNT = 1000
const s:TIMEOUT = 500
augroup index_after_slash | au!
au CmdlineLeave /,\? call s:index_after_slash()
augroup END
fu s:index_after_slash() abort
if getcmdline() is# '' || state() =~# 'm'
return
endif
call timer_start(0, {-> mode() =~# '[nv]' ? s:search_index() : 0})
endfu
fu s:search_index() abort
try
let result = searchcount(#{maxcount: s:MAXCOUNT, timeout: s:TIMEOUT})
let [current, total, incomplete] = [result.current, result.total, result.incomplete]
catch
echohl ErrorMsg | echom v:exception | echohl NONE
return ''
endtry
let msg = ''
let pat = substitute(@/, '\%x00', '^@', 'g')
if incomplete == 0
let msg = printf('[%*d/%d] %s', len(total), current, total, pat)
elseif incomplete == 1 " recomputing took too much time
let msg = printf('[?/??] '..%s', pat)
elseif incomplete == 2 " too many matches
if result.total == (result.maxcount+1) && result.current <= result.maxcount
let msg = printf('[%*d/>%d] %s', len(total-1), current, total-1, pat)
else
let msg = printf('[>%*d/>%d] %s', len(total-1), current-1, total-1, pat)
endif
endif
if strchars(msg, 1) > (v:echospace + (&cmdheight-1)*&columns)
let n = v:echospace - 3
let [n1, n2] = n%2 ? [n/2, n/2] : [n/2-1, n/2]
let msg = matchlist(msg, '\(.\{' .. n1 .. '}\).*\(.\{' .. n2 .. '}\)')[1:2]->join('...')
endif
echo msg
return ''
endfu
nmap n <plug>(n)<plug>(search_index)
nmap N <plug>(N)<plug>(search_index)
nno <plug>(n) n
nno <plug>(N) N
nno <expr> <plug>(search_index) <sid>search_index()
searchcount()
won't show a total amount of matches greater than 1000. If that's not enough, increase s:MAXCOUNT
.
And it will stop trying to compute the number of matches after half-a-second. If that's too long, decrease s:TIMEOUT
.
Note that increasing s:MAXCOUNT
and s:TIMEOUT
may have a negative impact on Vim's performance. The values used in the previous snippet work for me; they may or may not work for you. I guess it depends on the machine you're using and/or on the patterns you're usually looking for. Take that into consideration before setting these parameters.
You can improve the performance by rewriting the code in Vim9 script:
vim9script
const MAXCOUNT: number = 1'000
const TIMEOUT: number = 500
augroup index_after_slash | au!
au CmdlineLeave /,\? IndexAfterSlash()
augroup END
def IndexAfterSlash()
if getcmdline() == '' || state() =~ 'm'
return
endif
timer_start(0, () => mode() =~ '[nv]' ? SearchIndex() : 0)
enddef
def SearchIndex(): string
var incomplete: number
var total: number
var current: number
var result: dict<any>
try
result = searchcount({maxcount: MAXCOUNT, timeout: TIMEOUT})
current = result.current
total = result.total
incomplete = result.incomplete
catch
echohl ErrorMsg | echom v:exception | echohl NONE
return ''
endtry
var msg: string = ''
var pat: string = getreg('/')->substitute('\%x00', '^@', 'g')
if incomplete == 0
msg = printf('[%*d/%d] %s', len(total), current, total, pat)
elseif incomplete == 1 # recomputing took too much time
msg = printf('[?/??] %s', pat)
elseif incomplete == 2 # too many matches
if result.total == (result.maxcount + 1) && result.current <= result.maxcount
msg = printf('[%*d/>%d] %s', len(total - 1), current, total - 1, pat)
else
msg = printf('[>%*d/>%d] %s', len(total - 1), current - 1, total - 1, pat)
endif
endif
if strchars(msg, 1) > (v:echospace + (&cmdheight - 1) * &columns)
var n: number = v:echospace - 3
var n1: number = n % 2 ? n / 2 : n / 2 - 1
var n2: number = n / 2
var matchlist: list<string> = matchlist(msg, '\(.\{' .. n1 .. '}\).*\(.\{' .. n2 .. '}\)')
msg = matchlist[1] .. '...' .. matchlist[2]
endif
echo msg
return ''
enddef
nmap n <plug>(n)<plug>(search_index)
nmap N <plug>(N)<plug>(search_index)
nno <plug>(n) n
nno <plug>(N) N
nno <expr> <plug>(search_index) <sid>SearchIndex()
This requires a recent Vim version. It works on 8.2.2332.
For more info, see: