"============================================================================= " FILE: grep.vim " AUTHOR: Shougo Matsushita " Tomohiro Nishimura " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= " 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') "}}} function! unite#sources#grep#define() abort "{{{ return s:source endfunction "}}} let s:source = { \ 'name': 'grep', \ 'max_candidates': 100, \ '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 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', \ unite#util#substitute_path_separator(command), \ default_opts, \ recursive_opt, \ a:context.source__extra_opts, \ 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 "{{{ let default_opts = get(a:context, 'custom_grep_default_opts', \ g:unite_source_grep_default_opts) 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)") if default_opts =~ '^-[^-]*l' \ || a:context.source__extra_opts =~ '^-[^-]*l' let lines = map(filter(lines, 'v:val != ""'), \ '[v:val, [v:val[2:], 0]]') else let lines = map(filter(lines, 'v:val =~ "^.\\+:.\\+$"'), \ '[v:val, split(v:val[2:], ":", 1)]') endif let candidates = [] for [line, fields] in lines let col = 0 if len(fields) <= 1 || fields[1] !~ '^\d\+$' let path = a:context.source__targets[0] if len(fields) <= 1 let linenr = line[:1][0] let text = fields[0] else let linenr = line[:1] . fields[0] let text = join(fields[1:], ':') endif else let path = line[:1] . fields[0] let linenr = fields[1] let text = join(fields[2:], ':') if text =~ '^\d\+:' let col = matchstr(text, '^\d\+') let text = text[len(col)+1 :] endif endif if path ==# '.' call unite#print_source_error( \ 'Your grep configuration is wrong.' \ . ' Please check ":help unite-source-grep" example.', \ s:source.name) break endif 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"}}} " vim: foldmethod=marker