Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added more options #49

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 118 additions & 30 deletions autoload/ag.vim
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,95 @@ if !exists("g:ag_mapping_message")
let g:ag_mapping_message=1
endif

function! ag#Ag(cmd, args)
" If no pattern is provided, search for the word under the cursor
if empty(a:args)
let l:grepargs = expand("<cword>")
if !exists("g:ag_scm_dirs")
let g:ag_scm_dirs = [ '.git', '.svn', '.hg' ]
endif

let s:ag_results_mapping = {
\ 'open_and_close' : 'e',
\ 'open' : 'o,<cr>',
\ 'preview_open' : 'go',
\ 'new_tab' : 't',
\ 'new_tab_silent' : 'T',
\ 'horizontal_split' : 'h',
\ 'horizontal_split_silent' : 'H',
\ 'vertical_split' : 'v',
\ 'vertical_split_silent' : 'gv',
\ 'quit' : 'q'
\ }

if exists("g:ag_results_mapping_replacements")
call extend(s:ag_results_mapping, g:ag_results_mapping_replacements, 'force')
endif

function! ag#FindSCMDir()
let filedir = expand('%:p:h')
for candidate in g:ag_scm_dirs
let dir = finddir(candidate, filedir . ';')
if dir == candidate
return '.'
elseif dir != ""
let dir = substitute(dir, '/' . candidate, '', '')
return dir
endif
endfor
return "~"
endfunction

function! ag#ApplyMapping(dictkey, mapping)
for key in split(s:ag_results_mapping[a:dictkey], ',')
exe "nnoremap <silent> <buffer> " . key . " " . a:mapping
endfor
endfunction

function! ag#AgForExtension(cmd, opts, regex, ...)
let exts = []
" map() is just too much of a pain in the ass
for e in a:000
call add(exts, substitute(e, '^\.\=\(.*\)', '\\.\1$', ''))
endfor
if empty(exts)
echoerr "No extensions provided."
else
let l:grepargs = a:args . join(a:000, ' ')
end
let extRegex = join(exts, '|')
let l:opts = a:opts
call ag#Ag(a:cmd, a:regex, extend(l:opts, {'specific_file_exts': extRegex}))
endif
endfunction

function! ag#AgFrontend(cmd, args)
call ag#Ag(a:cmd, a:args, {})
endfunction

function! ag#Ag(cmd, args, opts)
let l:ag_args = ""

let l:opts = a:opts

" Handle the types of files to search
if has_key(l:opts, 'current_file_ext')
let l:ag_args = l:ag_args . " -G'\\." . expand('%:e') . "$'"
elseif has_key(l:opts, 'specific_file_exts')
let l:ag_args = l:ag_args . " -G'" . l:opts['specific_file_exts'] . "'"
endif

" If no pattern is provided, search for the word under the cursor
let l:pat = expand('<cword>')
if !empty(a:args)
let l:pat = a:args
let l:pat = substitute(l:pat, '\%(\\<\|\\>\)', '\\b', 'g')
let l:pat = substitute(l:pat, '\\', '\\\\', 'g')
endif
let l:ag_args = l:ag_args . ' ' . l:pat

" If they want to search from the 'scm' directory
if has_key(l:opts, 'scmdir')
let l:ag_args = l:ag_args . ' ' . ag#FindSCMDir()
elseif has_key(l:opts, 'current_file_dir')
let l:ag_args = l:ag_args . ' ' . expand('%:p:h')
elseif has_key(l:opts, 'specific_dirs')
let l:ag_args = l:ag_args . ' ' . l:opts['specific_dirs']
endif

" Format, used to manage column jump
if a:cmd =~# '-g$'
Expand All @@ -45,7 +127,8 @@ function! ag#Ag(cmd, args)
try
let &grepprg=g:agprg
let &grepformat=g:agformat
silent execute a:cmd . " " . escape(l:grepargs, '|')
let toExecute = a:cmd . " " . escape(l:ag_args, "|")
silent execute toExecute
finally
let &grepprg=grepprg_bak
let &grepformat=grepformat_bak
Expand All @@ -69,26 +152,26 @@ function! ag#Ag(cmd, args)

" If highlighting is on, highlight the search keyword.
if exists("g:aghighlight")
let @/=a:args
let @/ = l:pat
set hlsearch
end

redraw!

if l:match_count
if l:apply_mappings
nnoremap <silent> <buffer> h <C-W><CR><C-w>K
nnoremap <silent> <buffer> H <C-W><CR><C-w>K<C-w>b
nnoremap <silent> <buffer> o <CR>
nnoremap <silent> <buffer> t <C-w><CR><C-w>T
nnoremap <silent> <buffer> T <C-w><CR><C-w>TgT<C-W><C-W>
nnoremap <silent> <buffer> v <C-w><CR><C-w>H<C-W>b<C-W>J<C-W>t

exe 'nnoremap <silent> <buffer> e <CR><C-w><C-w>:' . l:matches_window_prefix .'close<CR>'
exe 'nnoremap <silent> <buffer> go <CR>:' . l:matches_window_prefix . 'open<CR>'
exe 'nnoremap <silent> <buffer> q :' . l:matches_window_prefix . 'close<CR>'

exe 'nnoremap <silent> <buffer> gv :let b:height=winheight(0)<CR><C-w><CR><C-w>H:' . l:matches_window_prefix . 'open<CR><C-w>J:exe printf(":normal %d\<lt>c-w>_", b:height)<CR>'
call ag#ApplyMapping('horizontal_split', '<C-W><CR><C-w>K')
call ag#ApplyMapping('horizontal_split_silent', '<C-W><CR><C-w>K<C-w>b')
call ag#ApplyMapping('open', '<cr>')
call ag#ApplyMapping('new_tab', '<C-w><CR><C-w>T')
call ag#ApplyMapping('new_tab_silent', '<C-w><CR><C-w>TgT<C-W><C-W>')
call ag#ApplyMapping('vertical_split', '<C-w><CR><C-w>H<C-W>b<C-W>J<C-W>t')

call ag#ApplyMapping('open_and_close', '<CR><C-w><C-w>:' . l:matches_window_prefix . 'close<CR>')
call ag#ApplyMapping('preview_open', '<CR>:' . l:matches_window_prefix . 'open<CR>')
call ag#ApplyMapping('quit', ':' . l:matches_window_prefix . 'close<CR>')

call ag#ApplyMapping('vertical_split_silent', ':let b:height=winheight(0)<CR><C-w><CR><C-w>H:' . l:matches_window_prefix . 'open<CR><C-w>J:exe printf(":normal %d\<lt>c-w>_", b:height)<CR>')
" Interpretation:
" :let b:height=winheight(0)<CR> Get the height of the quickfix/location list window
" <CR><C-w> Open the current item in a new split
Expand All @@ -98,19 +181,25 @@ function! ag#Ag(cmd, args)
" :exe printf(":normal %d\<lt>c-w>_", b:height)<CR> Restore the quickfix/location list window's height from before we opened the match

if g:ag_mapping_message && l:apply_mappings
echom "ag.vim keys: q=quit <cr>/e/t/h/v=enter/edit/tab/split/vsplit go/T/H/gv=preview versions of same"
echom "ag.vim keys: " . s:ag_results_mapping['quit'] . "=quit " .
\ s:ag_results_mapping['open'] . '/' .
\ s:ag_results_mapping['open_and_close'] . '/' .
\ s:ag_results_mapping['new_tab'] . '/' .
\ s:ag_results_mapping['horizontal_split'] . '/' .
\ s:ag_results_mapping['vertical_split'] . "=enter/edit/tab/split/vsplit " .
\ s:ag_results_mapping['preview_open'] . '/' .
\ s:ag_results_mapping['horizontal_split_silent'] . '/' .
\ s:ag_results_mapping['vertical_split_silent'] . "=preview versions of same"
endif
endif
else
echom 'No matches for "'.a:args.'"'
echom 'No matches for "' . l:pat . '"'
endif
endfunction

function! ag#AgFromSearch(cmd, args)
let search = getreg('/')
" translate vim regular expression to perl regular expression.
let search = substitute(search,'\(\\<\|\\>\)','\\b','g')
call ag#Ag(a:cmd, '"' . search .'" '. a:args)
function! ag#AgFromSearch(cmd, opts)
let search = getreg('/')
call ag#Ag(a:cmd, search, a:opts)
endfunction

function! ag#GetDocLocations()
Expand All @@ -124,7 +213,6 @@ function! ag#GetDocLocations()
return dp
endfunction

function! ag#AgHelp(cmd,args)
let args = a:args.' '.ag#GetDocLocations()
call ag#Ag(a:cmd,args)
function! ag#AgHelp(cmd, args)
call ag#Ag(a:cmd, a:args, {'specific_dirs': ag#GetDocLocations()})
endfunction
88 changes: 88 additions & 0 deletions doc/ag.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,29 @@ shows the results in a split window.
Just like |:AgHelp| but instead of the |quickfix| list, matches are placed
in the current |location-list|.

:AgForCurrentFileDir [options] {pattern} *:AgForCurrentFileDir*

Uses the 'current_file_dir' option to ensure that we limit the search to
the directory of the current buffer's file

:AgForProjectRoot [options] {pattern} *:AgForProjectRoot*

The notion of a "project" is the directory subtree that starts at the root
of a source control managed directory. This is currently defined with
'g:ag_scm_dirs' variable.

:AgForExtension [options] {pattern} *:AgForExtension*

This command exists to let you specify a number of specific file extensions.
It implies the "scmdir" option so if you don't want that you'll have to
create a new command on your own (or override this one). Call it like
this: >

AgForExtension 'search for me' .js .java .txt
<
This will search for 'search for me' in {js}, {java} and {txt} files. The
leading "." on all of the extensions is optional.

Files containing the search term will be listed in the split window, along
with the line number of the occurrence, once for each occurrence. <Enter> on
a line in this window will open the file, and place the cursor on the matching
Expand Down Expand Up @@ -113,6 +136,45 @@ the mappings are not applied (see |g:ag_apply_qmappings| and
|g:ag_apply_lmappings| for more info. Default 1. Example: >
let g:ag_mapping_message=0
<
*g:ag_scm_dirs*
This is a list containing the directories that should be treated as source
control management directories. It's what allows this plugin to limit the
searches to subtrees of entire source directories.

==============================================================================
THE AG FUNCTION *ag-function*

The ag#Ag() function has some special configuration options that you might be
interested in. The permutations are annoying so pre-canning all of those
permutations hasn't been done. The function looks like >

ag#Ag(command, arguments, options)
<
The first two should always look something like: >

ag#Ag('grep<bang>', <a-args>, ...)
<
But the "options" argument is a dictionary. You can put the following into
the dictionary:
>
'current_file_ext': 1
<
Limits the search to the current buffer's file's extension (e.g. ".vim")
>
'current_file_dir': 1
<
Limits the search to the current buffer's file's directory.
>
'scmdir': 1
<
Limits the search to the "project" root subtree. This will search up the
directory tree for the first of the elements in the g:ag_scm_dirs list and
use that containing directoy as the directory argument to ag.
>
'specific_dirs': 'directory1 directory2 and so forth'
<
Limits the search to the specific directories given in this string


==============================================================================
MAPPINGS *ag-mappings*
Expand All @@ -139,4 +201,30 @@ gv open in vertical split silently.

q close the quickfix window.

*g:ag_results_mapping_replacements*
You can customize all of the mappings using the
g:ag_results_mapping_replacements dictionary. The default values for the
dictionary are: >

{
'open_and_close': 'e'
'open': 'o,<cr>'
'preview_open': 'go'
'new_tab': 't'
'new_tab_silent': 'T'
'horizontal_split': 'h'
'horizontal_split_silent': 'H'
'vertical_split': 'v'
'vertical_split_silent': 'gv'
'quit': 'q'
}
<
Personally, I prefer that <cr> closes the quickfix window, so I've customized
these as: >

let g:ag_results_mapping_replacements = {
\ 'open_and_close': '<cr>',
\ 'open': 'o',
\ }
<
vim:tw=78:fo=tcq2:ft=help:norl:
13 changes: 8 additions & 5 deletions plugin/ag.vim
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
" NOTE: You must, of course, install ag / the_silver_searcher
command! -bang -nargs=* -complete=file Ag call ag#Ag('grep<bang>',<q-args>)
command! -bang -nargs=* -complete=file AgAdd call ag#Ag('grepadd<bang>', <q-args>)
command! -bang -nargs=* -complete=file Ag call ag#Ag('grep<bang>',<q-args>, {})
command! -bang -nargs=* -complete=file AgAdd call ag#Ag('grepadd<bang>', <q-args>, {})
command! -bang -nargs=* -complete=file AgFromSearch call ag#AgFromSearch('grep<bang>', <q-args>)
command! -bang -nargs=* -complete=file LAg call ag#Ag('lgrep<bang>', <q-args>)
command! -bang -nargs=* -complete=file LAgAdd call ag#Ag('lgrepadd<bang>', <q-args>)
command! -bang -nargs=* -complete=file AgFile call ag#Ag('grep<bang> -g', <q-args>)
command! -bang -nargs=* -complete=file LAg call ag#Ag('lgrep<bang>', <q-args>, {})
command! -bang -nargs=* -complete=file LAgAdd call ag#Ag('lgrepadd<bang>', <q-args>, {})
command! -bang -nargs=* -complete=file AgFile call ag#Ag('grep<bang> -g', <q-args>, {})
command! -bang -nargs=* -complete=help AgHelp call ag#AgHelp('grep<bang>',<q-args>)
command! -bang -nargs=* -complete=help LAgHelp call ag#AgHelp('lgrep<bang>',<q-args>)
command! -bang -nargs=* -complete=file AgForCurrentFileDir call ag#Ag('grep<bang>', <q-args>, {'current_file_dir': 1})
command! -bang -nargs=* -complete=file AgForProjectRoot call ag#Ag('grep<bang>', <q-args>, {'current_file_ext': 1, 'scmdir': 1})
command! -bang -nargs=+ -complete=file AgForExtension call ag#AgForExtension('grep<bang>', {'scmdir': 1}, <f-args>)