Add the way to get search stat information when 'set shortmess-=S'#4446
Add the way to get search stat information when 'set shortmess-=S'#4446tyru wants to merge 20 commits intovim:masterfrom
Conversation
Usecase
Problem
Current specification has another problem. nnoremap n nzz
nnoremap N Nzz
If user can get the status by variable, user can :echo the status at any timing. set shortmess-=S
" zz removes search status information
"nnoremap n nzz
"nnoremap N Nzz
nnoremap n nzz:echo printf('[%d/%d]', v:searchstat.current, v:searchstat.count)<CR>
nnoremap N Nzz:echo printf('[%d/%d]', v:searchstat.current, v:searchstat.count)<CR> |
|
Please add test for empty status. Also I'm interesting whether the stat must be reset somewhere. |
|
I think this needs some |
|
Okay. >empty status, ifdef Currently no change (cleared, updated) is made until the next I'm also wondering that
Personally I think
How do you think? |
|
Takuya Fujiwara wrote:
# Usecase
* Show the status in statusline.
I wonder, if you show the stats in the statusline, shouldn't there be a
way to not show them on the command line?
v:searchstat should probably be cleared when editing another file.
Perhaps also when switching to another window.
# Problem
> As of [8.1.1270](9dfa313), vim can show current match position and count like `[1/20]` at command-line.
> It is useful but cannot get the status from Vim script, without using `execute(':unsilent :norm! n')` as test script does.
> But I don't want to execute `n` to know the status, because it throws CursorMoved, and changes jumplist, and so on.
Current specification has another problem.
If user has mappings of `n`, `N`,
```vim
nnoremap n nzz
nnoremap N Nzz
```
`zz` redraws the screen and `[1/20]` message disappears.
If user can get the status by variable, user can :echo the status at
any timing.
```vim
set shortmess-=S
" zz removes search status information
"nnoremap n nzz
"nnoremap N Nzz
nnoremap n nzz:echo printf('[%d/%d]', v:searchstat.current, v:searchstat.count)<CR>
nnoremap N Nzz:echo printf('[%d/%d]', v:searchstat.current, v:searchstat.count)<CR>
```
Add to the help somewhere?
…--
Never overestimate a man's ability to underestimate a woman.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
After thinking some more about the use case, I also wondered about that. Once we have |
Ah, that's true.
Yes. That's right.
You mean another interface (function, option, ...) is better? |
|
> I wonder, if you show the stats in the statusline, shouldn't there be a way to not show them on the command line?
Ah, that's true.
> v:searchstat should probably be cleared when editing another file. Perhaps also when switching to another window.
Yes. That's right.
> Probably would need another option.
You mean another interface (function, option, ...) is better?
I think a variable is good to make use of the stat because it's simple, and fast to reference the stat from statusline (function is a little bit slow?).
But please tell me if you have any idea.
What could work:
- Make v:searchstat available independend from the "S" flag in
'shortmess'
- When the value of v:searchstat is requested, compute the values, like
when displaying it in the command line.
- Keep track of when the values in v:searchstat become invalid (when the
text in the command line would be updated, when editing another
buffer, when the search string changes, etc.)
That way the "S" flag in 'shortmess' just controls whether the stats are
displayed in the command line.
The value is cached to avoid recomputing it when nothing changed, and we
don't compute it when it is not used.
…--
"Oh, no! NOT the Spanish Inquisition!"
"NOBODY expects the Spanish Inquisition!!!"
-- Monty Python sketch --
"Oh, no! NOT another option!"
"EVERYBODY expects another option!!!"
-- Discussion in vim-dev mailing list --
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
How about to add new identify of the status for statusline? ex |
This reverts commit dbe0d96.
It also has lifecycle issue yet. If statusline has And in most cases, users want to see the stat only in statusline of current window. So, I want to simply add a function to get the stat. One problem is the performance. So the function should be able to get the cached value when I wrote also PoC API in help: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 15ffed343..f8b7baafa 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2564,6 +2564,7 @@ screenrow() Number current cursor row
screenstring({row}, {col}) String characters at screen position
search({pattern} [, {flags} [, {stopline} [, {timeout}]]])
Number search for {pattern}
+searchcount([{dict}]) Dictionary the search stats
searchdecl({name} [, {global} [, {thisblock}]])
Number search for variable declaration
searchpair({start}, {middle}, {end} [, {flags} [, {skip} [...]]])
@@ -7910,6 +7911,31 @@ search({pattern} [, {flags} [, {stopline} [, {timeout}]]]) *search()*
The 'n' flag tells the function not to move the cursor.
+searchcount({dict}) *searchcount()*
+ The result is almost the same structure as {dict}.
+ Some keys can be specified by only arguments.
+ This function changes {dict} in-place and returns it.
+ If the keys of {dict} are omitted, default values were used.
+
+ key type arg only meaning ~
+ dir String no (default: "/" if |v:searchforward| is
+ no non-zero, otherwise "?")
+ lastpos List no `[lnum, col, off]` . see |getpos()|
+ no (default: the last position if
+ no |'shortmess'| does not contain "S",
+ no otherwise `[0, 0, 0]`)
+ pattern String no (default: |@/|)
+ bufnr Number no (default: current buffer)
+ changedtick Number no (default: |b:changedtick|)
+ current Number no
+ count Number no
+ wrap Number no
+ maxcount Number yes Max number of count (default: 99)
+ recompute Number yes if specified and zero, the
+ last computed values when
+ |'shortmess'| has not "S" flag
+ (default: non-zero)
+
searchdecl({name} [, {global} [, {thisblock}]]) *searchdecl()*
Search for the declaration of {name}.
|
|
To get the cached value (when :echo searchcount({'recompute': 0})
{'bufnr': 1, 'pattern': '\<Vim\>', 'dir': '/', 'wrap': 0, 'changedtick': 4, 'lastpos': [65, 17, 0], 'current': 3, 'recompute': 0, 'count': 10} |
|
A function avoids the need for tricks with updating the variable, I like that. |
|
Are you planning to make the suggested changes? |
|
sorry, I missed that. |
It's tough to merge master now... ;)
Done it. @brammool |
Codecov Report
@@ Coverage Diff @@
## master #4446 +/- ##
==========================================
+ Coverage 80.45% 82.88% +2.42%
==========================================
Files 110 134 +24
Lines 143354 148062 +4708
==========================================
+ Hits 115335 122720 +7385
+ Misses 28019 25342 -2677
Continue to review full report at Codecov.
|
|
I also found the way to show search stat information on command-line nnoremap n nzz
nnoremap N NzzThis is little hacky thing so that I hesitated to add this to vim help. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f65d46fec..5e698c80e 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -6738,6 +6738,26 @@ A jump table for the options with a short description can be found at |Q_op|.
NOTE: This option is set to the Vi default value when 'compatible' is
set and to the Vim default value when 'compatible' is reset.
+ *shortmess-S-faq*
+ When you set `set shortmess-=S`, if you want to show the count message
+ even when you have mapped to |n| and |N| like this: >
+
+ " Centering screen after n, N.
+ " But zz also clears search count message!
+ nnoremap n nzz
+ nnoremap N Nzz
+<
+ You can do like this: >
+
+ nnoremap <silent> <SID>(cmd:n) :<C-u>let w:search_stat = execute('unsilent norm! n')->split('\n')->get(-1, '')<CR>
+ nnoremap <silent> <SID>(cmd:N) :<C-u>let w:search_stat = execute('unsilent norm! N')->split('\n')->get(-1, '')<CR>
+ nnoremap <silent> <SID>(echo-search-stat) :<C-u>redraw <Bar> echo '' <Bar> echo w:search_stat<CR>
+
+ nmap <script> n <SID>(cmd:n)zz<SID>(echo-search-stat)
+ nmap <script> N <SID>(cmd:N)zz<SID>(echo-search-stat)
+<
+ Or you can use |searchcount()| function for more further information.
+
*'shortname'* *'sn'* *'noshortname'* *'nosn'*
'shortname' 'sn' boolean (default off)
local to buffer |
|
I also wrote detailed example to show the search stat in statusline. c4100e1 |
9c799aa to
7762334
Compare
|
0707327 to
93e5e79
Compare
|
This function looks useful, but I'm not sure about the details. Let me include it as-is now, and we can further improve it after that. |
|
Thanks! |
|
I don't know whether it can be optimized, but the longer the line the slower vim9script
@/ = 'x'
repeat('x', 100000)->setline(1)
nno <expr> n Func()
def g:Func(): string
searchcount({'maxcount': 1000, 'timeout': 500})
return 'n'
enddefKeep pressing This is not merely caused by the size of the buffer or the number of matches. Here is the exact same text, but splitted on 1000 lines: vim9script
@/ = 'x'
range(1000)->map({i -> repeat('x', 100)->setline(i + 1)})
nno <expr> n Func()
def g:Func(): string
searchcount({'maxcount': 1000, 'timeout': 500})
return 'n'
enddefKeep pressing The issue is really the length of the line. |
|
This will require profiling to find out what the time is spent on. |
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0 Additional changes: - Tests weren't passing because the test ran assuming the cursor was at start of buffer but append() left the cursor at end of buffer . So cursor is moved to start of buffer after append. - searchcount() added to list of builtin functions.
Problem: Cannot get the search statistics. Solution: Add the searchcount() function. (Fujiwara Takuya, closes vim/vim#4446) vim/vim@e8f5ec0 Additional changes: - Tests weren't passing because the test ran assuming the cursor was at start of buffer but append() left the cursor at end of buffer . So cursor is moved to start of buffer after append. - searchcount() added to list of builtin functions.
As of 8.1.1270, vim can show current match position and count like
[1/20]at command-line.It is useful but cannot get the status from Vim script, without using
execute(':unsilent :norm! n')as test script does.But I don't want to execute
nto know the status, because it throws CursorMoved, and changes jumplist, and so on.So I add av:searchstatvariable which can be referenced by Vim script without running any command.EDIT: added a function (
searchcount()) instead of a variable.