augroup vimrc-selector autocmd! autocmd User SelectorChanged : augroup END function! s:cursor_changed() abort let old = get(s:, 'current', 'xyzzy') let new = getline('.') .. getcmdline() if old !=# new let s:current = new doautocmd <nomodeline> User SelectorChanged endif endfunction function! selector#changed() abort if expand('<afile>') !=# '@' return endif let oldline = get(b:, 'oldline', "\<Nul>") let newline = getcmdline() if oldline ==# newline return endif let b:oldline = newline let filtered = b:filter(getcmdline()) call deletebufline('%', 1, '$') call setbufline('%', 1, filtered) call cursor(1, 1) call s:cursor_changed() redraw endfunction function! s:down() abort let current = line('.') if current == line('$') let next = 1 else let next = current + 1 endif call cursor(next, 1) redraw call s:cursor_changed() return '' endfunction function! s:up() abort let current = line('.') if current == 1 let next = line('$') else let next = current - 1 endif call cursor(next, 1) redraw call s:cursor_changed() return '' endfunction function! selector#run(source, ...) abort let winid = win_getid() let rest = winrestcmd() botright 1new let filter_name = get(a:000, 0, 'exact') call selector#filter#{filter_name}#gather(a:source) let b:filter = function(printf('selector#filter#%s#filter', get(a:000, 0, 'exact'))) execute 'resize' &cmdwinheight setlocal buftype=nofile bufhidden=hide noswapfile cursorline autocmd CmdlineEnter,CmdlineChanged <buffer> call selector#changed() cnoremap <buffer> <Esc> <C-c> " vim cnoremap <silent> <buffer> <C-j> <C-r>=<SID>down()<CR> cnoremap <silent> <buffer> <C-k> <C-r>=<SID>up()<CR> " emacs cnoremap <silent> <buffer> <C-n> <C-r>=<SID>down()<CR> cnoremap <silent> <buffer> <C-p> <C-r>=<SID>up()<CR> " cursor cnoremap <silent> <buffer> <Down> <C-r>=<SID>down()<CR> cnoremap <silent> <buffer> <Up> <C-r>=<SID>up()<CR> try let result = input('> ') return getline('.') catch finally close call win_gotoid(winid) execute rest endtry endfunction