Vim Tips Wiki
Advertisement

Previous TipNext Tip

Tip: #79 - Use grep to get a clickable list of function names

Created: June 14, 2001 2:13 Complexity: basic Author: Flemming Madsen Version: 6.0 Karma: 130/40 Imported from: Tip#79

The following function will make a :cwindow window with a line per function

in the current C source file. NOTE: It writes the file as a side effect.


Invoke with ':call ShowFunc()'

You may want to do :nmap <somekey> :call ShowFunc()<CR>


function! ShowFunc()


let gf_s = &grepformat 
let gp_s = &grepprg 


let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %*\s%m' 
let &grepprg = 'ctags -x --c-types=f --sort=no -o -' 


write 
silent! grep % 
cwindow 


let &grepformat = gf_s 
let &grepprg = gp_s 


endfunc

Comments

When I try this from a .c source file: I get the following error message:

Error detected while processing function ShowFunc: Regular expressions can't be delimited by letters Not an editor command: cwindow


tim--AT--johnsons-web.com , June 14, 2001 9:11


I guess this works only with vim 6.0 so cwindow isnt recognized in the above node. This is a really useful functions. But somehow when I use it on a file opened using explorer.vim it doesnt work as expected. It does list the functions in cwindow but somehow the links dont work. Does anyone know how to fix this. It the file is opened normally using :e then things work just fine. Very useful, especially with big files.

Thanks. Parth


parth.malwankar--AT--usa.net , June 15, 2001 6:38


Some enhancements courtesy of Bill McCarthy:

> let &grepprg = 'ctags -x --c-types=f --sort=no -o -' or just: let &grepprg = 'ctags -x --c-types=f --sort=no' since the '-o -' is redundant with '-x'. > write or better yet: update which will not change the filedate on a file that hasn't changed.


Flemming , June 18, 2001 0:14


I'd suggest that the call to write or update (as noted in the note above) be changed to:

if (&readonly == 0) | update | endif 

so that you don't get an error message when attempting this on a read only file.

leifw at bigfoot , com , July 19, 2001 11:16


for some reason this failes in vim6.0au under unix with file names longer than about 14 characters. however, if you change

let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %*\s%m' 

to

let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %m' 

then it works fine regardless of file name length.

running on a terminal, if there are a lot of functions in a file then the screen tends to get messed up, which can be fixed by insering a call to redraw after the cwindow call, so you get:

silent! grep % 
cwindow 
redraw 
let &grepformat = gf_s

feline3344--AT--yahoo.com , September 10, 2001 3:38


WOW! this is absolutely kewl!! thx!!

supergrass--AT--gmx.net , February 9, 2002 4:50


Ok, after installing Exuberant Ctags (ctags.sourceforge.net), and tweaking it a little while, this version of the function works with C, Perl, PHP, Python, Shell and Vim filetypes.

if !exists("*ShowFunc")

function! ShowFunc() 
let gf_s = &grepformat 
let gp_s = &grepprg 
if ( &filetype == "c" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --c-types=f --sort=no' 
elseif ( &filetype == "perl" ) 
let &grepformat='%*\k%*\ssubroutine%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --perl-types=s --sort=no' 
elseif ( &filetype == "php" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --php-types=f --sort=no' 
elseif ( &filetype == "python" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --python-types=f --sort=no' 
elseif ( &filetype == "sh" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --sh-types=f --sort=no' 
elseif ( &filetype == "vim" ) 
let &grepformat='%*\k%*\sfunction!%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --vim-types=f --sort=no' 
endif 
if (&readonly == 0) | update | endif 
silent! grep % 
cwindow 
redraw 
let &grepformat = gf_s 
let &grepprg = gp_s 
endfunc 

endif


Dave V.

davev--AT--ziplip.com , February 25, 2002 20:07


It doesn't seem to work or do anything at all for me.

Anyone have any ideas?

kkm9--AT--cornell.edu , March 7, 2002 6:22


Ok, couple of small bugs and mistakes fixed. Try this version:

function! ShowFunc(sort)

let gf_s = &grepformat 
let gp_s = &grepprg 
if ( &filetype == "c" || &filetype == "php" || &filetype == "python" || 
\ &filetype == "sh" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --'.&filetype.'-types=f --sort='.a:sort 
elseif ( &filetype == "perl" ) 
let &grepformat='%*\k%*\ssubroutine%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --perl-types=s --sort='.a:sort 
elseif ( &filetype == "vim" ) 
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --vim-types=f --language-force=vim --sort='.a:sort 
endif 
if (&readonly == 0) | update | endif 
silent! grep % 
cwindow 10 
redraw 
let &grepformat = gf_s 
let &grepprg = gp_s 

endfunc

I map this function to F3 to produce a list in the order the functions appear in the file or Shift-F3 to list them in alphabetical order.

noremap <F3> <ESC>:call ShowFunc("no")<CR><ESC> noremap <S-F3> <ESC>:call ShowFunc("yes")<CR><ESC>

And last be sure you have Exuberant CTags installed or it won't work.

Dave V.

davev--AT--ziplip.com , March 16, 2002 19:56


I am using vim 6.1 on Unix, it's seems like not working at all. When I do F3 or Shift F3, VIM screen refreshes but nothing else Himanshu

himanshu_patel--AT--hotmail.com , April 17, 2002 6:08


Do you have filetype detection enabled?

If not, add "filetype on" to your .vimrc.

Dave V.

davev--AT--ziplip.com , April 27, 2002 21:34


This is really cool! Is there any chance someone could add a java case as well. I don't really understand whats happening here but adding it to the c et al case doesn't work.

bmonnahan--AT--subdimension.com , July 19, 2002 0:21


Try this:

elseif ( &filetype == "java" ) 
let &grepformat='%*\k%*\sclass%*\s%l%*\s%f %m' 
let &grepprg = 'ctags -x --java-types=c --sort='.a:sort 

If this produces blank results, then you can try changing the last line to:

let &grepprg = 'ctags -x --java-types=c --language-force=java --sort='.a:sort 

Good luck,

Dave


davev--AT--ziplip.com , August 3, 2002 21:50


I increased the number of file types supported to 19.

You can now search for 1. Classes - Java 2. Functions - Awk, C, C++, Fortran, Lisp, Pascal, PHP, Python, Ruby, Shell Scripts, Scheme, Slang, and Vim 3. Macros - Makefiles 4. Procedures - Expect, and Tcl 5. Subroutines - Perl and Rexx

C, Shell Scripts, Vim, Expect, Tcl and Perl are well tested. The rest work on the few tests that I have given them. Let me know of any bugs and I'll work them out.

Additionally, I changed it so that it opens a dynamically sized cwindow based on the height of the window it was called from and/or the number of links in the results. An empty search returns a cwindow a single line tall.

Last, I packaged this function as a script ([/scripts/script.php?script_id=397 vimscript #397]) to make it easier to install, and to get it out of my vimrc file.

Dave Vehrs


davev--AT--ziplip.com , August 24, 2002 16:57


I installed the exuberant-ctags deb file from unstable (after having the same error from testing) and all I get is this error: ctags: unrecognized option `--c-types=f'

It seems the problem is with ctags but it also seems to be version 5.3 and I can see that line referenced as an example in the man page.


montagne--AT--boora.com , August 27, 2002 8:17


dear sir how do you sh convert this into straight forward PERL.



#!/usr/bin/sh 

if test $# -ne "2" then

echo "" 
echo Error: Usage: $0 rooms 
echo "" 
exit 1 

fi if test ! -f $1 then

echo "" 
echo Error: File '$1' does not exist 
echo "" 
exit 2 

fi

if test -z "`grep -i $2 $1`" then

echo "" 
echo Error: No records found for '$2' building 
echo "" 
exit 3 

else echo "" echo List of rooms in '$2' building in ascending seat_capacity order echo "" grep -i $2 $1 $3 | sort -b -n -k3 echo "" fi exit 0 set


pritchard_albany_uk--AT--hotmail.com , November 7, 2004 9:28


dear sir how do you sh convert this into straight forward PERL.



#!/usr/bin/sh 

if test $# -ne "2" then

echo "" 
echo Error: Usage: $0 rooms 
echo "" 
exit 1 

fi if test ! -f $1 then

echo "" 
echo Error: File '$1' does not exist 
echo "" 
exit 2 

fi

if test -z "`grep -i $2 $1`" then

echo "" 
echo Error: No records found for '$2' building 
echo "" 
exit 3 

else echo "" echo List of rooms in '$2' building in ascending seat_capacity order echo "" grep -i $2 $1 $3 | sort -b -n -k3 echo "" fi exit 0 set


pritchard_albany_uk--AT--hotmail.com , November 7, 2004 9:29


Advertisement