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