Hi all, On Thu, Jan 4, 2024 at 1:45 PM Christian Brabandt <cbli...@256bit.org> wrote:
> patch 9.1.0009: Cannot easily get the list of matches > > Commit: > https://github.com/vim/vim/commit/f93b1c881a99fa847a1bafa71877d7e16f18e6ef > Author: Yegappan Lakshmanan <yegap...@yahoo.com> > Date: Thu Jan 4 22:28:46 2024 +0100 > > patch 9.1.0009: Cannot easily get the list of matches > > Problem: Cannot easily get the list of matches > Solution: Add the matchstrlist() and matchbufline() Vim script > functions (Yegappan Lakshmanan) > > To demonstrate the use of the new matchbufline() function, I have created the following script. This does search text completion from the list of words in the current buffer. After typing a few letters in the "/" prompt, if you press Tab, it will complete the word from the current buffer. If you press Tab again, then it will go to the next match. If you press Shift-Tab, it will go back to the previous match. Regards, Yegappan -------------------------------------------------------------------------------------------------------- vim9script var searchMatches: list<string> = [] var prevMatchIndex: number = 0 var prevCmdline: string = '' var prevCmdlinePrefix: string = '' var prevPat: string = '' def SearchComplete(forward: bool): string var cmdtype: string = getcmdtype() if cmdtype != '/' && cmdtype != '?' feedkeys(forward ? "\<Tab>" : "\<S-Tab>", 'nt') return '' endif var cmdline: string = getcmdline() if cmdline != '' && cmdline ==# prevCmdline # Jump to the next/previous match if (cmdtype == '/' && forward) || (cmdtype == '?' && !forward) prevMatchIndex += 1 else prevMatchIndex -= 1 endif if prevMatchIndex < 0 prevMatchIndex = searchMatches->len() - 1 elseif prevMatchIndex >= searchMatches->len() prevMatchIndex = 0 endif var s = searchMatches[prevMatchIndex][strlen(prevPat) : ] prevCmdline = prevCmdlinePrefix .. s setcmdline(prevCmdlinePrefix) return s endif var cmdpos: number = getcmdpos() var start: number = cmdpos - 1 if start >= strlen(cmdline) start -= 1 endif while start > 0 && cmdline[start - 1] =~ '\k' start -= 1 endwhile var pat: string = cmdline[start : cmdpos] # Get the List of matches var start_lnum = &wrapscan || cmdtype == '?' ? 1 : line('.') var end_lnum = &wrapscan || cmdtype == '/' ? '$' : line('.') var l = matchbufline('', $'\<{pat}\k\+\>', start_lnum, end_lnum) if l->empty() return '' endif var curline = line('.') var curcol = col('.') var patStartByte = curcol - 1 - strlen(pat) l->filter((_, v) => v.lnum == curline ? cmdtype == '/' ? v.byteidx >= patStartByte : v.byteidx <= patStartByte : true) if l->empty() return '' endif # Sort by matched string and line/byte index l->sort((a, b) => { if a.text > b.text return 1 elseif a.text == b.text if a.lnum > b.lnum return 1 elseif a.lnum == b.lnum return a.byteidx > b.byteidx ? 1 : 0 endif return 0 endif return 0 }) # Remove duplicates l->uniq((a, b) => a.text ==# b.text ? 0 : 1) # Sort by byte index and line number l->sort((a, b) => a.lnum == b.lnum ? a.byteidx - b.byteidx : a.lnum - b.lnum) var startIdx: number if cmdtype == '/' startIdx = l->indexof((_, v) => v.lnum == curline ? v.byteidx >= patStartByte : v.lnum > curline) else startIdx = l->copy()->reverse()->indexof((_, v) => v.lnum == curline ? v.byteidx <= patStartByte : v.lnum < curline) startIdx = l->len() - startIdx - 1 endif if startIdx == -1 startIdx = forward ? 0 : searchMatches->len() - 1 endif # Save the matched strings searchMatches = l->map((_, v) => v.text) var s = searchMatches[startIdx][strlen(pat) : ] # Save the state for jumping to the next previous match prevMatchIndex = startIdx prevPat = pat prevCmdline = cmdline .. s prevCmdlinePrefix = cmdline return s enddef cnoremap <Tab> <C-R>=<SID>SearchComplete(v:true)<CR> cnoremap <S-Tab> <C-R>=<SID>SearchComplete(v:false)<CR> # vim: ts=8 sw=2 sts=2 expandtab tw=80 -------------------------------------------------------------------------------------------------------- -- -- You received this message from the "vim_use" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_use" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_use+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/vim_use/CAAW7x7nDkmO_MQRy4XycR%3DhDPmAVi1pHh2DSV23cPj65%3Dfi%2BQg%40mail.gmail.com.