mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-23 07:20:04 +08:00
Grep on the fly (#705)
* Grep on the fly * Fix screen update * Fix commands for prompt * Supprt <BS> in prompt * Redrew on stdout * Fix prompt api * Improve flygrep screen update * Add function keys for flygrep buffer * Add statusline support && ignore case * Add highlight feature * Fix highlight error * Ignore FocusLost and FocusGained * Add prompt mappings * Add documentation for fly searching * Update documentation * Fix lint for flygrep
This commit is contained in:
parent
6845ac5f74
commit
d6f184f2da
132
autoload/SpaceVim/api/prompt.vim
Normal file
132
autoload/SpaceVim/api/prompt.vim
Normal file
@ -0,0 +1,132 @@
|
||||
let s:self = {}
|
||||
|
||||
|
||||
let s:self._keys = {
|
||||
\ 'close' : "\<Esc>",
|
||||
\ 'cursor_back' : '<Left>',
|
||||
\ 'cursor_forword' : '<Right>',
|
||||
\ }
|
||||
let s:self._prompt = {
|
||||
\ 'mpt' : '==>',
|
||||
\ 'begin' : '',
|
||||
\ 'cursor' : '',
|
||||
\ 'end' : '',
|
||||
\ }
|
||||
let s:self._function_key = {}
|
||||
|
||||
let s:self._quit = 1
|
||||
|
||||
let s:self._handle_fly = ''
|
||||
let s:self._onclose = ''
|
||||
let s:self._oninputpro = ''
|
||||
|
||||
|
||||
|
||||
func! s:self.open() abort
|
||||
let self._quit = 0
|
||||
let save_redraw = &lazyredraw
|
||||
set nolazyredraw
|
||||
call self._build_prompt()
|
||||
call self._handle_input()
|
||||
let &lazyredraw = save_redraw
|
||||
endf
|
||||
|
||||
function! s:self._getchar(...) abort
|
||||
let ret = call('getchar', a:000)
|
||||
return (type(ret) == type(0) ? nr2char(ret) : ret)
|
||||
endfunction
|
||||
|
||||
func! s:self._handle_input() abort
|
||||
while self._quit == 0
|
||||
let char = self._getchar()
|
||||
if has_key(self._function_key, char)
|
||||
call call(self._function_key[char], [])
|
||||
continue
|
||||
endif
|
||||
if char ==# "\<FocusLost>" || char ==# "\<FocusGained>"
|
||||
continue
|
||||
endif
|
||||
if char ==# "\<Right>" || char == 6
|
||||
let self._prompt.begin = self._prompt.begin . self._prompt.cursor
|
||||
let self._prompt.cursor = matchstr(self._prompt.end, '^.')
|
||||
let self._prompt.end = substitute(self._prompt.end, '^.', '', 'g')
|
||||
call self._build_prompt()
|
||||
continue
|
||||
elseif char ==# "\<Left>" || char == 2
|
||||
if self._prompt.begin !=# ''
|
||||
let self._prompt.end = self._prompt.cursor . self._prompt.end
|
||||
let self._prompt.cursor = matchstr(self._prompt.begin, '.$')
|
||||
let self._prompt.begin = substitute(self._prompt.begin, '.$', '', 'g')
|
||||
call self._build_prompt()
|
||||
endif
|
||||
continue
|
||||
elseif char ==# "\<C-w>"
|
||||
let self._prompt.begin = substitute(self._prompt.begin,'[^\ .*]\+\s*$','','g')
|
||||
call self._build_prompt()
|
||||
elseif char ==# "\<C-a>" || char ==# "\<Home>"
|
||||
let self._prompt.end = substitute(self._prompt.begin . self._prompt.cursor . self._prompt.end, '^.', '', 'g')
|
||||
let self._prompt.cursor = matchstr(self._prompt.begin, '^.')
|
||||
let self._prompt.begin = ''
|
||||
call self._build_prompt()
|
||||
continue
|
||||
elseif char ==# "\<C-e>" || char ==# "\<End>"
|
||||
let self._prompt.begin = self._prompt.begin . self._prompt.cursor . self._prompt.end
|
||||
let self._prompt.cursor = ''
|
||||
let self._prompt.end = ''
|
||||
call self._build_prompt()
|
||||
continue
|
||||
elseif char ==# "\<C-u>"
|
||||
let self._prompt.begin = ''
|
||||
call self._build_prompt()
|
||||
elseif char ==# "\<C-k>"
|
||||
let self._prompt.cursor = ''
|
||||
let self._prompt.end = ''
|
||||
call self._build_prompt()
|
||||
elseif char ==# "\<bs>"
|
||||
let self._prompt.begin = substitute(self._prompt.begin,'.$','','g')
|
||||
call self._build_prompt()
|
||||
elseif char == self._keys.close
|
||||
call self.close()
|
||||
break
|
||||
else
|
||||
let self._prompt.begin .= char
|
||||
call self._build_prompt()
|
||||
endif
|
||||
if self._oninputpro !=# ''
|
||||
call call(self._oninputpro, [])
|
||||
endif
|
||||
if self._handle_fly !=# ''
|
||||
call call(self._handle_fly, [self._prompt.begin . self._prompt.cursor . self._prompt.end])
|
||||
endif
|
||||
endwhile
|
||||
endf
|
||||
|
||||
func! s:self._build_prompt() abort
|
||||
redraw
|
||||
echohl Comment | echon self._prompt.mpt
|
||||
echohl None | echon self._prompt.begin
|
||||
echohl Wildmenu | echon self._prompt.cursor
|
||||
echohl None | echon self._prompt.end
|
||||
endf
|
||||
|
||||
function! s:self._clear_prompt() abort
|
||||
let self._prompt = {
|
||||
\ 'mpt' : self._prompt.mpt,
|
||||
\ 'begin' : '',
|
||||
\ 'cursor' : '',
|
||||
\ 'end' : '',
|
||||
\ }
|
||||
endfunction
|
||||
|
||||
function! s:self.close() abort
|
||||
if self._onclose !=# ''
|
||||
call call(self._onclose, [])
|
||||
endif
|
||||
call self._clear_prompt()
|
||||
normal! :
|
||||
let self._quit = 1
|
||||
endfunction
|
||||
|
||||
function! SpaceVim#api#prompt#get() abort
|
||||
return deepcopy(s:self)
|
||||
endfunction
|
@ -214,6 +214,10 @@ function! SpaceVim#layers#core#statusline#get(...) abort
|
||||
\ . '%#SpaceVim_statusline_a_bold_SpaceVim_statusline_b# %{get(unite#get_context(), "buffer_name", "")} '
|
||||
\ . '%#SpaceVim_statusline_b_SpaceVim_statusline_c# '
|
||||
\ . '%#SpaceVim_statusline_c# %{unite#get_status_string()} '
|
||||
elseif &filetype ==# 'SpaceVimFlyGrep'
|
||||
return '%#SpaceVim_statusline_a# FlyGrep %#SpaceVim_statusline_a_SpaceVim_statusline_b#'
|
||||
\ . '%#SpaceVim_statusline_b# %{getcwd()}%#SpaceVim_statusline_b_SpaceVim_statusline_c#'
|
||||
\ . '%#SpaceVim_statusline_c# %{SpaceVim#plugins#flygrep#lineNr()}'
|
||||
endif
|
||||
if a:0 > 0
|
||||
return s:active()
|
||||
|
@ -196,6 +196,9 @@ function! SpaceVim#mapping#space#init() abort
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['s', 't', 'J'], 'call SpaceVim#plugins#searcher#find(expand("<cword>"), "pt")',
|
||||
\ 'Background search cursor words in project with pt', 1)
|
||||
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['s', 'g', 'G'], 'call SpaceVim#plugins#flygrep#open()',
|
||||
\ 'grep on the fly', 1)
|
||||
|
||||
call SpaceVim#mapping#space#def('nnoremap', ['s', 'c'], 'noh',
|
||||
\ 'clear search highlight', 1)
|
||||
endfunction
|
||||
|
133
autoload/SpaceVim/plugins/flygrep.vim
Normal file
133
autoload/SpaceVim/plugins/flygrep.vim
Normal file
@ -0,0 +1,133 @@
|
||||
let s:MPT = SpaceVim#api#import('prompt')
|
||||
let s:JOB = SpaceVim#api#import('job')
|
||||
let s:grepid = 0
|
||||
|
||||
|
||||
function! SpaceVim#plugins#flygrep#open() abort
|
||||
rightbelow split __flygrep__
|
||||
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber
|
||||
" setlocal nomodifiable
|
||||
setf SpaceVimFlyGrep
|
||||
redraw!
|
||||
call s:MPT.open()
|
||||
endfunction
|
||||
|
||||
function! s:flygrep(expr) abort
|
||||
call s:MPT._build_prompt()
|
||||
if a:expr ==# ''
|
||||
redrawstatus
|
||||
return
|
||||
endif
|
||||
try
|
||||
syn clear FileNames
|
||||
catch
|
||||
endtr
|
||||
exe 'syn match FileNames /' . substitute(a:expr, '\([/\\]\)', '\\\1', 'g') . '/'
|
||||
hi def link FileNames MoreMsg
|
||||
let exe = SpaceVim#mapping#search#default_tool()
|
||||
let s:grepid = s:JOB.start(s:get_search_cmd(exe, a:expr), {
|
||||
\ 'on_stdout' : function('s:grep_stdout'),
|
||||
\ 'in_io' : 'null',
|
||||
\ 'on_exit' : function('s:grep_exit'),
|
||||
\ })
|
||||
endfunction
|
||||
|
||||
let s:MPT._handle_fly = function('s:flygrep')
|
||||
|
||||
function! s:close_buffer() abort
|
||||
q
|
||||
endfunction
|
||||
|
||||
let s:MPT._onclose = function('s:close_buffer')
|
||||
|
||||
|
||||
function! s:close_grep_job() abort
|
||||
if s:grepid != 0
|
||||
call s:JOB.stop(s:grepid)
|
||||
endif
|
||||
normal! "_ggdG
|
||||
endfunction
|
||||
|
||||
let s:MPT._oninputpro = function('s:close_grep_job')
|
||||
|
||||
" @vimlint(EVL103, 1, a:data)
|
||||
" @vimlint(EVL103, 1, a:id)
|
||||
" @vimlint(EVL103, 1, a:event)
|
||||
function! s:grep_stdout(id, data, event) abort
|
||||
let datas =filter(a:data, '!empty(v:val)')
|
||||
if getline(1) ==# ''
|
||||
call setline(1, datas)
|
||||
else
|
||||
call append('$', datas)
|
||||
endif
|
||||
call s:MPT._build_prompt()
|
||||
endfunction
|
||||
|
||||
function! s:grep_exit(id, data, event) abort
|
||||
redrawstatus
|
||||
let s:grepid = 0
|
||||
endfunction
|
||||
|
||||
" @vimlint(EVL103, 0, a:data)
|
||||
" @vimlint(EVL103, 0, a:id)
|
||||
" @vimlint(EVL103, 0, a:event)
|
||||
|
||||
function! s:get_search_cmd(exe, expr) abort
|
||||
if a:exe ==# 'grep'
|
||||
return ['grep', '-inHR', '--exclude-dir', '.git', a:expr, '.']
|
||||
elseif a:exe ==# 'rg'
|
||||
return ['rg', '-n', '-i', a:expr]
|
||||
else
|
||||
return [a:exe, a:expr]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:next_item() abort
|
||||
if line('.') == line('$')
|
||||
normal! gg
|
||||
else
|
||||
normal! j
|
||||
endif
|
||||
redrawstatus
|
||||
call s:MPT._build_prompt()
|
||||
endfunction
|
||||
|
||||
function! s:previous_item() abort
|
||||
if line('.') == 1
|
||||
normal! G
|
||||
else
|
||||
normal! k
|
||||
endif
|
||||
redrawstatus
|
||||
call s:MPT._build_prompt()
|
||||
endfunction
|
||||
|
||||
function! s:open_item() abort
|
||||
if line('.') !=# ''
|
||||
if s:grepid != 0
|
||||
call s:JOB.stop(s:grepid)
|
||||
endif
|
||||
call s:MPT._clear_prompt()
|
||||
let s:MPT._quit = 1
|
||||
normal! gF
|
||||
let nr = bufnr('%')
|
||||
q
|
||||
exe 'silent b' . nr
|
||||
normal! :
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:MPT._function_key = {
|
||||
\ "\<Tab>" : function('s:next_item'),
|
||||
\ "\<S-tab>" : function('s:previous_item'),
|
||||
\ "\<Return>" : function('s:open_item'),
|
||||
\ }
|
||||
|
||||
" statusline api
|
||||
function! SpaceVim#plugins#flygrep#lineNr() abort
|
||||
if getline(1) ==# ''
|
||||
return ''
|
||||
else
|
||||
return line('.') . '/' . line('$')
|
||||
endif
|
||||
endfunction
|
@ -2,7 +2,7 @@ let s:JOB = SpaceVim#api#import('job')
|
||||
|
||||
let s:rst = []
|
||||
|
||||
function! SpaceVim#plugins#searcher#find(expr, exe)
|
||||
function! SpaceVim#plugins#searcher#find(expr, exe) abort
|
||||
if empty(a:expr)
|
||||
let expr = input('search expr: ')
|
||||
else
|
||||
@ -14,6 +14,8 @@ function! SpaceVim#plugins#searcher#find(expr, exe)
|
||||
\ 'on_exit' : function('s:search_exit'),
|
||||
\ })
|
||||
endfunction
|
||||
" @vimlint(EVL103, 1, a:id)
|
||||
" @vimlint(EVL103, 1, a:event)
|
||||
function! s:search_stdout(id, data, event) abort
|
||||
for data in a:data
|
||||
let info = split(data, '\:\d\+\:')
|
||||
@ -30,27 +32,31 @@ function! s:search_stdout(id, data, event) abort
|
||||
endfunction
|
||||
|
||||
function! s:get_search_cmd(exe, expr) abort
|
||||
if a:exe == 'grep'
|
||||
if a:exe ==# 'grep'
|
||||
return ['grep', '-inHR', '--exclude-dir', '.git', a:expr, '.']
|
||||
elseif a:exe == 'rg'
|
||||
elseif a:exe ==# 'rg'
|
||||
return ['rg', '-n', a:expr]
|
||||
else
|
||||
return [a:exe, a:expr]
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @vimlint(EVL103, 1, a:data)
|
||||
function! s:search_exit(id, data, event) abort
|
||||
let &l:statusline = SpaceVim#layers#core#statusline#get(1)
|
||||
endfunction
|
||||
|
||||
" @vimlint(EVL103, 0, a:data)
|
||||
" @vimlint(EVL103, 0, a:id)
|
||||
" @vimlint(EVL103, 0, a:event)
|
||||
|
||||
function! SpaceVim#plugins#searcher#list()
|
||||
function! SpaceVim#plugins#searcher#list() abort
|
||||
call setqflist(s:rst)
|
||||
let s:rst = []
|
||||
copen
|
||||
endfunction
|
||||
|
||||
function! SpaceVim#plugins#searcher#count()
|
||||
function! SpaceVim#plugins#searcher#count() abort
|
||||
if empty(s:rst)
|
||||
return ''
|
||||
else
|
||||
|
@ -76,6 +76,7 @@ title: "Documentation"
|
||||
* [Searching in a project](#searching-in-a-project)
|
||||
* [Background searching in a project](#background-searching-in-a-project)
|
||||
* [Searching the web](#searching-the-web)
|
||||
* [Searching on the fly](#searching-on-the-fly)
|
||||
* [Persistent highlighting](#persistent-highlighting)
|
||||
* [Editing](#editing)
|
||||
* [Text insertion commands](#text-insertion-commands)
|
||||
@ -1117,13 +1118,35 @@ Key Binding | Description
|
||||
|
||||
##### Searching the web
|
||||
|
||||
Key Binding Description
|
||||
Key Binding | Description
|
||||
-----------| -----------
|
||||
`SPC s w g` | Get Google suggestions in vim. Opens Google results in Browser.
|
||||
`SPC s w w` | Get Wikipedia suggestions in vim. Opens Wikipedia page in Browser.(TODO)
|
||||
|
||||
**Note**: to enable google suggestions in vim, you need to add `let g:spacevim_enable_googlesuggest = 1` to your custom Configuration file.
|
||||
|
||||
#### Searching on the fly
|
||||
|
||||
Key Binding | Description
|
||||
-----------| -----------
|
||||
`SPC s g G` | Searching in project on the fly with default tools
|
||||
|
||||
key binding in FlyGrep buffer:
|
||||
|
||||
Key Binding Description
|
||||
-----------| -----------
|
||||
`<Esc>` | close FlyGrep buffer
|
||||
`<Enter>` | open file at the cursor line
|
||||
`<Tab>` | move cursor line down
|
||||
`<S-Tab>` | move cursor line up
|
||||
`<Bs>` | remove last character
|
||||
`<C-w>` | remove the Word before the cursor
|
||||
`<C-u>` | remove the Line before the cursor
|
||||
`<C-k>` | remove the Line after the cursor
|
||||
`<C-a>`/`<Home>` | Go to the beginning of the line
|
||||
`<C-e>`/`<End>` | Go to the end of the line
|
||||
|
||||
|
||||
#### Persistent highlighting
|
||||
|
||||
SpaceVim uses `g:spacevim_search_highlight_persist` to keep the searched expression highlighted until the next search. It is also possible to clear the highlighting by pressing `SPC s c` or executing the ex command `:noh`.
|
||||
|
8
syntax/SpaceVimFlyGrep.vim
Normal file
8
syntax/SpaceVimFlyGrep.vim
Normal file
@ -0,0 +1,8 @@
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
let b:current_syntax = "SpaceVimFlyGrep"
|
||||
syntax case ignore
|
||||
syn match FileName /[^:]*:\d\+:/
|
||||
|
||||
hi def link FileName Comment
|
Loading…
Reference in New Issue
Block a user