add scala vim files
[cmccabe-etc] / .vim / plugin / grep.vim
1 " File: grep.vim
2 " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
3 " Version: 1.9
4 " Last Modified: September 10, 2007
5
6 " Overview
7 " --------
8 " The grep plugin integrates the grep, fgrep, egrep, and agrep tools with
9 " Vim and allows you to search for a pattern in one or more files and jump
10 " to them.
11 "
12 " To use this plugin, you need the grep, fgrep, egrep, agrep, find and
13 " xargs utilities. These tools are present in most of the Unix installations.
14 " For MS-Windows systems, you can download the GNU grep and find utilities
15 " from the following sites:
16 "
17 "    http://gnuwin32.sourceforge.net/packages/grep.htm
18 "    http://gnuwin32.sourceforge.net/packages/findutils.htm
19 "
20 " Installation
21 " ------------
22 " 1. Copy the grep.vim file to the $HOME/.vim/plugin or $HOME/vimfiles/plugin
23 "    or $VIM/vimfiles/plugin directory. 
24 "    Refer to the following Vim help topics for more information about Vim
25 "    plugins:
26 "       :help add-plugin
27 "       :help add-global-plugin
28 "       :help runtimepath
29 " 2. If the grep executables are not already present in one of the directories
30 "    in the PATH environment variable, then set the Grep_Path and other _Path
31 "    variables to point to the location of the grep utilites in the .vimrc
32 "    file.
33 " 3. Restart Vim.
34 " 4. You can now use the ":Grep" and other commands to search for patterns in
35 "    files.
36 "
37 " Usage
38 " -----
39 " The grep.vim plugin introduces the following Vim commands:
40 "
41 " :Grep          - Search for the specified pattern in the specified files
42 " :GrepAdd       - Same as ":Grep" but adds the results to the current results
43 " :Rgrep         - Run recursive grep
44 " :RgrepAdd      - Same as ":Rgrep" but adds the results to the current results
45 " :GrepBuffer    - Search for a pattern on all open buffers
46 " :GrepBufferAdd - Same as ":GrepBuffer" but adds the results to the current
47 "                  results
48 " :Bgrep         - Same as :GrepBuffer
49 " :BgrepAdd      - Same as :GrepBufferAdd
50 " :GrepArgs      - Search for a pattern on all the Vim argument 
51 "                  filenames (:args)
52 " :GrepArgsAdd   - Same as ":GrepArgs" but adds the results to the current
53 "                  results
54 " :Fgrep         - Run fgrep
55 " :FgrepAdd      - Same as ":Fgrep" but adds the results to the current
56 "                  results
57 " :Rfgrep        - Run recursive fgrep
58 " :RfgrepAdd     - Same as ":Rfgrep" but adds the results to the current
59 "                  results
60 " :Egrep         - Run egrep
61 " :EgrepAdd      - Same as ":Egrep" but adds the results to the current
62 "                  results
63 " :Regrep        - Run recursive egrep
64 " :RegrepAdd     - Same as ":Regrep" but adds the results to the current
65 "                  results
66 " :Agrep         - Run agrep
67 " :AgrepAdd      - Same as ":Agrep" but adds the results to the current
68 "                  results
69 " :Ragrep        - Run recursive agrep
70 " :RagrepAdd     - Same as ":Ragrep" but adds the results to the current
71 "                  results
72 "
73 " The above commands can be invoked like this:
74 "
75 "    :Grep   [<grep_options>] [<search_pattern> [<file_name(s)>]]
76 "    :Rgrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
77 "    :Fgrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
78 "    :Rfgrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
79 "    :Egrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
80 "    :Regrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
81 "    :Agrep  [<grep_options>] [<search_pattern> [<file_name(s)>]]
82 "    :Ragrep [<grep_options>] [<search_pattern> [<file_name(s)>]]
83 "
84 "    :GrepAdd   [<grep_options>] [<search_pattern> [<file_name(s)>]]
85 "    :RgrepAdd  [<grep_options>] [<search_pattern> [<file_name(s)>]]
86 "    :FgrepAdd  [<grep_options>] [<search_pattern> [<file_name(s)>]]
87 "    :RfgrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]]
88 "    :EgrepAdd  [<grep_options>] [<search_pattern> [<file_name(s)>]]
89 "    :RegrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]]
90 "    :AgrepAdd  [<grep_options>] [<search_pattern> [<file_name(s)>]]
91 "    :RagrepAdd [<grep_options>] [<search_pattern> [<file_name(s)>]]
92 "
93 "    :GrepBuffer [<grep_options>] [<search_pattern>]
94 "    :Bgrep [<grep_options>] [<search_pattern>]
95 "    :GrepArgs [<grep_options>] [<search_pattern>]
96 "
97 "    :GrepBufferAdd [<grep_options>] [<search_pattern>]
98 "    :BgrepAdd [<grep_options>] [<search_pattern>]
99 "    :GrepArgsAdd [<grep_options>] [<search_pattern>]
100 "
101 " In the above commands, all the arguments are optional.
102 "
103 " You can specify grep options like -i (ignore case) or -w (search for a word)
104 " to the above commands.  If the <grep_options> are not specified, then the
105 " default grep options specified by the variable Grep_Default_Options is 
106 " used.
107 "
108 " You can specify the grep pattern to search as an argument to the above
109 " commands.  If the <search_pattern> is not specified, then you will be
110 " prompted to enter a search pattern. By default, the keyword under the cursor
111 " is displayed for the search pattern prompt. You can accept the default or
112 " modify it.
113 "
114 " The search pattern is automatically enclosed by the character specified in
115 " the Grep_Shell_Quote_Char variable. You should not enclose the search
116 " pattern with a shell escape character.
117 "
118 " If you want to specify a search pattern with space characters or a
119 " multi-word pattern, then you should use the Grep command pattern input
120 " prompt to supply the pattern.
121 "
122 " You can specify one or more file names (or file patterns) to the above
123 " commands.  If the <file_names> are not specified, then you will be prompted
124 " to enter file names.  By default, the pattern specified by the
125 " Grep_Default_Filelist variable is used. To specify the file name(s) as an
126 " argument to the above commands, you have to specify the search pattern also.
127 "
128 " When you enter only the command name, you will be prompted to enter the
129 " search pattern and the files in which to search for the pattern. By default,
130 " the keyword under the cursor is displayed for the search pattern prompt.
131 " Depending on the command, you may prompted for additional parameters like
132 " the directories to search for the pattern.
133 "
134 " You can retrieve previously entered values for the Grep prompts using the up
135 " and down arrow keys. You can cancel the command by pressing the escape key.
136 " You can use CTRL-U to erase the default shown for the prompt and CTRL-W to
137 " erase the previous word in the prompt. For more information about editing
138 " the prompt, read ':help cmdline-editing' Vim help topic.
139 "
140 " After invoking any of the grep commands, you can cancel the command, when
141 " you are prompted for a search pattern or file names or a directory by
142 " pressing the <Esc> key. You cannot cancel (or kill) the
143 " grep/fgrep/egrep/agrep commands after the external command is invoked.
144 "
145 " The GrepAdd, RgrepAdd and other *Add commands append the search output to
146 " the current search output. This is useful if you want to see the search
147 " results for multiple patterns at the same time. These commands are available
148 " only in Vim version 7.0 and above.
149 "
150 " You can map a key to invoke any of the above commands. For example, the
151 " following map invokes the :Grep command to search for the keyword under the
152 " cursor:
153 "
154 "       nnoremap <silent> <F3> :Grep<CR>
155 "
156 " The output of the grep command will be listed in the Vim quickfix window.
157 " 1. You can select a line in the quickfix window and press <Enter> or double
158 "    click on a match to jump to that line.
159 " 2. You can use the ":cnext" and ":cprev" commands to the jump to the next or
160 "    previous output line.
161 " 3. You can use the ":colder" and ":cnewer" commands to go between multiple
162 "    grep quickfix output windows.
163 " 4. The quickfix window need not be opened always to use the grep output.
164 "    You can close the quickfix window and use the quickfix commands to jump
165 "    to the grep matches.  Use the ":copen" command to open the quickfix
166 "    window again.
167 "
168 " For more information about other quickfix commands read ":help quickfix"
169
170 " When using GUI Vim, the Tools->Search menu item with a few sub-menu items is
171 " created for few variations of the search command.
172 "
173 " Configuration
174 " -------------
175 " By changing the following variables you can configure the behavior of this
176 " plugin. Set the following variables in your .vimrc file using the 'let'
177 " command.
178 "
179 " The 'Grep_Path' variable is used to locate the grep utility. By default,
180 " this is set to grep. You can change this using the let command:
181 "
182 "       :let Grep_Path = 'd:\tools\grep.exe'
183 "
184 " The 'Fgrep_Path' variable is used to locate the fgrep utility. By default,
185 " this is set to fgrep. You can change this using the let command:
186 "
187 "       :let Fgrep_Path = 'd:\tools\fgrep.exe'
188 "
189 " The 'Egrep_Path' variable is used to locate the egrep utility. By default,
190 " this is set to egrep. You can change this using the let command:
191 "
192 "       :let Egrep_Path = 'd:\tools\egrep.exe'
193 "
194 " The 'Agrep_Path' variable is used to locate the agrep utility. By default,
195 " this is set to agrep. You can change this using the let command:
196 "
197 "       :let Agrep_Path = 'd:\tools\agrep.exe'
198 "
199 " The 'Grep_Find_Path' variable is used to locate the find utility. By
200 " default, this is set to d:\tools\find.exe. You can change this using the let
201 " command:
202 "
203 "       :let Grep_Find_Path = 'd:\tools\find.exe'
204 "
205 " The 'Grep_Xargs_Path' variable is used to locate the xargs utility. By
206 " default, this is set to xargs. You can change this using the let
207 " command:
208 "
209 "       :let Grep_Xargs_Path = 'd:\tools\xargs.exe'
210 "
211 " When running any one of the Grep commands, you will be prompted for the
212 " files in which to search for the pattern. The 'Grep_Default_Filelist'
213 " variable is used to specify to default for this prompt. By default, this
214 " variable is set to '*'. You can specify multiple matching patterns separated
215 " by spaces. You can change this settings using the let command:
216 "
217 "       :let Grep_Default_Filelist = '*.[chS]'
218 "       :let Grep_Default_Filelist = '*.c *.cpp *.asm'
219 "
220 " The 'Grep_Default_Options' is used to pass default command line options to
221 " the grep/fgrep/egrep/agrep utilities. By default, this is set to an empty
222 " string. You can change this using the let command:
223 "
224 "       :let Grep_Default_Options = '-i'
225 "
226 " The 'Grep_Skip_Dirs' variable specifies the list of directories to skip
227 " while doing recursive searches. By default, this is set to 'RCS CVS SCCS'.
228 " You can change this using the let command:
229 "
230 "       :let Grep_Skip_Dirs = 'dir1 dir2 dir3'
231 "
232 " The 'Grep_Skip_Files' variable specifies the list of files to skip while
233 " doing recursive searches. By default, this is set to '*~ *,v s.*'. You can
234 " change this using the let command:
235 "
236 "       :let Grep_Skip_Files = '*.bak *~'
237 "
238 " By default, when you invoke the Grep commands the quickfix window will be
239 " opened with the grep output.  You can disable opening the quickfix window,
240 " by setting the 'Grep_OpenQuickfixWindow' variable  to zero:
241 "
242 "       :let Grep_OpenQuickfixWindow = 0
243 "
244 " You can manually open the quickfix window using the :cwindow command.
245 "
246 " By default, for recursive searches, the 'find' and 'xargs' utilities are
247 " used.  If you don't have the 'xargs' utility or don't want to use the
248 " 'xargs' utility, " then you can set the 'Grep_Find_Use_Xargs' variable to
249 " zero. If this is set to zero, then only the 'find' utility is used for
250 " recursive searches:
251 "
252 "       :let Grep_Find_Use_Xargs = 0
253
254 " To handle file names with space characters in them, the xargs utility
255 " is invoked with the '--null' argument. If the xargs utility in your system
256 " doesn't accept the '--null' argument, then you can change the
257 " Grep_Xargs_Options variable. For example, to use the '--print0' xargs
258 " argument, you can use the following command:
259 "
260 "       :let Grep_Xargs_Options = '--print0'
261 "
262 " The Grep_Cygwin_Find variable should be set to 1, if you are using the find
263 " utility from the cygwin package. This setting is used to handle the
264 " difference between the backslash and forward slash path separators.
265 "
266 "       :let Grep_Cygwin_Find = 1
267
268 " The 'Grep_Null_Device' variable specifies the name of the null device to
269 " pass to the grep commands. This is needed to force the grep commands to
270 " print the name of the file in which a match is found, if only one filename
271 " is specified. For Unix systems, this is set to /dev/null and for MS-Windows
272 " systems, this is set to NUL. You can modify this by using the let command:
273 "
274 "       :let Grep_Null_Device = '/dev/null'
275 "
276 " The 'Grep_Shell_Quote_Char' variable specifies the quote character to use
277 " for protecting patterns from being interpreted by the shell. For Unix
278 " systems, this is set to "'" and for MS-Window systems, this is set to an
279 " empty string.  You can change this using the let command:
280 "
281 "       :let Grep_Shell_Quote_Char = "'"
282 "
283 " The 'Grep_Shell_Escape_Char' variable specifies the escape character to use
284 " for protecting special characters from being interpreted by the shell.  For
285 " Unix systems, this is set to '\' and for MS-Window systems, this is set to
286 " an empty string.  You can change this using the let command:
287 "
288 "       :let Grep_Shell_Escape_Char = "'"
289 "
290 " --------------------- Do not modify after this line ---------------------
291 if exists("loaded_grep")
292     finish
293 endif
294 let loaded_grep = 1
295
296 " Line continuation used here
297 let s:cpo_save = &cpo
298 set cpo&vim
299
300 " Location of the grep utility
301 if !exists("Grep_Path")
302     let Grep_Path = 'grep'
303 endif
304
305 " Location of the fgrep utility
306 if !exists("Fgrep_Path")
307     let Fgrep_Path = 'fgrep'
308 endif
309
310 " Location of the egrep utility
311 if !exists("Egrep_Path")
312     let Egrep_Path = 'egrep'
313 endif
314
315 " Location of the agrep utility
316 if !exists("Agrep_Path")
317     let Agrep_Path = 'agrep'
318 endif
319
320 " Location of the find utility
321 if !exists("Grep_Find_Path")
322     let Grep_Find_Path = 'find'
323 endif
324
325 " Location of the xargs utility
326 if !exists("Grep_Xargs_Path")
327     let Grep_Xargs_Path = 'xargs'
328 endif
329
330 " Open the Grep output window.  Set this variable to zero, to not open
331 " the Grep output window by default.  You can open it manually by using
332 " the :cwindow command.
333 if !exists("Grep_OpenQuickfixWindow")
334     let Grep_OpenQuickfixWindow = 1
335 endif
336
337 " Default grep file list
338 if !exists("Grep_Default_Filelist")
339     let Grep_Default_Filelist = '*'
340 endif
341
342 " Default grep options
343 if !exists("Grep_Default_Options")
344     let Grep_Default_Options = ''
345 endif
346
347 " Use the 'xargs' utility in combination with the 'find' utility. Set this
348 " to zero to not use the xargs utility.
349 if !exists("Grep_Find_Use_Xargs")
350     let Grep_Find_Use_Xargs = 1
351 endif
352
353 " The command-line arguments to supply to the xargs utility
354 if !exists('Grep_Xargs_Options')
355     let Grep_Xargs_Options = '--null'
356 endif
357
358 " The find utility is from the cygwin package or some other find utility.
359 if !exists("Grep_Cygwin_Find")
360     let Grep_Cygwin_Find = 0
361 endif
362
363 " NULL device name to supply to grep.  We need this because, grep will not
364 " print the name of the file, if only one filename is supplied. We need the
365 " filename for Vim quickfix processing.
366 if !exists("Grep_Null_Device")
367     if has("win32") || has("win16") || has("win95")
368         let Grep_Null_Device = 'NUL'
369     else
370         let Grep_Null_Device = '/dev/null'
371     endif
372 endif
373
374 " Character to use to quote patterns and filenames before passing to grep.
375 if !exists("Grep_Shell_Quote_Char")
376     if has("win32") || has("win16") || has("win95")
377         let Grep_Shell_Quote_Char = ''
378     else
379         let Grep_Shell_Quote_Char = "'"
380     endif
381 endif
382
383 " Character to use to escape special characters before passing to grep.
384 if !exists("Grep_Shell_Escape_Char")
385     if has("win32") || has("win16") || has("win95")
386         let Grep_Shell_Escape_Char = ''
387     else
388         let Grep_Shell_Escape_Char = '\'
389     endif
390 endif
391
392 " The list of directories to skip while searching for a pattern. Set this
393 " variable to '', if you don't want to skip directories.
394 if !exists("Grep_Skip_Dirs")
395     let Grep_Skip_Dirs = 'RCS CVS SCCS'
396 endif
397
398 " The list of files to skip while searching for a pattern. Set this variable
399 " to '', if you don't want to skip any files.
400 if !exists("Grep_Skip_Files")
401     let Grep_Skip_Files = '*~ *,v s.*'
402 endif
403
404 " RunGrepCmd()
405 " Run the specified grep command using the supplied pattern
406 function! s:RunGrepCmd(cmd, pattern, action)
407     let cmd_output = system(a:cmd)
408
409     if cmd_output == ""
410         echohl WarningMsg | 
411         \ echomsg "Error: Pattern " . a:pattern . " not found" | 
412         \ echohl None
413         return
414     endif
415
416     let tmpfile = tempname()
417
418     let old_verbose = &verbose
419     set verbose&vim
420
421     exe "redir! > " . tmpfile
422     silent echon '[Search results for pattern: ' . a:pattern . "]\n"
423     silent echon cmd_output
424     redir END
425
426     let &verbose = old_verbose
427
428     let old_efm = &efm
429     set efm=%f:%\\s%#%l:%m
430
431     if v:version >= 700 && a:action == 'add'
432         execute "silent! caddfile " . tmpfile
433     else
434         if exists(":cgetfile")
435             execute "silent! cgetfile " . tmpfile
436         else
437             execute "silent! cfile " . tmpfile
438         endif
439     endif
440
441     let &efm = old_efm
442
443     " Open the grep output window
444     if g:Grep_OpenQuickfixWindow == 1
445         " Open the quickfix window below the current window
446         botright copen
447     endif
448
449     call delete(tmpfile)
450 endfunction
451
452 " RunGrepRecursive()
453 " Run specified grep command recursively
454 function! s:RunGrepRecursive(cmd_name, grep_cmd, action, ...)
455     if a:0 > 0 && (a:1 == "-?" || a:1 == "-h")
456         echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern> " .
457                         \ "[<file_name(s)>]]"
458         return
459     endif
460
461     let grep_opt    = ""
462     let pattern     = ""
463     let filepattern = ""
464
465     let argcnt = 1
466     while argcnt <= a:0
467         if a:{argcnt} =~ '^-'
468             let grep_opt = grep_opt . " " . a:{argcnt}
469         elseif pattern == ""
470             let pattern = g:Grep_Shell_Quote_Char . a:{argcnt} . 
471                             \ g:Grep_Shell_Quote_Char
472         else
473             let filepattern = filepattern . " " . a:{argcnt}
474         endif
475         let argcnt= argcnt + 1
476     endwhile
477     if grep_opt == ""
478         let grep_opt = g:Grep_Default_Options
479     endif
480
481     if a:grep_cmd != 'agrep'
482         " Don't display messages about non-existent files
483         " Agrep doesn't support the -s option
484         let grep_opt = grep_opt . " -s"
485     endif
486
487     if a:grep_cmd == 'grep'
488         let grep_path = g:Grep_Path
489         let grep_expr_option = '--'
490     elseif a:grep_cmd == 'fgrep'
491         let grep_path = g:Fgrep_Path
492         let grep_expr_option = '-e'
493     elseif a:grep_cmd == 'egrep'
494         let grep_path = g:Egrep_Path
495         let grep_expr_option = '-e'
496     elseif a:grep_cmd == 'agrep'
497         let grep_path = g:Agrep_Path
498         let grep_expr_option = ''
499     else
500         return
501     endif
502
503     " No argument supplied. Get the identifier and file list from user
504     if pattern == "" 
505         let pattern = input("Search for pattern: ", expand("<cword>"))
506         if pattern == ""
507             return
508         endif
509         let pattern = g:Grep_Shell_Quote_Char . pattern . 
510                         \ g:Grep_Shell_Quote_Char
511     endif
512
513     let cwd = getcwd()
514     if g:Grep_Cygwin_Find == 1
515         let cwd = substitute(cwd, "\\", "/", "g")
516     endif
517     if v:version >= 700
518         let startdir = input("Start searching from directory: ", cwd, "dir")
519     else
520         let startdir = input("Start searching from directory: ", cwd)
521     endif
522     if startdir == ""
523         return
524     endif
525
526     if filepattern == ""
527         let filepattern = input("Search in files matching pattern: ", 
528                                           \ g:Grep_Default_Filelist)
529         if filepattern == ""
530             return
531         endif
532     endif
533
534     let txt = filepattern . ' '
535     let find_file_pattern = ''
536     while txt != ''
537         let one_pattern = strpart(txt, 0, stridx(txt, ' '))
538         if find_file_pattern != ''
539             let find_file_pattern = find_file_pattern . ' -o'
540         endif
541         let find_file_pattern = find_file_pattern . ' -name ' .
542               \ g:Grep_Shell_Quote_Char . one_pattern . g:Grep_Shell_Quote_Char
543         let txt = strpart(txt, stridx(txt, ' ') + 1)
544     endwhile
545     let find_file_pattern = g:Grep_Shell_Escape_Char . '(' .
546                     \ find_file_pattern . ' ' . g:Grep_Shell_Escape_Char . ')'
547
548     let txt = g:Grep_Skip_Dirs
549     let find_prune = ''
550     if txt != ''
551         let txt = txt . ' '
552         while txt != ''
553             let one_dir = strpart(txt, 0, stridx(txt, ' '))
554             if find_prune != ''
555                 let find_prune = find_prune . ' -o'
556             endif
557             let find_prune = find_prune . ' -name ' . one_dir
558             let txt = strpart(txt, stridx(txt, ' ') + 1)
559         endwhile
560         let find_prune = '-type d ' . g:Grep_Shell_Escape_Char . '(' .
561                          \ find_prune
562         let find_prune = find_prune . ' ' . g:Grep_Shell_Escape_Char . ')'
563     endif
564
565     let txt = g:Grep_Skip_Files
566     let find_skip_files = '-type f'
567     if txt != ''
568         let txt = txt . ' '
569         while txt != ''
570             let one_file = strpart(txt, 0, stridx(txt, ' '))
571             let find_skip_files = find_skip_files . ' ! -name ' .
572                                   \ g:Grep_Shell_Quote_Char . one_file .
573                                   \ g:Grep_Shell_Quote_Char
574             let txt = strpart(txt, stridx(txt, ' ') + 1)
575         endwhile
576     endif
577
578     if g:Grep_Find_Use_Xargs == 1
579         let cmd = g:Grep_Find_Path . " " . startdir
580         let cmd = cmd . " " . find_prune . " -prune -o"
581         let cmd = cmd . " " . find_skip_files
582         let cmd = cmd . " " . find_file_pattern
583         let cmd = cmd . " -print0 | "
584         let cmd = cmd . g:Grep_Xargs_Path . ' ' . g:Grep_Xargs_Options
585         let cmd = cmd . ' ' . grep_path . " " . grep_opt . " -n "
586         let cmd = cmd . grep_expr_option . " " . pattern
587         let cmd = cmd . ' ' . g:Grep_Null_Device 
588     else
589         let cmd = g:Grep_Find_Path . " " . startdir
590         let cmd = cmd . " " . find_prune . " -prune -o"
591         let cmd = cmd . " " . find_skip_files
592         let cmd = cmd . " " . find_file_pattern
593         let cmd = cmd . " -exec " . grep_path . " " . grep_opt . " -n "
594         let cmd = cmd . grep_expr_option . " " . pattern
595         let cmd = cmd . " {} " . g:Grep_Null_Device . ' ' .
596                          \ g:Grep_Shell_Escape_Char . ';'
597     endif
598
599     call s:RunGrepCmd(cmd, pattern, a:action)
600 endfunction
601
602 " RunGrepSpecial()
603 " Search for a pattern in all the opened buffers or filenames in the
604 " argument list
605 function! s:RunGrepSpecial(cmd_name, which, action, ...)
606     if a:0 > 0 && (a:1 == "-?" || a:1 == "-h")
607         echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern>]"
608         return
609     endif
610
611     " Search in all the Vim buffers
612     if a:which == 'buffer'
613         " Get a list of all the buffer names
614         let last_bufno = bufnr("$")
615
616         let i = 1
617         let filenames = ""
618
619         while i <= last_bufno
620             if bufexists(i) && buflisted(i)
621                 let filenames = filenames . " " . bufname(i)
622             endif
623             let i = i + 1
624         endwhile
625
626         " No buffers
627         if filenames == ""
628             return
629         endif
630     elseif a:which == 'args'
631         " Search in all the filenames in the argument list
632         let arg_cnt = argc()
633
634         if arg_cnt == 0
635             echohl WarningMsg
636             echomsg "Error: Argument list is empty"
637             echohl None
638             return
639         endif
640
641         let i = 0
642         let filenames = ""
643
644         while i < arg_cnt
645             let filenames = filenames . " " . argv(i)
646             let i = i + 1
647         endwhile
648
649         " No arguments
650         if filenames == ""
651             echohl WarningMsg
652             echomsg "Error: Argument list is empty"
653             echohl None
654             return
655         endif
656     endif
657
658     let grep_opt = ""
659     let pattern = ""
660
661     " Get the list of optional grep command-line options (if present)
662     " supplied by the user. All the grep options will be preceded
663     " by a '-'
664     let argcnt= 1
665     while argcnt <= a:0 && a:{argcnt} =~ '^-'
666         let grep_opt = grep_opt . " " . a:{argcnt}
667         let argcnt = argcnt + 1
668     endwhile
669
670     " If the user didn't specify the option, then use the defaults
671     if grep_opt == ""
672         let grep_opt = g:Grep_Default_Options
673     endif
674
675     " Don't display messages about non-existent files
676     let grep_opt = grep_opt . " -s"
677
678     " The last argument specified by the user is the pattern
679     if argcnt == a:0
680         let pattern = a:{argcnt}
681     else
682         " No argument supplied. Get the identifier and file list from user
683         let pattern = input("Search for pattern: ", expand("<cword>"))
684         if pattern == ""
685             return
686         endif
687     endif
688
689     let pattern = g:Grep_Shell_Quote_Char . pattern . g:Grep_Shell_Quote_Char
690
691     " Add /dev/null to the list of filenames, so that grep print the
692     " filename and linenumber when grepping in a single file
693     let filenames = filenames . " " . g:Grep_Null_Device
694     let cmd = g:Grep_Path . " " . grep_opt . " -n -- "
695     let cmd = cmd . pattern . " " . filenames
696
697     call s:RunGrepCmd(cmd, pattern, a:action)
698 endfunction
699
700 " RunGrep()
701 " Run the specified grep command
702 function! s:RunGrep(cmd_name, grep_cmd, action, ...)
703     if a:0 > 0 && (a:1 == "-?" || a:1 == "-h")
704         echo 'Usage: ' . a:cmd_name . " [<grep_options>] [<search_pattern> " .
705                         \ "[<file_name(s)>]]"
706         return
707     endif
708
709     let grep_opt  = ""
710     let pattern   = ""
711     let filenames = ""
712
713     " Parse the arguments
714     " grep command-line flags are specified using the "-flag" format
715     " the next argument is assumed to be the pattern
716     " and the next arguments are assumed to be filenames or file patterns
717     let argcnt = 1
718     while argcnt <= a:0
719         if a:{argcnt} =~ '^-'
720             let grep_opt = grep_opt . " " . a:{argcnt}
721         elseif pattern == ""
722             let pattern = g:Grep_Shell_Quote_Char . a:{argcnt} .
723                             \ g:Grep_Shell_Quote_Char
724         else
725             let filenames= filenames . " " . a:{argcnt}
726         endif
727         let argcnt = argcnt + 1
728     endwhile
729
730     if grep_opt == ""
731         let grep_opt = g:Grep_Default_Options
732     endif
733
734     if a:grep_cmd != 'agrep'
735         " Don't display messages about non-existent files
736         " Agrep doesn't support the -s option
737         let grep_opt = grep_opt . " -s"
738     endif
739
740     if a:grep_cmd == 'grep'
741         let grep_path = g:Grep_Path
742         let grep_expr_option = '--'
743     elseif a:grep_cmd == 'fgrep'
744         let grep_path = g:Fgrep_Path
745         let grep_expr_option = '-e'
746     elseif a:grep_cmd == 'egrep'
747         let grep_path = g:Egrep_Path
748         let grep_expr_option = '-e'
749     elseif a:grep_cmd == 'agrep'
750         let grep_path = g:Agrep_Path
751         let grep_expr_option = ''
752     else
753         return
754     endif
755
756     " Get the identifier and file list from user
757     if pattern == "" 
758         let pattern = input("Search for pattern: ", expand("<cword>"))
759         if pattern == ""
760             return
761         endif
762         let pattern = g:Grep_Shell_Quote_Char . pattern .
763                         \ g:Grep_Shell_Quote_Char
764     endif
765
766     if filenames == ""
767         if v:version >= 700
768             let filenames = input("Search in files: ", g:Grep_Default_Filelist,
769                         \ "file")
770         else
771             let filenames = input("Search in files: ", g:Grep_Default_Filelist)
772         endif
773         if filenames == ""
774             return
775         endif
776     endif
777
778     " Add /dev/null to the list of filenames, so that grep print the
779     " filename and linenumber when grepping in a single file
780     let filenames = filenames . " " . g:Grep_Null_Device
781     let cmd = grep_path . " " . grep_opt . " -n "
782     let cmd = cmd . grep_expr_option . " " . pattern
783     let cmd = cmd . " " . filenames
784
785     call s:RunGrepCmd(cmd, pattern, a:action)
786 endfunction
787
788 " Define the set of grep commands
789 command! -nargs=* -complete=file Grep
790             \ call s:RunGrep('Grep', 'grep', 'set', <f-args>)
791 command! -nargs=* -complete=file Rgrep
792             \ call s:RunGrepRecursive('Rgrep', 'grep', 'set', <f-args>)
793 command! -nargs=* GrepBuffer
794             \ call s:RunGrepSpecial('GrepBuffer', 'buffer', 'set', <f-args>)
795 command! -nargs=* Bgrep
796             \ call s:RunGrepSpecial('Bgrep', 'buffer', 'set', <f-args>)
797 command! -nargs=* GrepArgs
798             \ call s:RunGrepSpecial('GrepArgs', 'args', 'set', <f-args>)
799
800 command! -nargs=* -complete=file Fgrep
801             \ call s:RunGrep('Fgrep', 'fgrep', 'set', <f-args>)
802 command! -nargs=* -complete=file Rfgrep
803             \ call s:RunGrepRecursive('Rfgrep', 'fgrep', 'set', <f-args>)
804 command! -nargs=* -complete=file Egrep
805             \ call s:RunGrep('Egrep', 'egrep', 'set', <f-args>)
806 command! -nargs=* -complete=file Regrep
807             \ call s:RunGrepRecursive('Regrep', 'egrep', 'set', <f-args>)
808 command! -nargs=* -complete=file Agrep
809             \ call s:RunGrep('Agrep', 'agrep', 'set', <f-args>)
810 command! -nargs=* -complete=file Ragrep
811             \ call s:RunGrepRecursive('Ragrep', 'agrep', 'set', <f-args>)
812
813 if v:version >= 700
814 command! -nargs=* -complete=file GrepAdd
815             \ call s:RunGrep('GrepAdd', 'grep', 'add', <f-args>)
816 command! -nargs=* -complete=file RgrepAdd
817             \ call s:RunGrepRecursive('RgrepAdd', 'grep', 'add', <f-args>)
818 command! -nargs=* GrepBufferAdd
819             \ call s:RunGrepSpecial('GrepBufferAdd', 'buffer', 'add', <f-args>)
820 command! -nargs=* BgrepAdd
821             \ call s:RunGrepSpecial('BgrepAdd', 'buffer', 'add', <f-args>)
822 command! -nargs=* GrepArgsAdd
823             \ call s:RunGrepSpecial('GrepArgsAdd', 'args', 'add', <f-args>)
824
825 command! -nargs=* -complete=file FgrepAdd
826             \ call s:RunGrep('FgrepAdd', 'fgrep', 'add', <f-args>)
827 command! -nargs=* -complete=file RfgrepAdd
828             \ call s:RunGrepRecursive('RfgrepAdd', 'fgrep', 'add', <f-args>)
829 command! -nargs=* -complete=file EgrepAdd
830             \ call s:RunGrep('EgrepAdd', 'egrep', 'add', <f-args>)
831 command! -nargs=* -complete=file RegrepAdd
832             \ call s:RunGrepRecursive('RegrepAdd', 'egrep', 'add', <f-args>)
833 command! -nargs=* -complete=file AgrepAdd
834             \ call s:RunGrep('AgrepAdd', 'agrep', 'add', <f-args>)
835 command! -nargs=* -complete=file RagrepAdd
836             \ call s:RunGrepRecursive('RagrepAdd', 'agrep', 'add', <f-args>)
837 endif
838
839 " Add the Tools->Search Files menu
840 if has('gui_running')
841     anoremenu <silent> Tools.Search.Current\ Directory<Tab>:Grep
842                 \ :Grep<CR>
843     anoremenu <silent> Tools.Search.Recursively<Tab>:Rgrep
844                 \ :Rgrep<CR>
845     anoremenu <silent> Tools.Search.Buffer\ List<Tab>:Bgrep
846                 \ :Bgrep<CR>
847     anoremenu <silent> Tools.Search.Argument\ List<Tab>:GrepArgs
848                 \ :GrepArgs<CR>
849 endif
850
851 " restore 'cpo'
852 let &cpo = s:cpo_save
853 unlet s:cpo_save
854