1
0
forked from aniani/vim

patch 8.2.0877: cannot get the search statistics

Problem:    Cannot get the search statistics.
Solution:   Add the searchcount() function. (Fujiwara Takuya, closes #4446)
This commit is contained in:
Bram Moolenaar
2020-06-01 17:28:35 +02:00
parent 950587242c
commit e8f5ec0d30
7 changed files with 495 additions and 99 deletions

View File

@@ -2714,6 +2714,7 @@ screenrow() Number current cursor row
screenstring({row}, {col}) String characters at screen position
search({pattern} [, {flags} [, {stopline} [, {timeout}]]])
Number search for {pattern}
searchcount([{options}]) Dict get or update search stats
searchdecl({name} [, {global} [, {thisblock}]])
Number search for variable declaration
searchpair({start}, {middle}, {end} [, {flags} [, {skip} [...]]])
@@ -8429,6 +8430,126 @@ search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()*
Can also be used as a |method|: >
GetPattern()->search()
searchcount([{options}]) *searchcount()*
Get or update the last search count, like what is displayed
without the "S" flag in 'shortmess'. This works even if
'shortmess' does contain the "S" flag.
This returns a Dictionary. The dictionary is empty if the
previous pattern was not set and "pattern" was not specified.
key type meaning ~
current |Number| current position of match;
0 if the cursor position is
before the first match
exact_match |Boolean| 1 if "current" is matched on
"pos", otherwise 0
total |Number| total count of matches found
incomplete |Number| 0: search was fully completed
1: recomputing was timed out
2: max count exceeded
For {options} see further down.
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
you want to get correct information, specify `recompute: 1`: >
" result == maxcount + 1 (100) when many matches
let result = searchcount(#{recompute: 0})
" Below returns correct result (recompute defaults
" to 1)
let result = searchcount()
<
The function is useful to add the count to |statusline|: >
function! LastSearchCount() abort
let result = searchcount(#{recompute: 0})
if empty(result)
return ''
endif
if result.incomplete ==# 1 " timed out
return printf(' /%s [?/??]', @/)
elseif result.incomplete ==# 2 " max count exceeded
if result.total > result.maxcount &&
\ result.current > result.maxcount
return printf(' /%s [>%d/>%d]', @/,
\ result.current, result.total)
elseif result.total > result.maxcount
return printf(' /%s [%d/>%d]', @/,
\ result.current, result.total)
endif
endif
return printf(' /%s [%d/%d]', @/,
\ result.current, result.total)
endfunction
let &statusline .= '%{LastSearchCount()}'
" Or if you want to show the count only when
" 'hlsearch' was on
" let &statusline .=
" \ '%{v:hlsearch ? LastSearchCount() : ""}'
<
You can also update the search count, which can be useful in a
|CursorMoved| or |CursorMovedI| autocommand: >
autocmd CursorMoved,CursorMovedI *
\ let s:searchcount_timer = timer_start(
\ 200, function('s:update_searchcount'))
function! s:update_searchcount(timer) abort
if a:timer ==# s:searchcount_timer
call searchcount(#{
\ recompute: 1, maxcount: 0, timeout: 100})
redrawstatus
endif
endfunction
<
This can also be used to count matched texts with specified
pattern in the current buffer using "pattern": >
" Count '\<foo\>' in this buffer
" (Note that it also updates search count)
let result = searchcount(#{pattern: '\<foo\>'})
" To restore old search count by old pattern,
" search again
call searchcount()
<
{options} must be a Dictionary. It can contain:
key type meaning ~
recompute |Boolean| if |TRUE|, recompute the count
like |n| or |N| was executed.
otherwise returns the last
result by |n|, |N|, or this
function is returned.
(default: |TRUE|)
pattern |String| recompute if this was given
and different with |@/|.
this works as same as the
below command is executed
before calling this function >
let @/ = pattern
< (default: |@/|)
timeout |Number| 0 or negative number is no
timeout. timeout milliseconds
for recomputing the result
(default: 0)
maxcount |Number| 0 or negative number is no
limit. max count of matched
text while recomputing the
result. if search exceeded
total count, "total" value
becomes `maxcount + 1`
(default: 0)
pos |List| `[lnum, col, off]` value
when recomputing the result.
this changes "current" result
value. see |cursor()|, |getpos()
(default: cursor's position)
searchdecl({name} [, {global} [, {thisblock}]]) *searchdecl()*
Search for the declaration of {name}.