Vim Tips Wiki
No edit summary
m (Reverted edits by 62.189.77.47 (talk | block) to last version by Fritzophrenic)
 
Line 1: Line 1:
  +
{{review}}
  +
{{TipImported
  +
|id=79
  +
|previous=78
  +
|next=80
  +
|created=June 14, 2001
  +
|complexity=basic
  +
|author=Flemming Madsen
  +
|version=6.0
  +
|rating=130/40
  +
|category1=C
  +
|category2=Searching
  +
}}
  +
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()'
#include<stdio.h>
 
  +
#include<string.h>
 
  +
You may want to do :nmap <somekey> :call ShowFunc()<CR>
int main(int argc,char *argv[])
 
  +
{
 
  +
<pre>
int i,j;
 
  +
function! ShowFunc()
char a1[100],b1[100];
 
  +
let gf_s = &grepformat
FILE *fp;
 
  +
let gp_s = &grepprg
if(argc==3)
 
  +
let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %*\s%m'
{
 
  +
let &grepprg = 'ctags -x --c-types=f --sort=no -o -'
fp=fopen(argv[2],"r");
 
  +
write
strcpy(a1,argv[1]);
 
  +
silent! grep %
i=0;
 
  +
cwindow
while(!feof(fp))
 
  +
let &grepformat = gf_s
{
 
  +
let &grepprg = gp_s
fgets(b1,sizeof(b1),fp);
 
  +
endfunc
if(strstr(b1,a1)!=NULL)
 
  +
</pre>
{
 
  +
i++;
 
  +
==Comments==
printf("%s",b1);
 
  +
Some enhancements courtesy of Bill McCarthy:
}
 
  +
 
  +
<pre>
}
 
  +
> let &grepprg = 'ctags -x --c-types=f --sort=no -o -'
if(i==0)
 
  +
or just: let &grepprg = 'ctags -x --c-types=f --sort=no'
printf("\n NO MATCH FOUND \n");
 
  +
since the '-o -' is redundant with '-x'.
fclose(fp);
 
  +
> write
}
 
  +
or better yet: update
else if(argc==4)
 
  +
which will not change the filedate on a file that hasn't changed.
{
 
  +
</pre>
int i=0;
 
  +
char a[100],b[100],c[100];
 
  +
----
fp=fopen(argv[3],"r");
 
  +
I'd suggest that the call to write or update (as noted in the note above) be changed to:
strcpy(a,argv[2]);
 
  +
if (&readonly == 0) | update | endif
if(argv[1][1]=='n')
 
  +
so that you don't get an error message when attempting this on a read only file.
{
 
  +
 
  +
----
j=0;
 
  +
For some reason this fails in vim6.0au under unix with file names longer than about 14 characters. however, if you change
printf("Lno Line\n");
 
  +
let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %*\s%m'
while(!feof(fp))
 
  +
to
{
 
  +
let &grepformat = '%*\k%*\sfunction%*\s%l%*\s%f %m'
fgets(b,sizeof(b),fp);
 
  +
then it works fine regardless of file name length.
i++;
 
  +
if(strstr(b,a)!=NULL)
 
  +
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 %
j++;
 
  +
cwindow
printf("%d %s\n",i,b);
 
  +
redraw
}
 
  +
let &grepformat = gf_s
}
 
  +
if(j==0)
 
  +
----
printf("\nNO MATCH FOUND\n");
 
  +
Ok, couple of small bugs and mistakes fixed. Try this version:
fclose(fp);
 
  +
}
 
  +
<pre>
if(argv[1][1]=='c')
 
  +
function! ShowFunc(sort)
{
 
  +
let gf_s = &grepformat
i=0;
 
  +
let gp_s = &grepprg
j=0;
 
  +
if ( &filetype == "c" || &filetype == "php" || &filetype == "python" ||
fp=fopen(argv[3],"r");
 
  +
\ &filetype == "sh" )
while(!feof(fp))
 
  +
let &grepformat='%*\k%*\sfunction%*\s%l%*\s%f %m'
{
 
  +
let &grepprg = 'ctags -x --'.&filetype.'-types=f --sort='.a:sort
fgets(b,sizeof(b),fp);
 
  +
elseif ( &filetype == "perl" )
if(strstr(b,a)!=NULL)
 
  +
let &grepformat='%*\k%*\ssubroutine%*\s%l%*\s%f %m'
{
 
  +
let &grepprg = 'ctags -x --perl-types=s --sort='.a:sort
i++;
 
  +
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
printf("\n Number of lines containing Pattern %s is : %d\n",a,i);
 
  +
endif
if(i==0)
 
  +
if (&readonly == 0) | update | endif
printf("NO MATCH FOUND\n");
 
  +
silent! grep %
fclose(fp);
 
  +
cwindow 10
}
 
  +
redraw
if(argv[1][1]=='v')
 
  +
let &grepformat = gf_s
{
 
  +
let &grepprg = gp_s
i=0;
 
  +
endfunc
fp=fopen(argv[3],"r");
 
  +
</pre>
while(!feof(fp))
 
  +
{
 
  +
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.
fgets(b,sizeof(b),fp);
 
  +
if(strstr(b,a)==NULL)
 
  +
noremap <F3> <Esc>:call ShowFunc("no")<CR><Esc>
{
 
  +
noremap &lt;S-F3> <Esc>:call ShowFunc("yes")<CR><Esc>
i++;
 
  +
printf("%s",b);
 
  +
And last be sure you have Exuberant CTags installed or it won't work.
}
 
  +
}
 
  +
----
if(i==0)
 
  +
Try this for Java:
printf("\nALL LINES CONTAINS THE PATTERN\n");
 
  +
elseif ( &filetype == "java" )
 
  +
let &grepformat='%*\k%*\sclass%*\s%l%*\s%f %m'
fclose(fp);
 
  +
let &grepprg = 'ctags -x --java-types=c --sort='.a:sort
}
 
  +
if(argv[1][1]=='x')
 
  +
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
 
  +
 
  +
----
fp=fopen(argv[3],"r");
 
  +
I increased the number of file types supported to 19.
a[strlen(a)]='\n';
 
  +
i=0;
 
  +
You can now search for
while(!feof(fp))
 
  +
1. Classes - Java
{
 
  +
2. Functions - Awk, C, C++, Fortran, Lisp, Pascal, PHP, Python, Ruby, Shell Scripts, Scheme, Slang, and Vim
fgets(b,sizeof(b),fp);
 
  +
3. Macros - Makefiles
if(strcmp(a,b)==0)
 
  +
4. Procedures - Expect, and Tcl
{
 
  +
5. Subroutines - Perl and Rexx
i++;
 
  +
printf("%s",b);
 
  +
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.
if(i==0)
 
  +
printf("\nNO LINE MATCHES THE PATTERN\n");
 
  +
Last, I packaged this function as {{script|id=397}} to make it easier to install, and to get it out of my vimrc file.
fclose(fp);
 
  +
}
 
  +
----
if(argv[1][1]=='i')
 
{
 
j=0;
 
fp=fopen(argv[3],"r");
 
for(i=0;a[i];i++)
 
a[i]=tolower(a[i]);
 
while(!feof(fp))
 
{
 
fgets(b,sizeof(b),fp);
 
for(i=0;b[i];i++)
 
c[i]=tolower(b[i]);
 
if(strstr(c,a)!=NULL)
 
{
 
printf("%s",b);
 
i++;
 
}
 
}
 
if(j==0)
 
printf("\nNO MATCH FOUND\n");
 
fclose(fp);
 
}
 
}
 
else
 
{
 
printf("\nEnter Arguments As Per Grep Command\n ");
 
}
 
return 0;
 
}
 

Latest revision as of 14:37, 30 August 2011

Tip 79 Printable Monobook Previous Next

created June 14, 2001 · complexity basic · author Flemming Madsen · version 6.0


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[]

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.

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.


For some reason this fails 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

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.


Try this for Java:

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

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 script#397 to make it easier to install, and to get it out of my vimrc file.