1
0
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:
Wang Shidong 2017-07-06 21:59:09 +08:00 committed by GitHub
parent 6845ac5f74
commit d6f184f2da
7 changed files with 315 additions and 6 deletions

View 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

View File

@ -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()

View File

@ -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

View 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

View File

@ -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

View File

@ -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`.

View 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