main.d (4297B) download
1// (c) 2022 Friedel Schon <[email protected]>
2
3module importsort.main;
4
5import core.stdc.stdlib : exit;
6import importsort.sort : Import, SortConfig, sortImports;
7import std.array : replace;
8import std.conv : ConvException, parse;
9import std.file : DirEntry, SpanMode, dirEntries, exists, isDir, isFile;
10import std.functional : unaryFun;
11import std.stdio : File, stderr, stdin, stdout;
12import std.string : endsWith;
13
14enum BINARY = "importsort-d";
15enum VERSION = "0.1.0";
16enum HELP = import("help.txt")
17 .replace("{binary}", BINARY)
18 .replace("{version}", VERSION);
19
20DirEntry[] listEntries(alias F = "true")(string[] input, bool recursive) {
21 alias filterFunc = unaryFun!F;
22
23 DirEntry[] entries;
24
25 foreach (path; input) {
26 if (!exists(path)) {
27 stderr.writef("error: '%s' does not exist\n", path);
28 exit(1);
29 } else if (isDir(path)) {
30 foreach (entry; dirEntries(path, recursive ? SpanMode.depth : SpanMode.shallow)) {
31 if (entry.isFile && entry.name.endsWith(".d") && filterFunc(entry.name))
32 entries ~= entry;
33 }
34 } else if (isFile(path)) {
35 if (!path.endsWith(".d")) {
36 stderr.writef("error: '%s' is not a .d-file\n", path);
37 exit(1);
38 }
39 if (filterFunc(path))
40 entries ~= DirEntry(path);
41 } else {
42 stderr.writef("error: '%s' is not a file or directory\n", path);
43 exit(1);
44 }
45 }
46 return entries;
47}
48
49void main(string[] args) {
50 SortConfig config;
51 bool inline;
52 string output;
53 string[] input;
54 bool watcher;
55 bool watcherDelaySet;
56 double watcherDelay = 0.1; // sec
57 bool recursive;
58
59 // -*- option parser -*-
60
61 bool nextOutput;
62 bool nextWatcherDelay;
63 foreach (arg; args[1 .. $]) {
64 if (nextOutput) {
65 output = arg;
66 nextOutput = false;
67 } else if (nextWatcherDelay) {
68 try {
69 watcherDelay = parse!double(arg);
70 } catch (ConvException) {
71 stderr.writef("error: cannot parse delay '%s' to an integer\n", arg);
72 exit(1);
73 }
74 watcherDelaySet = true;
75 nextWatcherDelay = false;
76 } else if (arg == "--help" || arg == "-h") {
77 stdout.writeln(HELP);
78 return;
79 } else if (arg == "--verbose" || arg == "-v") {
80 config.verbose = true;
81 } else if (arg == "--keep" || arg == "-k") {
82 config.keepLine = true;
83 } else if (arg == "--attribute" || arg == "-a") {
84 config.byAttribute = true;
85 } else if (arg == "--binding" || arg == "-b") {
86 config.byBinding = true;
87 } else if (arg == "--merge" || arg == "-m") {
88 config.merge = true;
89 } else if (arg == "--inline" || arg == "-i") {
90 inline = true;
91 } else if (arg == "--recursive" || arg == "-r") {
92 recursive = true;
93 // TODO: --watch
94 /*} else if (arg == "--watch" || arg == "-w") {
95 watcher = true;
96 } else if (arg == "--delay" || arg == "-d") {
97 if (watcherDelaySet) {
98 stderr.writeln("error: watcher-delay already specified");
99 stderr.writeln(HELP);
100 exit(1);
101 }
102 nextWatcherDelay = true;*/
103 } else if (arg == "--output" || arg == "-o") {
104 if (output != null) {
105 stderr.writeln("error: output already specified");
106 stderr.writeln(HELP);
107 exit(1);
108 }
109 nextOutput = true;
110 } else if (arg[0] == '-') {
111 stderr.writef("error: unknown option '%s'\n", arg);
112 stderr.writeln(HELP);
113 exit(1);
114 } else {
115 input ~= arg;
116 }
117 }
118 if (recursive && input.length == 0) {
119 stderr.writeln("error: cannot use '--recursive' and specify no input");
120 exit(1);
121 }
122 if (inline && input.length == 0) {
123 stderr.writeln("error: cannot use '--inline' and read from stdin");
124 exit(1);
125 }
126 if ((!inline || output.length > 0) && input.length > 0) {
127 stderr.writeln("error: if you use inputs you must use '--inline'");
128 exit(1);
129 }
130 // -*- operation -*-
131
132 /* if (watcher) {
133 stderr.writeln("\033[1;34mwatching files...\033[0m");
134 SysTime[string] lastModified;
135 for (;;) {
136 auto entries = listEntries!(x => x !in lastModified
137 || lastModified[x] != x.timeLastModified)(input, recursive);
138
139 foreach (entry; entries) {
140 lastModified[entry.name] = entry.timeLastModified;
141 }
142 entries.sortImports(config);
143 Thread.sleep(Duration!"msecs"(cast(long) watcherDelay * 1000));
144 }
145 } else
146 */
147 if (input == null) {
148 File outfile = (output == null) ? stdout : File(output);
149
150 sortImports(stdin, outfile, config);
151 if (output)
152 outfile.close();
153 } else {
154 listEntries(input, recursive).sortImports(config);
155 }
156}