Skip to main content
added 541 characters in body
Source Link

One more subtlety is that we need to get the "startcol", that is, the start of the text being replaced, so that selecting the completions replaces that text, rather than appending to the end. We find this by <C-n> (to ensure some completion is selected), get the cursor position after the selection and finding the length of the selected completion by complete_info(), and compensating the <C-n> with a <C-p>. The "startcol" is the cursor position after selection minus the length of the selected completion.

Some more subtleties about the implementation:

  1. We need to get the "startcol", that is, the start of the text being replaced, so that selecting the completions replaces that text, rather than appending to the end. We find this by <C-n> (to ensure some completion is selected), get the cursor position after the selection and finding the length of the selected completion by complete_info(), and compensating the <C-n> with a <C-p>. The "startcol" is the cursor position after selection minus the length of the selected completion.
  2. Naively passing <C-e> back into the mapping may not work, because the popup menu state is reset when we call complete(), so we have to save the value ourselves and restore it. Similarly, we should persist this state when we perform <C-/> to refine the search. We find the state by performing <C-e> and saving the result before starting the completion search.
  3. Only apply the mapping when pum is active.

This is the result:

function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        
        if exists('g:lastexittext')
            let exittext = g:lastexittext
            unlet g:lastexittext
        else
            let exitcol = col('.')
            let exittext = getline('.')[startcol-1:exitcol-2]
            endif
        
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
            if len(matchwords) == 0
                call add (matchwords, exittext)
                endif
                
            call complete(startcol, matchwords)
            
            echomsg '/' .. filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                call complete(startcol, [exittext])
                return "\<C-e>"y>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                call feedkeys ("\<C-_>")
           let g:lastexittext = exittext
  return ""
            elseif charcall ==feedkeys "\<CR>"("\<C-_>")
                return ""
            elseif char == "\<BS>"
                if len(filter) == 1"\<CR>"
                    let filter =return ""
             elseif char == else"\<BS>"
                    let filter = filter[:len(filter) - 2]
                    endif
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> pumvisible() ? Prepareearchpum () . '<C-e><C-r>=Searchpum()<CR>' : '<C-_>'

One more subtlety is that we need to get the "startcol", that is, the start of the text being replaced, so that selecting the completions replaces that text, rather than appending to the end. We find this by <C-n> (to ensure some completion is selected), get the cursor position after the selection and finding the length of the selected completion by complete_info(), and compensating the <C-n> with a <C-p>. The "startcol" is the cursor position after selection minus the length of the selected completion.

function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
                
            call complete(startcol, matchwords)
            
            echomsg '/' .. filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                return "\<C-e>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                call feedkeys ("\<C-_>")
                return ""
            elseif char == "\<CR>"
                return ""
            elseif char == "\<BS>"
                if len(filter) == 1
                    let filter = ""
                else
                    let filter = filter[:len(filter) - 2]
                    endif
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> Prepareearchpum () . '<C-r>=Searchpum()<CR>'

Some more subtleties about the implementation:

  1. We need to get the "startcol", that is, the start of the text being replaced, so that selecting the completions replaces that text, rather than appending to the end. We find this by <C-n> (to ensure some completion is selected), get the cursor position after the selection and finding the length of the selected completion by complete_info(), and compensating the <C-n> with a <C-p>. The "startcol" is the cursor position after selection minus the length of the selected completion.
  2. Naively passing <C-e> back into the mapping may not work, because the popup menu state is reset when we call complete(), so we have to save the value ourselves and restore it. Similarly, we should persist this state when we perform <C-/> to refine the search. We find the state by performing <C-e> and saving the result before starting the completion search.
  3. Only apply the mapping when pum is active.

This is the result:

function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        
        if exists('g:lastexittext')
            let exittext = g:lastexittext
            unlet g:lastexittext
        else
            let exitcol = col('.')
            let exittext = getline('.')[startcol-1:exitcol-2]
            endif
        
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
            if len(matchwords) == 0
                call add (matchwords, exittext)
                endif
                
            call complete(startcol, matchwords)
            
            echomsg '/' .. filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                call complete(startcol, [exittext])
                return "\<C-y>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                let g:lastexittext = exittext
                call feedkeys ("\<C-_>")
                return ""
            elseif char == "\<CR>"
                return ""
            elseif char == "\<BS>"
                let filter = filter[:-2]
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> pumvisible() ? Prepareearchpum () . '<C-e><C-r>=Searchpum()<CR>' : '<C-_>'
added 7 characters in body
Source Link
function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
                
            call complete(startcol, matchwords)
            
            echomsg '/' .. filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                return "\<C-e>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                call feedkeys ("\<C-_>")
                return ""
            elseif char == "\<CR>"
                return ""
            elseif char == "\<BS>"
                if len(filter) == 1
                    let filter = ""
                else
                    let filter = filter[:len(filter) - 2]
                    endif
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> Prepareearchpum () . '<C-r>=Searchpum()<CR>'
function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
                
            call complete(startcol, matchwords)
            
            echomsg filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                return "\<C-e>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                call feedkeys ("\<C-_>")
                return ""
            elseif char == "\<CR>"
                return ""
            elseif char == "\<BS>"
                if len(filter) == 1
                    let filter = ""
                else
                    let filter = filter[:len(filter) - 2]
                    endif
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> Prepareearchpum () . '<C-r>=Searchpum()<CR>'
function! Prepareearchpum ()
    let g:compstartcol = col('.')
    let g:compinf = complete_info()
    
    if len(g:compinf.items) && (g:compinf.selected == -1)
        return "\<C-n>\<C-r>=Prepareearchpum()\<CR>\<C-p>"
    else
        return ""
        endif
    endfunction
function! Searchpum ()
    let words = []
    for item in g:compinf.items
        call add(words, item.word)
        endfor
        
    let filter = ""

    if len(words)
        let startcol = g:compstartcol - len(g:compinf.items[g:compinf.selected].word)
        while 1
            let matchwords = []
            for word in words
                if word =~ filter
                    call add (matchwords, word)
                    endif
                endfor
                
            call complete(startcol, matchwords)
            
            echomsg '/' .. filter
            
            try
                let char = getchar()
            catch /^Vim:Interrupt$/
                return "\<C-c>"
                endtry

            if type(char) == 0
                let char = nr2char(char)
                endif

            if char == "\<C-e>"
                return "\<C-e>"
            elseif char == "\<C-y>"
                return "\<C-y>"
            elseif char == "\<C-n>"
                return "\<C-n>"
            elseif char == "\<C-p>"
                return "\<C-p>"
            elseif char == "\<C-l>"
                return "\<C-l>"
            elseif char == "\<C-h>"
                return "\<C-h>"
            elseif char == "\<Up>"
                return "\<Up>"
            elseif char == "\<Down>"
                return "\<Down>"
            elseif char == "\<Esc>"
                return "\<Esc>"
            elseif char == "\<C-_>"
                call feedkeys ("\<C-_>")
                return ""
            elseif char == "\<CR>"
                return ""
            elseif char == "\<BS>"
                if len(filter) == 1
                    let filter = ""
                else
                    let filter = filter[:len(filter) - 2]
                    endif
            elseif char == "\<C-u>"
                let filter = ""
            else
                let filter = filter .. char
                endif
            endwhile
        endif
    endfunction
inoremap <expr> <C-_> Prepareearchpum () . '<C-r>=Searchpum()<CR>'
deleted 1 character in body
Source Link

I mapped this to <C-/>/<C-_>. To use this, after getting a lot of completions (e.g. from <C-n> or <C-x><C-i>), invoke <C-/> and start typing to search for the completion you need. You will see your search at the bottom of the screen (like the usual commandsearch prompt). You can see the completions being filtered as you type.

I mapped this to <C-/>/<C-_>. To use this, after getting a lot of completions (e.g. from <C-n> or <C-x><C-i>), invoke <C-/> and start typing to search for the completion you need. You will see your search at the bottom of the screen (like the usual command prompt). You can see the completions being filtered as you type.

I mapped this to <C-/>/<C-_>. To use this, after getting a lot of completions (e.g. from <C-n> or <C-x><C-i>), invoke <C-/> and start typing to search for the completion you need. You will see your search at the bottom of the screen (like the usual search prompt). You can see the completions being filtered as you type.

deleted 1 character in body
Source Link
Loading
added 186 characters in body
Source Link
Loading
added 91 characters in body
Source Link
Loading
Source Link
Loading