├── plugin └── ag.vim ├── README.md └── autoload └── ctrlp └── ag.vim /plugin/ag.vim: -------------------------------------------------------------------------------- 1 | command! CtrlPag call ctrlp#ag#exec('n') 2 | command! CtrlPagPrevious call ctrlp#ag#exec('p') 3 | command! -range CtrlPagVisual ,call ctrlp#ag#exec('v') 4 | command! -nargs=1 CtrlPagLocate call ctrlp#ag#exec() 5 | 6 | if exists('g:ctrlp_ag_filter') 7 | let g:ctrlp_ag_filter .= ' ' 8 | else 9 | if !exists('g:ctrlp_ag_timeout') 10 | let g:ctrlp_ag_timeout = 10 11 | endif 12 | if executable('timeout') 13 | let g:ctrlp_ag_filter = 'timeout ' . g:ctrlp_ag_timeout . ' ' 14 | elseif executable('gtimeout') 15 | let g:ctrlp_ag_filter = 'gtimeout ' . g:ctrlp_ag_timeout . ' ' 16 | else 17 | let g:ctrlp_ag_filter = '' 18 | endif 19 | endif 20 | 21 | if executable('ag') 22 | let prg = &grepprg 23 | set grepprg& 24 | if prg ==# &grepprg 25 | set grepformat=%f:%l:%c:%m 26 | let &grepprg = g:ctrlp_ag_filter . 'ag --vimgrep --hidden $*' 27 | else 28 | let &grepprg = prg 29 | endif 30 | 31 | if !exists('g:ctrlp_user_command') 32 | let g:ctrlp_user_command = g:ctrlp_ag_filter . 'ag %s --nocolor --nogroup --hidden -g ""' 33 | endif 34 | endif 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CtrlP ag 2 | 3 | [CtrlP][1] extension for global searching source code with ag. 4 | Modified from [vim-ctrlp-tjump][2], another CtrlP extension that is strongly recommended. 5 | 6 | Automatically configures `:grep` and CtrlP to use ag unless `grepprg` or `g:ctrlp_user_command` 7 | have been user-defined. 8 | 9 | ## Installation 10 | 11 | 1. Fire any plugin manager like Vundle 12 | 13 | ``` 14 | Plugin 'lokikl/vim-ctrlp-ag' 15 | ``` 16 | 17 | 2. Create mapping 18 | 19 | ``` 20 | nnoremap :CtrlPag 21 | vnoremap :CtrlPagVisual 22 | nnoremap ca :CtrlPagLocate 23 | nnoremap cp :CtrlPagPrevious 24 | let g:ctrlp_ag_ignores = '--ignore .git 25 | \ --ignore "deps/*" 26 | \ --ignore "_build/*" 27 | \ --ignore "node_modules/*"' 28 | " By default ag will search from PWD 29 | " But you may enable one of below line to use an arbitrary directory or, 30 | " Using the magic word 'current-file-dir' to use current file base directory 31 | " let g:ctrlp_ag_search_base = 'current-file-dir' 32 | " let g:ctrlp_ag_search_base = 'app/controllers' " both relative and absolute path supported 33 | ``` 34 | 35 | ## Usage 36 | 37 | - Press `c-f` on the word you want to search (works in both normal/visual mode) 38 | - Press `ca`, a prompt opened to ask you what to search 39 | - Press `cp`, to redo the last ag search in CtrlP 40 | 41 | ## Configuration 42 | 43 | - Set the variable `g:ctrlp_ag_filter` to a command that executes its arguments as a sub-command, 44 | which in turn allows filtering the results. (Default: `'timeout 10'` or `'gtimeout 10'` or 45 | undefined, depending on the programs you've installed) 46 | - Set the variable `g:ctrlp_ag_timeout` to the number of seconds that the timeout filter should wait 47 | for ag to complete. (Default: `10`) Don't touch `g:ctrlp_ag_filter` if you want to use this 48 | filter. 49 | - Set the variable `g:ctrlp_ag_search_base` to change search base from PWD to current file directory or an arbitrary directory. 50 | Please see the Create Mapping section for example. 51 | 52 | [1]: https://github.com/kien/ctrlp.vim 53 | [2]: https://github.com/ivalkeen/vim-ctrlp-tjump 54 | -------------------------------------------------------------------------------- /autoload/ctrlp/ag.vim: -------------------------------------------------------------------------------- 1 | if (exists('g:loaded_ctrlp_ag') && g:loaded_ctrlp_ag) 2 | \ || v:version < 700 || &cp 3 | finish 4 | endif 5 | let g:loaded_ctrlp_ag = 1 6 | 7 | " 8 | " configuration options 9 | 10 | call add(g:ctrlp_ext_vars, { 11 | \ 'init': 'ctrlp#ag#init()', 12 | \ 'accept': 'ctrlp#ag#accept', 13 | \ 'lname': 'ag', 14 | \ 'sname': 'ag', 15 | \ 'type': 'line', 16 | \ 'enter': 'ctrlp#ag#enter()', 17 | \ 'exit': 'ctrlp#ag#exit()', 18 | \ 'opts': 'ctrlp#ag#opts()', 19 | \ 'sort': 0, 20 | \ 'specinput': 0, 21 | \ }) 22 | 23 | function! ctrlp#ag#exec(mode) 24 | let s:ag_opt_for_sensitivity = "-s" 25 | if a:mode == 'p' 26 | let s:word = s:word 27 | elseif a:mode == 'v' 28 | let newword = s:get_visual_selection() 29 | if exists('s:word') && s:word == newword 30 | echoerr 'Please use CtrlPagPrevious instead to build your muscle memory :)' 31 | return 32 | else 33 | let s:word = newword 34 | endif 35 | elseif a:mode == 'n' 36 | if (&filetype == 'ruby' || &filetype == 'eruby') && exists("*RubyCursorIdentifier") 37 | let s:word = RubyCursorIdentifier() 38 | else 39 | let s:word = expand('') 40 | endif 41 | else 42 | let s:ag_opt_for_sensitivity = "-S" 43 | let newword = a:mode 44 | if exists('s:word') && s:word == newword 45 | echoerr 'Please use CtrlPagPrevious instead to build your muscle memory :)' 46 | return 47 | else 48 | let s:word = newword 49 | endif 50 | endif 51 | 52 | if (!exists('g:ctrlp_ag_ignores')) 53 | let g:ctrlp_ag_ignores = "--ignore tags" 54 | endif 55 | 56 | if exists('g:ctrlp_ag_search_base') 57 | if g:ctrlp_ag_search_base == 'current-file-dir' 58 | let dir = expand('%:p:h') 59 | else 60 | let dir = g:ctrlp_ag_search_base 61 | endif 62 | else 63 | let dir = '' 64 | endif 65 | 66 | let s:ag_results = split(system(g:ctrlp_ag_filter . 67 | \ "ag -Q " . s:ag_opt_for_sensitivity . 68 | \ " --column " . g:ctrlp_ag_ignores . 69 | \ " '" . s:word . "' " . dir . ""), "\n") 70 | 71 | " remove current file/line from results 72 | let bname = bufname('%') . ':' . line('.') 73 | call filter(s:ag_results, 'v:val !~ "^' . bname . '"') 74 | 75 | if len(s:ag_results) == 0 76 | echo("No results found for: ".s:word) 77 | else 78 | call ctrlp#init(ctrlp#ag#id()) 79 | endif 80 | endfunction 81 | 82 | " Provide a list of strings to search in 83 | " 84 | " Return: a Vim's List 85 | " 86 | function! ctrlp#ag#init() 87 | " dim the content part to make it look more tidy 88 | " eg. 89 | " app/data/mgmt.rb:31: def abc 90 | if !ctrlp#nosy() 91 | cal ctrlp#hicheck('CtrlPTabExtra', 'Comment') 92 | syntax match CtrlPTabExtra `:.*$` 93 | en 94 | return s:ag_results 95 | endfunction 96 | 97 | " The action to perform on the selected string 98 | " 99 | " Arguments: 100 | " a:mode the mode that has been chosen by pressing or 101 | " the values are 'e', 'v', 't' and 'h', respectively 102 | " a:str the selected string 103 | " 104 | function! ctrlp#ag#accept(mode, str) 105 | call ctrlp#exit() 106 | call s:open_file(a:mode, a:str) 107 | endfunction 108 | 109 | " (optional) Do something before enterting ctrlp 110 | function! ctrlp#ag#enter() 111 | endfunction 112 | 113 | " (optional) Do something after exiting ctrlp 114 | function! ctrlp#ag#exit() 115 | endfunction 116 | 117 | " (optional) Set or check for user options specific to this extension 118 | function! ctrlp#ag#opts() 119 | endfunction 120 | 121 | " Give the extension an ID 122 | let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars) 123 | 124 | " Allow it to be called later 125 | function! ctrlp#ag#id() 126 | return s:id 127 | endfunction 128 | 129 | function! s:open_file(mode, str) 130 | let [path, line, column; rest] = split(a:str, ':') 131 | call ctrlp#acceptfile(a:mode, path) 132 | call cursor(line, column) 133 | endfunction 134 | 135 | function! s:get_visual_selection() 136 | let [lnum1, col1] = getpos("'<")[1:2] 137 | let [lnum2, col2] = getpos("'>")[1:2] 138 | let lines = getline(lnum1, lnum2) 139 | let lines[-1] = lines[-1][: col2 - (&selection == 'inclusive' ? 1 : 2)] 140 | let lines[0] = lines[0][col1 - 1:] 141 | return join(lines, "\n") 142 | endfunction 143 | --------------------------------------------------------------------------------