misc/importsort-d

src/main.d in v0.3.1
Repositories | Summary | Log | Files | README.md

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}