1 module dmdtags.main; 2 3 int main(string[] args) 4 { 5 import std.stdio: stderr; 6 7 try tryMain(args); 8 catch (Exception e) { 9 stderr.writeln("dmdtags: ", e.message); 10 return 1; 11 } 12 return 0; 13 } 14 15 void printUsage() 16 { 17 import std.stdio: stderr, writeln; 18 19 stderr.writeln("Usage: dmdtags [-R] [-a] [-f|-o tagfile] [path...]"); 20 } 21 22 void tryMain(string[] args) 23 { 24 import dmdtags.generate: SymbolTagger; 25 import dmdtags.appender: Appender; 26 import dmdtags.span; 27 28 import dmd.frontend: initDMD, parseModule; 29 import dmd.errors: DiagnosticHandler; 30 31 import std.algorithm: sort, uniq, each; 32 import std.getopt: getopt; 33 import std.stdio: File, stdout; 34 import std.file: exists, isDir, isFile, dirEntries, SpanMode; 35 36 bool recurse; 37 string tagfile = "tags"; 38 bool append; 39 40 auto result = args.getopt( 41 "recurse|R", &recurse, 42 "f|o", &tagfile, 43 "append|a", &append, 44 ); 45 46 if (result.helpWanted) { 47 printUsage(); 48 return; 49 } 50 51 string[] paths; 52 if (args.length > 1) { 53 paths = args[1 .. $]; 54 } else if (recurse) { 55 paths = ["."]; 56 } else { 57 printUsage(); 58 return; 59 } 60 61 DiagnosticHandler ignoreErrors = (ref _1, _2, _3, _4, _5, _6, _7) => true; 62 initDMD(ignoreErrors); 63 64 Appender!(Span!(const(char))) tags; 65 scope tagger = new SymbolTagger(tags); 66 67 void processSourceFile(string path) 68 { 69 auto parseResult = parseModule(path); 70 parseResult.module_.accept(tagger); 71 } 72 73 foreach (path; paths) { 74 if (path.isFile) { 75 processSourceFile(path); 76 } else if (recurse && path.isDir) { 77 foreach (entry; dirEntries(path, "*.{d,di}", SpanMode.depth)) { 78 if (entry.isFile) { 79 processSourceFile(entry.name); 80 } 81 } 82 } 83 } 84 85 if (append && tagfile.exists) { 86 import std.algorithm: filter, startsWith, map, copy; 87 88 File(tagfile, "r") 89 .byLineCopy 90 .filter!(line => !line.startsWith("!_TAG_")) 91 .map!((const(char)[] line) => line.span.headMutable) 92 .copy(tags); 93 } 94 95 sort(tags[]); 96 97 File output; 98 if (tagfile == "-") { 99 output = stdout; 100 } else { 101 output = File(tagfile, "w"); 102 } 103 104 output.writeln("!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/"); 105 tags[].uniq.each!(tag => output.writeln(tag)); 106 }