Full Code of henrik/vim-indexed-search for AI

master 763fdd0eb818 cached
5 files
19.1 KB
5.2k tokens
1 requests
Download .txt
Repository: henrik/vim-indexed-search
Branch: master
Commit: 763fdd0eb818
Files: 5
Total size: 19.1 KB

Directory structure:
gitextract_ydkyj2o8/

├── .gitignore
├── README.md
├── autoload/
│   └── indexed_search.vim
├── doc/
│   └── indexed-search.txt
└── plugin/
    └── indexed-search.vim

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
doc/tags


================================================
FILE: README.md
================================================
# IndexedSearch.vim

Requires vim7.4

Originally by [Yakov Lerner](http://www.vim.org/account/profile.php?user_id=2342) and put on GitHub by [Henrik Nyh](https://github.com/henrik) to have it there in a [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332)-friendly format.  Majorly rewritten by [Otto Modinos](https://github.com/otommod).

[See the original plugin page at vim.org.](http://www.vim.org/scripts/script.php?script_id=1682)

```
This plugin redefines 6 search commands (/,?,n,N,*,#). At every 
search command, it automatically prints>
       "At match #N out of M matches". 
>
-- the total number of matches (M) and the number(index) of current 
match (N). This helps to get oriented when searching forward and 
backward. 

There are no new commands and no new behavior to learn. 
Just watch the bottom line when you do /,?,n,N,*,#. 
```

[See full help file.](https://github.com/henrik/vim-indexed-search/blob/master/doc/indexed-search.txt)

## Alternatives

Is this plugin too slow for you?  Do you want more (or less) features?  Here're some other plugins that do (or can do) the same thing:

  * On Vim 8.1.1270+, you can use [`:set shortmess-=S`](https://stackoverflow.com/a/4671112/6962)
  * [google/vim-searchindex](https://github.com/google/vim-searchindex); very fast and unobtrusive
  * [osyo-manga/vim-anzu](https://github.com/osyo-manga/vim-anzu); tons of features
  * [romainl/vim-cool](https://github.com/romainl/vim-cool); initally just for disabling the highlighting of matches after a seach, now also show an index
  * [lacygoill/vim-search](https://github.com/lacygoill/vim-search); meant for [personal use](https://github.com/junegunn/vim-slash/issues/7) but can be used by everyone



================================================
FILE: autoload/indexed_search.vim
================================================
function! s:echohl(hl, msg)
    exec 'echohl' a:hl
    echo a:msg
    echohl None
endfunction

function! s:old_search(force)
    let winview = winsaveview()
    let line = winview["lnum"]
    let col = winview["col"] + 1
    let [index, total, is_on_match, first_match_lnum, last_match_lnum] = [0, 0, 0, 0, 0]

    call cursor(1, 1)
    let [matchline, matchcol] = searchpos(@/, 'Wc')
    let first_match_lnum = matchline
    while matchline && (total <= g:indexed_search_max_hits || a:force)
        let total += 1
        let last_match_lnum = matchline
        if matchline < line || (matchline == line && matchcol <= col)
            let index = total
            let is_on_match = matchline == line && matchcol == col
        endif
        let [matchline, matchcol] = searchpos(@/, 'W')
    endwhile
    let out_of_time = (!a:force && total > g:indexed_search_max_hits)
                \ + (!a:force && index > g:indexed_search_max_hits)

    call winrestview(winview)
    return [index, total, is_on_match, out_of_time, first_match_lnum, last_match_lnum]
endfunction

function! s:search(force)
    let [before, after, is_on_match, first_match_lnum, last_match_lnum] = [0, 0, 1, 0, 0]

    let now = reltime()
    let winview = winsaveview()
    let [save_ws, save_fen] = [&wrapscan, &foldenable]
    set nowrapscan nofoldenable

    " If we're at the last line and the file contains no EOL there,
    " `line2byte()` seems (to me) to give a wrong result.
    let eolbug = line('.') == line('$') && !&eol && (&bin || !&fixeol)

    " We need to find out whether the cursor is currently on a match or not
    " since that'll affect our numbering.  Naturally, there's no easy way to
    " get such information.  The hard way is to wiggle the cursor a bit and
    " try to search back and check if we ended up where we started.  There are
    " two edge cases though.
    let curpos = getpos('.')
    if line2byte(line('$') + 1) <= 3
        " The buffer is empty or has only one character.
        " In this case, we can't wiggle the cursor, so we just search and
        " check for the 'E486 Pattern not found' error.
        set wrapscan
        try
            silent keepjumps normal! n
        catch /^Vim[^)]\+):E486\D/
            let is_on_match = 0
        endtry
        set nowrapscan
    elseif line2byte('.') + col('.') - 1 <= 1
        " We're at the very start of the buffer.
        " We move the cursor forwards.
        silent! keepjumps goto 2
        silent! exec 'keepjumps normal!' (v:searchforward ? 'N' : 'n')
    else
        " In every other case, we move the cursor backwards.  This works even
        " if we're at the very edge of the buffer which is nice because I
        " couldn't find any surefire way to check for that.
        silent! exec 'keepjumps goto' (line2byte('.') + col('.') - (eolbug ? 0 : 2))
        silent! exec 'keepjumps normal!' (v:searchforward ? 'n' : 'N')
    endif
    if getpos('.') != curpos | let is_on_match = 0 | endif
    call winrestview(winview)

    " This is the algorithm itself; we first count all the matches before the
    " cursor and then all the ones after it.  To count these, we first try
    " moving in tens; running '10n' is (mostly) the same as running 'n' 10
    " times but it's faster since it runs in C.  If however there are only,
    " say, 9 matches, Vim will internally run 'n' 9 times before announcing
    " that the 10th found no match but with no way to see how many matched;
    " other than counting them one-by-one.  While this wastes some searches as
    " a whole it ends up being far faster than doing it all one-by-one.
    try
        while before <= g:indexed_search_max_hits || a:force
            " if reltimefloat(reltime(now)) > 0.1 | break | endif
            try
                silent keepjumps normal! 10N
                let before += 10
            catch /^Vim[^)]\+):E38[45]\D/
                try
                    silent keepjumps normal! N
                    let before += 1
                catch /^Vim[^)]\+):E38[45]\D/
                    let first_match_lnum = line('.')
                    break
                endtry
            endtry
        endwhile
        call winrestview(winview)
        while before + after <= g:indexed_search_max_hits || a:force
            " if reltimefloat(reltime(now)) > 0.1 | break | endif
            try
                silent keepjumps normal! 10n
                let after += 10
            catch /^Vim[^)]\+):E38[45]\D/
                try
                    silent keepjumps normal! n
                    let after += 1
                catch /^Vim[^)]\+):E38[45]\D/
                    let last_match_lnum = line('.')
                    break
                endtry
            endtry
        endwhile
    finally
        let [&wrapscan, &foldenable] = [save_ws, save_fen]
        call winrestview(winview)
    endtry
    if !v:searchforward
        let [after, before] = [before, after]
        let [first_match_lnum, last_match_lnum] = [last_match_lnum, first_match_lnum]
    end

    let out_of_time = (!a:force && before > g:indexed_search_max_hits)
                \ + (!a:force && after + before > g:indexed_search_max_hits)

    let index = before + is_on_match
    let total = before + after + is_on_match
    return [index, total, is_on_match, out_of_time, first_match_lnum, last_match_lnum]
endfunction

function! s:index_message(index, total, is_on_match, out_of_time, first_match_lnum, last_match_lnum)
    let hl = 'Directory'
    let msg = ''

    let matches = a:total
    if a:out_of_time
        let matches = '> '. a:total
        if !a:is_on_match || a:out_of_time > 1
            return [hl, matches .' matches']
        endif
    endif

    let line_info = ""
    if g:indexed_search_line_info
        let line_info = ' (FM:'. a:first_match_lnum .', LM:'. a:last_match_lnum .')'
    endif
    let shortmatch = matches . line_info . (g:indexed_search_shortmess ? '' : ' matches')

    if a:total == 0
        let hl = 'Error'
        let msg = 'No matches'

    elseif !a:is_on_match && a:index == 0
        let hl = 'WarningMsg'
        let msg = 'Before first match, of '. shortmatch
        if a:total == 1 | let msg = 'Before single match' | endif
    elseif !a:is_on_match && a:index == a:total
        let hl = 'WarningMsg'
        let msg = 'After last match of '. shortmatch
        if a:total == 1 | let msg = 'After single match' | endif
    elseif !a:is_on_match
        " hl remains default
        let msg = 'Between matches '. a:index .'-'. (a:index+1) .' of '. matches . line_info

    elseif !g:indexed_search_numbered_only && a:index == 1 && a:total == 1
        let hl = 'Search'
        let msg = 'Single match'
    elseif !g:indexed_search_numbered_only && a:index == 1
        let hl = 'Search'
        let msg = 'First of '. shortmatch
    elseif !g:indexed_search_numbered_only && a:index == a:total
        let hl = 'LineNr'
        let msg = 'Last of '. shortmatch
    else
        " hl remains default
        let msg = (g:indexed_search_shortmess ? '' : 'Match '). a:index .' of '. matches . line_info
    endif

    return [hl, msg.'  /'.@/.'/']
endfunction


function! indexed_search#show_index(force)
    if @/ == '' || (!a:force && line('$') >= g:indexed_search_max_lines)
        return
    endif

    let results = s:search(a:force)
    let [hl, msg] = call('s:index_message', results)
    call s:echohl(g:indexed_search_colors ? hl : 'None', msg)
endfunction


================================================
FILE: doc/indexed-search.txt
================================================
*indexed-search.txt*  Show match's count and index with search command

Author: Yakov Lerner
        Otto Modinos

INTRODUCTION                                    *indexed-search*

This plugin redefines 6 search commands (/,?,n,N,*,#). At every 
search command, it automatically prints >
       "At match #N out of M matches".
<
-- the total number of matches (M) and the number(index) of current match (N).
This helps to get oriented when searching forward and backward.

There's only one command and no new behavior to learn.  Just watch the bottom
line when you do /,?,n,N,*,#. 

Works on vim7.  Won't cause slowdown on very large files (but then counters
are not displayed). 

=============================================================================
COMMANDS                                        *indexed-search-commands*

                                                    *:ShowSearchIndex*
:ShowSearchIndex        Shows a message indicating your position relative to
                        the search matches in the file.  The message's content
                        also depends on the value of the |g:indexed_search_shortmess|
                        |g:indexed_search_line_info| and |g:indexed_search_colors| options.

=============================================================================
OPTIONS                                         *indexed-search-options*

                                                *g:indexed_search_mappings*
g:indexed_search_mappings
                If 0, does not create mappings.  |indexed-search-mappings|
                Default: 1

                                                *g:indexed_search_dont_move*
g:indexed_search_dont_move
                If 1, the mappings for * and # stay on the word under the
                cursor.  Basically, *N (or #N).
                Default: 0

                                                *g:indexed_search_center*
g:indexed_search_center
                If 1, the mappings for n and N also center the cursor on the
                match.  Basically, nzz (or Nzz).
                Default: 0

                                                *g:indexed_search_max_lines*
g:indexed_search_max_lines
                If a file has more lines than this, the plugin doesn't display
                messages,  for performance reasons. |indexed-search-performance|
                Default: 3000

                                                *g:indexed_search_max_hits*
g:indexed_search_max_hits
                When there are more matches than this, the plugin doesn't try
                to count all of them.  Instead it says, e.g. "> 1000 matches"
                Default: 1000                       |indexed-search-performance|

                                                *g:indexed_search_colors*
g:indexed_search_colors
                If 0, the messages are not displayed in color
                Default: 1
                                                *g:indexed_search_line_info*
g:indexed_search_line_info
                If 1, the messages also mention the first and the last match 
                line number in the following format:
                FM:<first match line no.>, LM:<last match line no.>
                Default: 0

                                                *g:indexed_search_shortmess*
g:indexed_search_shortmess
                If 1, the messages are (a bit) shorter.
                Default: 0

                                                *g:indexed_search_numbered_only*
g:indexed_search_numbered_only
                If 1, the messages only contain the search count.  No
                "First of" and "Last of".
                Default: 0

                                                *g:indexed_search_n_always_searches_forward*
g:indexed_search_n_always_searches_forward
                In vim, by default, the direction of n and N depends on
                whether / or ? was used for searching forward or backward
                respectively.
                If 1, n always search forward and N backward
                Default: 0

=============================================================================
MAPPINGS                                        *indexed-search-mappings*

Indexed Search remaps the standard Vim keys /, ?, *, #, n and N, so that the
appropriate message is displayed afterwards. If you don't want that, you can
disable these mappings by letting |g:indexed_search_mappings| to 0.

=============================================================================
PERFORMANCE                                     *indexed-search-performance*

Plugin bypasses the calculation of match index when it would take too much
time (too many matches, too large file).  You can use |g:indexed_search_max_lines|
and |g:indexed_search_max_hits| to tune these performance limits.

vim:tw=78:ts=8:ft=help:norl:


================================================
FILE: plugin/indexed-search.vim
================================================
" Author:       Yakov Lerner <iler.ml@gmail.com>
" URL:          http://www.vim.org/scripts/script.php?script_id=1682
" Last change:  2018-03-21

" This script redefines 6 search commands (/,?,n,N,*,#). At each search, it
" shows at which match number you are, and the total number of matches, like
" this: "At nth match out of N". This is printed at the bottom line at every
" n,N,/,?,*,# search command, automatically.
"
" I am posting this plugin because I find it useful.

" :ShowSearchIndex - Checking your match index
" -----------------------------------------------------
" At any time, you can use :ShowSearchIndex to show at which match index you
" are without moving the cursor.
"
" If cursor is exactly on the match, the message is:
"     At Nth match of M
" If cursor is between matches, following messages are displayed:
"     Betwen matches 189-190 of 300
"     Before first match, of 300
"     After last match, of 300

" To disable colors for messages, set g:indexed_search_colors to 0.
"
" Performance
" ------------------------------------------------------
" Plugin bypasses match counting when it would take too much time, i.e. too
" many matches or too large a file.  You can change these limits with
" g:indexed_search_max_lines and g:indexed_search_max_hits.


if exists("g:loaded_indexed_search") || &cp || v:version < 700
    finish
endif
let g:loaded_indexed_search = 1

let s:save_cpo = &cpo
set cpo&vim


" Performance tuning limits
if !exists('g:indexed_search_max_lines')
    " Max filesize (in lines) up to where the plugin works
    let g:indexed_search_max_lines = 30000
endif

if !exists("g:indexed_search_max_hits")
    " Max number of matches up to where the plugin stops counting
    let g:indexed_search_max_hits = 1000
endif

" Appearance settings
if !exists('g:indexed_search_colors')
    " Whether to use colors for messages
    let g:indexed_search_colors = 1
endif

if !exists('g:indexed_search_shortmess')
    " Make messages shorter
    let g:indexed_search_shortmess = 0
endif

if !exists('g:indexed_search_numbered_only')
    " Only show index number, no extra words
    let g:indexed_search_numbered_only = 0
endif

if !exists('g:indexed_search_line_info')
    let g:indexed_search_line_info = 0
endif

" Mappings
if !exists('g:indexed_search_mappings')
    let g:indexed_search_mappings = 1
endif

if !exists('g:indexed_search_dont_move')
    let g:indexed_search_dont_move = 0
endif

if !exists('g:indexed_search_center')
    let g:indexed_search_center = 0
endif

if !exists('g:indexed_search_n_always_searches_forward')
    let g:indexed_search_n_always_searches_forward = 0
endif


command! -bang ShowSearchIndex :call indexed_search#show_index(<bang>0)


function! s:should_unfold()
    return has('folding') && &fdo =~ 'search\|all'
endfunction

function! s:has_mapping(name)
    return !empty(maparg(a:name, mode()))
endfunction

function! s:restview()
    call winrestview(s:winview)
endfunction

function! s:star(seq)
    if g:indexed_search_dont_move
        let s:winview = winsaveview()
        return a:seq . "\<Plug>(indexed-search-restview)"
    endif
    return a:seq
endfunction

function! s:n(seq)
    if g:indexed_search_n_always_searches_forward && !v:searchforward
        return ["\<Plug>(indexed-search-n)", "\<Plug>(indexed-search-N)"][a:seq ==# 'n']
    endif
    return a:seq
endfunction

function! s:after()
    return (s:should_unfold() ? 'zv' : '')
                \ .(g:indexed_search_center ? 'zz' : '')
                \ .(s:has_mapping('<Plug>(indexed-search-custom)') ? "\<Plug>(indexed-search-custom)" : '')
                \ ."\<Plug>(indexed-search-index)"
endfunction


if g:indexed_search_mappings
    noremap  <Plug>(indexed-search-index)  <Nop>
    nnoremap <Plug>(indexed-search-index)  :ShowSearchIndex<CR>
    xnoremap <Plug>(indexed-search-index)  :<C-u>ShowSearchIndex<CR>gv

    noremap  <Plug>(indexed-search-n)  n
    noremap  <Plug>(indexed-search-N)  N

    noremap  <Plug>(indexed-search-restview)  :call <SID>restview()<CR>
    xnoremap <Plug>(indexed-search-restview)  :<C-u>call <SID>restview()<CR>gv

    map  <expr> <Plug>(indexed-search-after)  <SID>after()
    imap        <Plug>(indexed-search-after)  <Nop>

    cmap <expr> <CR> "\<CR>" . (getcmdtype() =~ '[/?]' ? "\<Plug>(indexed-search-after)" : '')
    " map  <expr> gd   'gd'    . "\<Plug>(indexed-search-after)"
    " map  <expr> gD   'gD'    . "\<Plug>(indexed-search-after)"
    map  <expr> *    <SID>star('*')  . "\<Plug>(indexed-search-after)"
    map  <expr> #    <SID>star('#')  . "\<Plug>(indexed-search-after)"
    map  <expr> g*   <SID>star('g*') . "\<Plug>(indexed-search-after)"
    map  <expr> g#   <SID>star('g#') . "\<Plug>(indexed-search-after)"
    map  <expr> n    <SID>n('n')     . "\<Plug>(indexed-search-after)"
    map  <expr> N    <SID>n('N')     . "\<Plug>(indexed-search-after)"
endif


let &cpo = s:save_cpo

" Wishlist
" -  using high-precision timer of vim7, count number of millisec
"    to run the counters, and base auto-disabling on time it takes.
"    very complex regexes can be terribly slow even of files like 'man bash'
"    which is mere 5k lines long. Also when there are >10k matches in the file
"    set limit to 200 millisec
" - implement CursorHold bg counting to which too_slow will resort
" - even on large files, we can show "At last match", "After last match"
" - define global vars for all highlights, with defaults
Download .txt
gitextract_ydkyj2o8/

├── .gitignore
├── README.md
├── autoload/
│   └── indexed_search.vim
├── doc/
│   └── indexed-search.txt
└── plugin/
    └── indexed-search.vim
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (20K chars).
[
  {
    "path": ".gitignore",
    "chars": 9,
    "preview": "doc/tags\n"
  },
  {
    "path": "README.md",
    "chars": 1728,
    "preview": "# IndexedSearch.vim\n\nRequires vim7.4\n\nOriginally by [Yakov Lerner](http://www.vim.org/account/profile.php?user_id=2342) "
  },
  {
    "path": "autoload/indexed_search.vim",
    "chars": 7480,
    "preview": "function! s:echohl(hl, msg)\n    exec 'echohl' a:hl\n    echo a:msg\n    echohl None\nendfunction\n\nfunction! s:old_search(fo"
  },
  {
    "path": "doc/indexed-search.txt",
    "chars": 4883,
    "preview": "*indexed-search.txt*  Show match's count and index with search command\n\nAuthor: Yakov Lerner\n        Otto Modinos\n\nINTRO"
  },
  {
    "path": "plugin/indexed-search.vim",
    "chars": 5430,
    "preview": "\" Author:       Yakov Lerner <iler.ml@gmail.com>\n\" URL:          http://www.vim.org/scripts/script.php?script_id=1682\n\" "
  }
]

About this extraction

This page contains the full source code of the henrik/vim-indexed-search GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (19.1 KB), approximately 5.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!