Skip to content

Instantly share code, notes, and snippets.

@gregoryv
Created January 26, 2017 12:20
Show Gist options
  • Save gregoryv/b4b95bca669556a6ea3561d0b0efc95e to your computer and use it in GitHub Desktop.
Save gregoryv/b4b95bca669556a6ea3561d0b0efc95e to your computer and use it in GitHub Desktop.
Find and got place in file script
#!/usr/bin/perl
=head1 NAME - gogrep
Written by Gregory Vincic <g@7de.se>
=head1 DESCRIPTION
Looks for a statemet within files. If .gitignore is found in current
directory those files and directories are also excluded. Note that the syntax
is slightly different between greps exclude format and .gitignore.
Each found statement is numbered so the user can easily open the file on the specific line.
$EDITOR is used.
=head1 USAGE
gogrep REGEXP [GOTOINDEX]
=cut
use Term::ANSIColor qw(:constants);
# Build exclude from .gitignore if found
$exclude = "";
if( -e ".gitignore" ) {
open(GI, ".gitignore");
foreach(<GI>) {
chomp;
if(/\/$/) {
s/\/$//;
$exclude .= ' --exclude-dir="'. $_ . '"';
} else {
$exclude .= ' --exclude="'. $_ . '"';
}
}
close(GI);
}
# Search for todo expressions using grep
$statement = shift @ARGV;
$root = ".";
if( -d $statement ) {
$root = $statement;
$statement = shift @ARGV;
}
if(scalar(@ARGV) == 1 && $ARGV[0] =~ /(\d+)/) {
$gotoindex = $1;
}
$cmd='grep -rnIE ' . $exclude . ' --exclude-dir=".git" ' .'"' . $statement . '" ' . $root;
#print $cmd unless $gotoindex;
@changes=`$cmd`;
# Group lines by todo_NAME
%groups;
foreach(@changes) {
$line = $_;
$name = "No group\n";
if(/.*todo_(\w+).*/) {
$name = $1;
}
if(!$groups{$name}) {
$groups{$name} = ();
}
push @{$groups{$name}}, $line;
}
# Print result
%same = ();
$count = 0;
sub parts {
$line = @_[0];
$line =~ /([^:]+):(\d+):(.*)/;
$file = $1;
$no = $2;
$str = $3;
# Remove spaces at beginning of line
$str =~ s/^\s*//;
$str =~ s/^\/*//;
$str =~ s/^\**\s*//;
#$str =~ s/^[^#]+//;
$str =~ s/^#\s*//;
$str =~ s/^@//;
return $file, $no, $str;
}
my @found = ();
@sorted = sort(keys(%groups));
push(@sorted, shift(@sorted)); # move no group last
foreach(@sorted) {
$name = $_;
print YELLOW, $name, RESET unless $gotoindex;
foreach(@{$groups{$name}}) {
$line = $_;
$file, $no, $str = &parts($line);
$found[$count] = "$file:$no";
$count++;
if(!$same{$file}) { # Group all todos in the same file
$same{$file} = 1;
printf "\n %s:\n", $file unless $gotoindex;
}
printf " (%s%d%s) %4d: %s\n", WHITE, $count, RESET, $no, $str unless $gotoindex;
}
#print "\n";
}
unless($gotoindex) {
# Let user select a match
my $range = ($count == 1) ? 1 : "1-$count";
print "\nSelect $range: ";
$gotoindex = <STDIN>;
chomp ($gotoindex);
}
exit 0 unless($gotoindex);
# Open selected todo
if ( $gotoindex =~ /\d+/) {
$gotoindex--;
$entry = $found[$gotoindex];
my ($path, $line) = split(':', $entry);
`emacsclient -n +$line $path`;
exit 0;
}
if ($gotoindex) {
$all = join(" ", @found);
print $all, "\n";
foreach $entry (@found) {
my ($path, $line) = split(':', $entry);
`emacsclient -n +$line $path`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment