Skip to content

Instantly share code, notes, and snippets.

@SirTony
Created March 2, 2015 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SirTony/c2c2ee48f0649dddddbf to your computer and use it in GitHub Desktop.
Save SirTony/c2c2ee48f0649dddddbf to your computer and use it in GitHub Desktop.
A grep-like tool written in D.
module grep;
private:
import std.stdio;
import std.regex;
import std.getopt;
import std.range;
import std.file;
import std.path;
import std.string;
import io = std.stream;
bool recursive;
bool ignoreCase;
Regex!char searchRegex;
Regex!char fileRegex;
enum string usage = q{grep.d - Tony Hudgins (c) 2015
A small command-line utility for matching file contents.
Usage: grep [flags...] <file filter> <regex pattern>
Flags can be any combination of the following:
--help, -h | Show this help message.
--ignore-case, -i | Perform a case-insensitive match.
--recursive, -r | Recursively search subdirectories for matching files.
};
int main( string[] args )
{
try
{
bool help;
args.getopt(
config.caseInsensitive,
config.bundling,
"help|h", &help,
"recursive|r", &recursive,
"ignore-case|i", &ignoreCase
);
if( help )
{
stderr.writeln( usage );
return -1;
}
}
catch( GetOptException e )
{
stderr.writeln( e.msg );
return 5;
}
if( args.length > 0 )
args.popFront();
if( args.length == 0 )
{
stderr.writeln( usage );
return 3;
}
if( !args.front.verifyRegex( fileRegex ) )
return 1;
args.popFront();
if( args.length == 0 )
{
stderr.writeln( usage );
return 4;
}
if( !args.front.verifyRegex( searchRegex ) )
return 2;
args.popFront();
auto entries = getcwd().dirEntries( recursive ? SpanMode.depth : SpanMode.shallow );
foreach( entry; entries )
{
if( entry.isDir )
continue;
if( !entry.name.matchFirst( fileRegex ) )
continue;
auto path = buildNormalizedPath( getcwd(), entry.name );
auto file = new io.File( path, io.FileMode.In );
foreach( lineno, char[] line; file )
{
auto match = line.matchFirst( searchRegex );
if( !match )
continue;
auto name = entry.name.replace( getcwd(), "" )[1 .. $];
"%s:%s - %s".writefln( name, lineno, match.hit );
}
}
return 0;
}
bool verifyRegex( string pattern, out Regex!char rex )
{
try
{
rex = pattern.regex( ignoreCase ? "i" : "" );
return true;
}
catch( RegexException e )
{
stderr.writeln( e.msg );
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment