mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 12:40:05 +08:00
283 lines
8.8 KiB
VimL
283 lines
8.8 KiB
VimL
"=============================================================================
|
|
" FILE: grep.vim
|
|
" AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com>
|
|
" Tomohiro Nishimura <tomohiro68 at gmail.com>
|
|
" License: MIT license
|
|
"=============================================================================
|
|
|
|
" Variables "{{{
|
|
" Set from grepprg.
|
|
call unite#util#set_default(
|
|
\ 'g:unite_source_grep_command', 'grep')
|
|
call unite#util#set_default(
|
|
\ 'g:unite_source_grep_default_opts', '-inH')
|
|
call unite#util#set_default('g:unite_source_grep_recursive_opt', '-r')
|
|
call unite#util#set_default('g:unite_source_grep_search_word_highlight',
|
|
\ 'Search')
|
|
call unite#util#set_default('g:unite_source_grep_encoding', 'char')
|
|
" Note: jvgrep does not support "--" separator
|
|
call unite#util#set_default('g:unite_source_grep_separator',
|
|
\ (g:unite_source_grep_command !=# 'jvgrep' ? '--' : ''))
|
|
"}}}
|
|
|
|
function! unite#sources#grep#define() abort "{{{
|
|
return s:source
|
|
endfunction "}}}
|
|
|
|
let s:source = {
|
|
\ 'name': 'grep',
|
|
\ 'max_candidates': 1000,
|
|
\ 'hooks' : {},
|
|
\ 'syntax' : 'uniteSource__Grep',
|
|
\ 'matchers' : 'matcher_regexp',
|
|
\ 'sorters' : 'sorter_nothing',
|
|
\ 'ignore_globs' : [
|
|
\ '*~', '*.o', '*.exe', '*.bak',
|
|
\ 'DS_Store', '*.pyc', '*.sw[po]', '*.class',
|
|
\ '.hg/**', '.git/**', '.bzr/**', '.svn/**',
|
|
\ 'tags', 'tags-*'
|
|
\ ],
|
|
\ }
|
|
|
|
function! s:source.hooks.on_init(args, context) abort "{{{
|
|
if !unite#util#has_vimproc()
|
|
call unite#print_source_error(
|
|
\ 'vimproc is not installed.', s:source.name)
|
|
return
|
|
endif
|
|
|
|
let target = get(a:args, 0, '')
|
|
|
|
if target ==# ''
|
|
let target = isdirectory(a:context.path) ?
|
|
\ a:context.path :
|
|
\ unite#util#input('Target: ', '.', 'file')
|
|
endif
|
|
|
|
let target = unite#util#expand(target)
|
|
|
|
if target ==# ''
|
|
let a:context.source__targets = []
|
|
let a:context.source__input = ''
|
|
return
|
|
endif
|
|
|
|
let targets = split(target, "\n")
|
|
if target ==# '%' || target ==# '#'
|
|
let targets = [bufname(target)]
|
|
elseif target ==# '$buffers'
|
|
let targets = map(filter(range(1, bufnr('$')),
|
|
\ 'buflisted(v:val) && filereadable(bufname(v:val))'),
|
|
\ 'bufname(v:val)')
|
|
elseif target ==# '**'
|
|
" Optimized.
|
|
let targets = ['.']
|
|
endif
|
|
|
|
let targets = map(targets, 'substitute(v:val, "\\*\\+$", "", "")')
|
|
let a:context.source__targets =
|
|
\ map(targets, 'unite#helper#parse_source_path(v:val)')
|
|
|
|
let a:context.source__extra_opts = get(a:args, 1, '')
|
|
|
|
let a:context.source__input = get(a:args, 2, a:context.input)
|
|
if a:context.source__input == '' || a:context.unite__is_restart
|
|
let a:context.source__input = unite#util#input('Pattern: ',
|
|
\ a:context.source__input,
|
|
\ 'customlist,unite#helper#complete_search_history')
|
|
endif
|
|
|
|
call unite#print_source_message('Pattern: '
|
|
\ . a:context.source__input, s:source.name)
|
|
|
|
let a:context.source__directory =
|
|
\ (len(a:context.source__targets) == 1) ?
|
|
\ unite#util#substitute_path_separator(
|
|
\ unite#util#expand(a:context.source__targets[0])) : ''
|
|
endfunction"}}}
|
|
function! s:source.hooks.on_syntax(args, context) abort "{{{
|
|
if !unite#util#has_vimproc()
|
|
return
|
|
endif
|
|
|
|
syntax case ignore
|
|
syntax match uniteSource__GrepHeader /[^:]*: \d\+: \(\d\+: \)\?/ contained
|
|
\ containedin=uniteSource__Grep
|
|
syntax match uniteSource__GrepFile /[^:]*: / contained
|
|
\ containedin=uniteSource__GrepHeader
|
|
\ nextgroup=uniteSource__GrepLineNR
|
|
syntax match uniteSource__GrepLineNR /\d\+: / contained
|
|
\ containedin=uniteSource__GrepHeader
|
|
\ nextgroup=uniteSource__GrepPattern
|
|
execute 'syntax match uniteSource__GrepPattern /'
|
|
\ . substitute(a:context.source__input, '\([/\\]\)', '\\\1', 'g')
|
|
\ . '/ contained containedin=uniteSource__Grep'
|
|
syntax match uniteSource__GrepSeparator /:/ contained conceal
|
|
\ containedin=uniteSource__GrepFile,uniteSource__GrepLineNR
|
|
highlight default link uniteSource__GrepFile Comment
|
|
highlight default link uniteSource__GrepLineNr LineNR
|
|
execute 'highlight default link uniteSource__GrepPattern'
|
|
\ get(a:context, 'custom_grep_search_word_highlight',
|
|
\ g:unite_source_grep_search_word_highlight)
|
|
endfunction"}}}
|
|
function! s:source.hooks.on_close(args, context) abort "{{{
|
|
if has_key(a:context, 'source__proc')
|
|
call a:context.source__proc.kill()
|
|
endif
|
|
endfunction "}}}
|
|
function! s:source.hooks.on_post_filter(args, context) abort "{{{
|
|
for candidate in a:context.candidates
|
|
let candidate.kind = ['file', 'jump_list']
|
|
let candidate.action__col_pattern = a:context.source__input
|
|
let candidate.is_multiline = 1
|
|
let candidate.action__line = candidate.source__info[1]
|
|
let candidate.action__text = candidate.source__info[2]
|
|
endfor
|
|
endfunction"}}}
|
|
|
|
function! s:source.gather_candidates(args, context) abort "{{{
|
|
let command = get(a:context, 'custom_grep_command',
|
|
\ g:unite_source_grep_command)
|
|
let default_opts = get(a:context, 'custom_grep_default_opts',
|
|
\ g:unite_source_grep_default_opts)
|
|
let recursive_opt = get(a:context, 'custom_grep_recursive_opt',
|
|
\ g:unite_source_grep_recursive_opt)
|
|
|
|
if !executable(command)
|
|
call unite#print_source_message(printf(
|
|
\ 'command "%s" is not executable.', command), s:source.name)
|
|
let a:context.is_async = 0
|
|
return []
|
|
endif
|
|
|
|
if !unite#util#has_vimproc()
|
|
call unite#print_source_message(
|
|
\ 'vimproc plugin is not installed.', self.name)
|
|
let a:context.is_async = 0
|
|
return []
|
|
endif
|
|
|
|
if empty(a:context.source__targets)
|
|
\ || a:context.source__input == ''
|
|
call unite#print_source_message('Canceled.', s:source.name)
|
|
let a:context.is_async = 0
|
|
return []
|
|
endif
|
|
|
|
if a:context.is_redraw
|
|
let a:context.is_async = 1
|
|
endif
|
|
|
|
let cmdline = printf('"%s" %s %s %s %s %s %s',
|
|
\ unite#util#substitute_path_separator(command),
|
|
\ default_opts,
|
|
\ recursive_opt,
|
|
\ a:context.source__extra_opts,
|
|
\ g:unite_source_grep_separator,
|
|
\ string(a:context.source__input),
|
|
\ unite#helper#join_targets(a:context.source__targets)
|
|
\)
|
|
|
|
call unite#add_source_message('Command-line: ' . cmdline, s:source.name)
|
|
|
|
let save_term = $TERM
|
|
try
|
|
" Disable colors.
|
|
let $TERM = 'dumb'
|
|
|
|
let a:context.source__proc = vimproc#plineopen3(
|
|
\ vimproc#util#iconv(cmdline, &encoding,
|
|
\ g:unite_source_grep_encoding),
|
|
\ unite#helper#is_pty(command))
|
|
finally
|
|
let $TERM = save_term
|
|
endtry
|
|
|
|
return self.async_gather_candidates(a:args, a:context)
|
|
endfunction "}}}
|
|
|
|
function! s:source.async_gather_candidates(args, context) abort "{{{
|
|
if !has_key(a:context, 'source__proc')
|
|
let a:context.is_async = 0
|
|
return []
|
|
endif
|
|
|
|
let stderr = a:context.source__proc.stderr
|
|
if !stderr.eof
|
|
" Print error.
|
|
let errors = filter(unite#util#read_lines(stderr, 200),
|
|
\ "v:val !~ '^\\s*$'")
|
|
if !empty(errors)
|
|
call unite#print_source_error(errors, s:source.name)
|
|
endif
|
|
endif
|
|
|
|
let stdout = a:context.source__proc.stdout
|
|
if stdout.eof
|
|
" Disable async.
|
|
let a:context.is_async = 0
|
|
call a:context.source__proc.waitpid()
|
|
endif
|
|
|
|
let lines = map(unite#util#read_lines(stdout, 1000),
|
|
\ "unite#util#iconv(v:val, g:unite_source_grep_encoding, &encoding)")
|
|
|
|
let candidates = []
|
|
for line in lines
|
|
let ret = unite#sources#grep#parse(line)
|
|
if empty(ret)
|
|
call unite#print_source_error(
|
|
\ 'Invalid grep line: ' . line, s:source.name)
|
|
continue
|
|
endif
|
|
|
|
let [path, linenr, col, text] = ret
|
|
|
|
call add(candidates, {
|
|
\ 'word' : printf('%s: %s: %s', path,
|
|
\ linenr . (col != 0 ? ': '.col : ''), text),
|
|
\ 'action__path' :
|
|
\ unite#util#substitute_path_separator(
|
|
\ fnamemodify(path, ':p')),
|
|
\ 'action__col' : col,
|
|
\ 'source__info' : [path, linenr, text]
|
|
\ })
|
|
endfor
|
|
|
|
return candidates
|
|
endfunction "}}}
|
|
|
|
function! s:source.complete(args, context, arglead, cmdline, cursorpos) abort "{{{
|
|
return ['%', '#', '$buffers'] + unite#sources#file#complete_directory(
|
|
\ a:args, a:context, a:arglead, a:cmdline, a:cursorpos)
|
|
endfunction"}}}
|
|
|
|
function! unite#sources#grep#parse(line) abort "{{{
|
|
let ret = matchlist(a:line,
|
|
\ '^\(\%([a-zA-Z]:\)\?[^:]*\):\(\d\+\)\%(:\(\d\+\)\)\?:\(.*\)$')
|
|
if empty(ret) || ret[1] == '' || ret[4] == ''
|
|
return []
|
|
endif
|
|
|
|
if ret[1] =~ ':\d\+$'
|
|
" Use column pattern
|
|
let ret = matchlist(a:line, '^\(.*\):\(\d\+\):\(\d\+\):\(.*\)$')
|
|
endif
|
|
|
|
let path = ret[1]
|
|
let linenr = ret[2]
|
|
let col = ret[3]
|
|
let text = ret[4]
|
|
|
|
if linenr == ''
|
|
let linenr = '1'
|
|
endif
|
|
if col == ''
|
|
let col = '0'
|
|
endif
|
|
|
|
return [path, linenr, col, text]
|
|
endfunction"}}}
|
|
|
|
" vim: foldmethod=marker
|