Created
March 2, 2015 19:59
-
-
Save SirTony/c2c2ee48f0649dddddbf to your computer and use it in GitHub Desktop.
A grep-like tool written in D.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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