[vim/vim] Show number of matches on the fly (#7817)

249 views
Skip to first unread message

Sebastian Nielsen

unread,
Feb 11, 2021, 3:49:56 AM2/11/21
to vim/vim, Subscribed

Is it possible to have Vim automatically update the number of matches as you type out the regex search query? As opposed to it only showing the number of matches when you hit enter?


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

bfrg

unread,
Feb 11, 2021, 6:50:25 AM2/11/21
to vim/vim, Subscribed

I use the following function to add number of matches and the match the cursor is currently on to my statusline:

function statusline#searchcount() abort
    if !v:hlsearch
        return ''
    endif

    try
        const count = searchcount({'maxcount': 0, 'timeout': 50})
    catch /^Vim\%((\a\+)\)\=:\%(E486\)\@!/
        return '[?/??]'
    endtry

    return count.total
            \ ? count.incomplete
            \   ? printf('[%d/??]', count.current)
            \   : printf('[%d/%d]', count.current, count.total)
            \ : '[0/0]'
endfunction

The function is called in statusline#main() which I set to 'statusline' in my vimrc. So something like:

" File: autoload/statusline.vim
function statusline#main() abort
    " Other parts of statusline ...
    let stl ..= '%{statusline#searchcount()}'
    return stl
endfunction

" In my vimrc
set statusline=%!statusline#main()

Screenshot:
screenshot-2021-02-11_124028

bfrg

unread,
Feb 11, 2021, 7:11:12 AM2/11/21
to vim/vim, Subscribed

There's also a plugin that displays the number of matches in a popup window: https://github.com/obcat/vim-hitspop

Bram Moolenaar

unread,
Feb 11, 2021, 12:47:51 PM2/11/21
to vim/vim, Subscribed

Closed #7817.

Bram Moolenaar

unread,
Feb 11, 2021, 12:47:53 PM2/11/21
to vim/vim, Subscribed

The problem for a generic solution is: Where to show the count? Either it requires a statusline or some kind of overlay on the window text. There may not be space on the command line itself. There are other complications, such as it has to be asynchronous to avoid a lag in typing the pattern.
Since there is a plugin for those users who really want it, I rather not implement this in code.

Sebastian Nielsen

unread,
Feb 11, 2021, 1:14:51 PM2/11/21
to vim/vim, Subscribed

@bfrg Thank you for your response. I am not familiar with vim functions, do you know why I am getting this error when I run your function?

image

bfrg

unread,
Feb 11, 2021, 1:49:38 PM2/11/21
to vim/vim, Subscribed

@Sebastian-Nielsen
You're getting an error because I gave you only a snippet of the function statusline#main(). The above was only meant as an example. Try the following here:

set statusline=%<%f\ %h%m%r\ %{statusline#searchcount()}%=%-14.(%l,%c%V%)\ %P

This will add the number of matches to the default statusline.

Sebastian Nielsen

unread,
Feb 11, 2021, 2:01:04 PM2/11/21
to vim/vim, Subscribed

@bfrg I assume that line is supposed to substitute the set statusline=%!statusline#main() function in .vimrc. Having done that, there is still no match count on the fly: (I did remember to save the .vimrc file)
image

bfrg

unread,
Feb 11, 2021, 2:09:56 PM2/11/21
to vim/vim, Subscribed

You need to add set laststatus=2 to enable the statusline.

Sebastian Nielsen

unread,
Feb 11, 2021, 2:16:54 PM2/11/21
to vim/vim, Subscribed

@bfrg Thank you, we're almost there! For some reason though, it always only displays question marks (no matter the search query), any idea why?

image

bfrg

unread,
Feb 11, 2021, 3:07:30 PM2/11/21
to vim/vim, Subscribed

You need to add scriptversion 4 at the top of the script-file that contains the statusline#searchcount() function.

Sebastian Nielsen

unread,
Feb 11, 2021, 3:10:58 PM2/11/21
to vim/vim, Subscribed

@bfrg
Hmm, it still doesn't seem to work.

I tried with both 'maxcount': 0 and 'maxcount': 50

image

bfrg

unread,
Feb 11, 2021, 8:29:41 PM2/11/21
to vim/vim, Subscribed

Which Vim version do you have?

Sebastian Nielsen

unread,
Feb 12, 2021, 2:44:37 AM2/12/21
to vim/vim, Subscribed

Which Vim version do you have? searchcount() was added in 8.2.0877.

I just ran sudo apt update (still doesn't work); here is the version number:

sebastian@ubuntu:~/.vim/autoload$ vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Apr 15 2020 06:40:31)
Included patches: 1-2269
Modified by team...@tracker.debian.org
Compiled by team...@tracker.debian.org
Huge version without GUI.  Features included (+) or not (-):
+acl               -farsi             -mouse_sysmouse    -tag_any_white
+arabic            +file_in_path      +mouse_urxvt       -tcl
+autocmd           +find_in_path      +mouse_xterm       +termguicolors
+autochdir         +float             +multi_byte        +terminal
-autoservername    +folding           +multi_lang        +terminfo
-balloon_eval      -footer            -mzscheme          +termresponse
+balloon_eval_term +fork()            +netbeans_intg     +textobjects
-browse            +gettext           +num64             +textprop
++builtin_terms    -hangul_input      +packages          +timers
+byte_offset       +iconv             +path_extra        +title
+channel           +insert_expand     -perl              -toolbar
+cindent           +job               +persistent_undo   +user_commands
-clientserver      +jumplist          +postscript        +vartabs
-clipboard         +keymap            +printer           +vertsplit
+cmdline_compl     +lambda            +profile           +virtualedit
+cmdline_hist      +langmap           -python            +visual
+cmdline_info      +libcall           +python3           +visualextra
+comments          +linebreak         +quickfix          +viminfo
+conceal           +lispindent        +reltime           +vreplace
+cryptv            +listcmds          +rightleft         +wildignore
+cscope            +localmap          -ruby              +wildmenu
+cursorbind        -lua               +scrollbind        +windows
+cursorshape       +menu              +signs             +writebackup
+dialog_con        +mksession         +smartindent       -X11
+diff              +modify_fname      +sound             -xfontset
+digraphs          +mouse             +spell             -xim
-dnd               -mouseshape        +startuptime       -xpm
-ebcdic            +mouse_dec         +statusline        -xsmp
+emacs_tags        +mouse_gpm         -sun_workshop      -xterm_clipboard
+eval              -mouse_jsbterm     +syntax            -xterm_save
+ex_extra          +mouse_netterm     +tag_binary        
+extra_search      +mouse_sgr         -tag_old_static    
   system vimrc file: "$VIM/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H   -Wdate-time  -g -O2 -fdebug-prefix-map=/build/vim-iU6mZD/vim-8.1.2269=. -fstack-protector-strong -Wformat -Werror=format-security -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1       
Linking: gcc   -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -o vim        -lm -ltinfo -lnsl  -lselinux  -lcanberra -lacl -lattr -lgpm -ldl     -L/usr/lib/python3.8/config-3.8-x86_64-linux-gnu -lpython3.8 -lcrypt -lpthread -ldl -lutil -lm -lm   

bfrg

unread,
Feb 12, 2021, 8:14:47 AM2/12/21
to vim/vim, Subscribed

You need to show us the included patches, for example:

$ vim --version | head -2
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Feb 12 2021 04:05:19)
Included patches: 1-2501

Sebastian Nielsen

unread,
Feb 12, 2021, 8:16:07 AM2/12/21
to vim/vim, Subscribed

Oh right, here you go:

sebastian@ubuntu:~$ vim --version 
VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Feb 11 2021 23:59:16)
Included patches: 1-2501

bfrg

unread,
Feb 12, 2021, 8:32:54 AM2/12/21
to vim/vim, Subscribed

Can you move the searchcount() call outside of the try-catch block so that we can see what error is emitted?

Sebastian Nielsen

unread,
Feb 12, 2021, 8:38:50 AM2/12/21
to vim/vim, Subscribed

@bfrg
There is no error now, but now there is also no "match display" printed anymore

image

bfrg

unread,
Feb 12, 2021, 8:59:03 AM2/12/21
to vim/vim, Subscribed

Can you try it with this modification:

function statusline#searchcount() abort
    if !v:hlsearch
        return ''
    endif

    try
        const count = searchcount({'maxcount': 0, 'timeout': 50})
    catch /^Vim\%((\a\+)\)\=:\%(E486\)\@!/
        return '[?/??]'
    endtry

    if empty(count)
        return ''
    endif

    return count.total
            \ ? count.incomplete
            \   ? printf('[%d/??]', count.current)
            \   : printf('[%d/%d]', count.current, count.total)
            \ : '[0/0]'
endfunction

Sebastian Nielsen

unread,
Feb 12, 2021, 9:02:12 AM2/12/21
to vim/vim, Subscribed

Hmm, there is still no match display shown

image

bfrg

unread,
Feb 12, 2021, 9:07:04 AM2/12/21
to vim/vim, Subscribed

After you saved the file, you need to either restart Vim or resource the file with :source %.

Sebastian Nielsen

unread,
Feb 12, 2021, 9:08:52 AM2/12/21
to vim/vim, Subscribed

After you saved the file, you need to either restart Vim or resource the file with :source %.

Yeah, sorry, that was what I meant I did.

bfrg

unread,
Feb 12, 2021, 9:38:12 AM2/12/21
to vim/vim, Subscribed

I really don't know why it doesn't work on your computer. Maybe someone else can take a look at this.

The following works on my system:

$ vim --clean test.vim -S test.vim

with

" test.vim
function Searchcount() abort
    if !v:hlsearch
        return ''
    endif

    try
        const cnt = searchcount({'maxcount': 0, 'timeout': 50})
    
catch /^Vim\%((\a\+)\)\=:\%(E486\)\@!/
        return '[?/??]'
    endtry

    if empty(cnt)
        return ''
    endif

    return cnt.total
            \ ? cnt.incomplete
            \   ? printf('[%d/??]', cnt.current)
            \   : printf('[%d/%d]', cnt.current, cnt.total)
            \ : '[0/0]'
endfunction

set laststatus=2
set hlsearch
set incsearch
set statusline=%<%f\ %h%m%r\ %{Searchcount()}%=%-14.(%l,%c%V%)\ %P

You can put this into your vimrc and try it again.

Notice that I removed the scriptversion 4. If we do so, we need to rename the variable count because v:count is a built-in variable. Prefixing Vim variables with v: is optional in scriptversion < 3 (see :help scriptversion-3 for more details), therefore count can't be used as a variable name, unless we prefix it with an l:.

Sebastian Nielsen

unread,
Feb 12, 2021, 9:42:59 AM2/12/21
to vim/vim, Subscribed

That works!

Thank you so much.

image

Reply all
Reply to author
Forward
0 new messages