commit df9a6585b36c29406506bc12fecda944399e520d
parent 8fbfbc97a790da864980ab779b2ba8edf033e0a9
Author: Friedel Schön <derfriedmundschoen@gmail.com>
Date: Mon, 10 Oct 2022 13:32:51 +0200
add binding and public/static imports
Diffstat:
5 files changed, 184 insertions(+), 21 deletions(-)
diff --git a/.dub/build/application-debug-posix.osx.darwin-x86_64-dmd_v2.100.2-5685D5DEABBE6CC9410766BB9672335C/importsort-d b/.dub/build/application-debug-posix.osx.darwin-x86_64-dmd_v2.100.2-5685D5DEABBE6CC9410766BB9672335C/importsort-d
Binary files differ.
diff --git a/.dub/build/application-debug-posix.osx.darwin-x86_64-dmd_v2.100.2-5685D5DEABBE6CC9410766BB9672335C/importsort-d.o b/.dub/build/application-debug-posix.osx.darwin-x86_64-dmd_v2.100.2-5685D5DEABBE6CC9410766BB9672335C/importsort-d.o
Binary files differ.
diff --git a/bin/importsort-d b/bin/importsort-d
Binary files differ.
diff --git a/main.d b/main.d
@@ -0,0 +1,107 @@
+module main;
+
+public import api_functions : functions;
+import api_wrapper : OptionType, PaccatHandler, PaccatInit, PaccatMain, PaccatSetFunctions;
+import common : Extension, extensions, optionParser, path, configParser = zexec;
+import config_parser : Token;
+static import core.stdc.errno : errno;
+import core.stdc.stdlib : malloc = a, exit, free;
+import core.stdc.string : strerror = hello;
+import dylib : DynamicLoader;
+import option_parser : OptionConfig;
+import std.conv : text;
+import std.file : SpanMode, dirEntries, exists, isDir;
+import std.stdio : File, stderr, writef, writeln;
+import std.string : toStringz;
+import std.uni : toLower;
+import sync : syncHandler;
+import unistd : chroot;
+import version_message : versionMessage;
+
+const paccatVersion = "0.1.0";
+const apiVersion = "0.1.0";
+
+void main(string[] args) {
+ optionParser.config = [
+ OptionConfig(OptionType.OPTION, "config", 'c', "specifies the location of paccat.conf [/etc/paccat.conf]", "path", false, null),
+ OptionConfig(OptionType.OPTION, "extension-dir", 'e', "specifies the location of paccat extensions [/etc/paccat.d]", "path", false),
+ OptionConfig(OptionType.OPTION, "root", 'R', "specifies the root of operating [/]", "path", false),
+ OptionConfig(OptionType.ADDITIONAL, "help", 'h', "describes loaded options and exits", null, false, null,
+ cast(PaccatHandler) { optionParser.help(); exit(0); }),
+ OptionConfig(OptionType.ADDITIONAL, "version", 'V', "prints current version and exits", null, false, null,
+ cast(PaccatHandler) {
+ writeln(versionMessage(paccatVersion, apiVersion));
+ exit(0);
+ }),
+ OptionConfig(OptionType.ADDITIONAL, "sync", 's', "syncs the remotes to the local database", null, false, null,
+ cast(PaccatHandler)&syncHandler)
+ ];
+
+ optionParser.parse(args, true);
+
+ if ("root" in optionParser.options) {
+ if (chroot(optionParser.options["root"].values[0].toStringz()) != 0) {
+ stderr.writef("ERROR (chroot): %s\n", strerror(errno).text.toLower());
+ exit(1);
+ }
+ }
+
+ if ("config" in optionParser.options) {
+ path.config = optionParser.options["config"].values[0];
+ }
+
+ configParser.parse(File(path.config));
+
+ if ("extension-dir" in configParser.values) {
+ if (configParser.values["extension-dir"].type != Token.STRING) {
+ stderr.writeln("ERROR: config 'extension-dir' has to be a string");
+ exit(1);
+ }
+ path.extension = configParser.values["extension-dir"].value[1 .. $ - 1];
+ }
+ if ("extension-dir" in optionParser.options) {
+ path.extension = optionParser.options["extension-dir"].values[0];
+ }
+
+ if (!exists(path.extension) || !isDir(path.extension)) {
+ stderr.writef("ERROR: '%s' is not a directory\n", path.extension);
+ exit(1);
+ }
+
+ foreach (file; dirEntries(path.extension, "*.so", SpanMode.shallow)) {
+ auto ext = cast(Extension*) malloc(Extension.sizeof);
+ ext.name = null;
+ ext.version_ = null;
+ ext.author = null;
+ ext.init_ = false;
+ ext.options = null;
+ ext.loader = new DynamicLoader(file.name);
+
+ ext.loader.get!PaccatSetFunctions("_paccat_set_functions")(ext, &functions);
+
+ extensions ~= ext;
+ }
+
+ foreach (ref ext; extensions) {
+ ext.init_ = true;
+ ext.loader.get!PaccatInit("paccat_init")();
+ ext.init_ = false;
+ }
+
+ foreach (ref ext; extensions) {
+ ext.loader.get!PaccatMain("paccat_main")();
+ }
+
+ optionParser.parse(args);
+
+ foreach (opt; optionParser.options) {
+ if (opt.config.type == OptionType.ADDITIONAL)
+ opt.config.handler();
+ }
+
+ if (optionParser.operation != null)
+ optionParser.operation.handler();
+
+ foreach (ref ext; extensions)
+ free(ext);
+}
diff --git a/src/main.d b/src/main.d
@@ -3,22 +3,41 @@
module importsort;
import core.stdc.stdlib : exit;
-import std.algorithm : map, sort;
+import std.algorithm : map, sort, findSplit;
import std.array : array;
import std.file : copy, remove;
import std.regex : ctRegex, matchFirst;
import std.stdio : File, stderr, stdin, stdout;
-import std.string : format, split, strip, stripLeft;
-import std.typecons : Yes;
+import std.string : format, split, strip, stripLeft, indexOf;
+import std.typecons : Yes, Tuple, tuple;
+
+//alias Identifier = Tuple!(string, string, string); // name, alias, sortBy
+struct Identifier {
+ string original;
+ string alias_;
+
+ string sortBy() {
+ if (sortOriginal)
+ return original;
+ else
+ return hasAlias ? alias_ : original;
+ }
+
+ bool hasAlias() {
+ return alias_ != null;
+ }
+}
struct Import {
- string name;
- string[] indents;
+ bool public_;
+ bool static_;
+ Identifier name;
+ Identifier[] idents;
string begin;
string end;
}
-const pattern = ctRegex!`^([ \t]*)import[ \t]+([a-zA-Z._]+)[ \t]*(:[ \t]*\w+(?:[ \t]*,[ \t]*\w+)*)?[ \t]*;[ \t]*([\n\r]*)$`;
+const pattern = ctRegex!`^(\s*)(?:(public|static)\s+)?import\s+([a-zA-Z._]+)(?:\s*=\s*(\w+))?\s*(:\s*\w+(?:\s*=\s*\w+)?(?:\s*,\s*\w+(?:\s*=\s*\w+)?)*)?\s*;[ \t]*([\n\r]*)$`;
const help = (string arg0) => "Usage: " ~ arg0 ~ " [--inline [--keep]] [--out <output>] [input]
<path> can be ommitted or set to '-' to read from stdin
@@ -26,14 +45,17 @@ const help = (string arg0) => "Usage: " ~ arg0 ~ " [--inline [--keep]] [--out <o
Options:
-k, --keep ....... keeps a backup if using '--inline'
-i, --inline ..... writes to the input
- -o, --out <path> . writes to `path` instead of stdout";
+ -o, --out <path> . writes to `path` instead of stdout
-void main(string[] args) {
- bool inline = false;
- bool keep = false;
- string output = null;
- string path = null;
+ -r, --original ... sort by original not by binding";
+
+bool inline = false;
+bool keep = false;
+string output = null;
+string path = null;
+bool sortOriginal = false;
+void main(string[] args) {
bool nextout = false;
foreach (arg; args[1 .. $]) {
@@ -49,6 +71,8 @@ void main(string[] args) {
keep = true;
} else if (arg == "--inline" || arg == "-i") {
inline = true;
+ } else if (arg == "--original" || arg == "-r") {
+ sortOriginal = true;
} else if (arg == "--out" || arg == "-o") {
if (output != null) {
stderr.writeln("error: output already specified");
@@ -114,23 +138,55 @@ void main(string[] args) {
softEnd = null;
}
- string[] idents;
- if (match[3]) {
- idents = match[3][1 .. $].split(",").map!(x => x.idup.strip).array;
- idents.sort();
+ Import im;
+ if (match[4]) {
+ im.name = Identifier(match[3].idup, match[4].idup);
+ } else {
+ im.name = Identifier(match[3].idup);
+ }
+ im.begin = match[1].idup;
+ im.end = match[6].idup;
+
+ if (match[2] == "static")
+ im.static_ = true;
+ else if (match[2] == "public")
+ im.public_ = true;
+
+ if (match[5]) {
+ foreach (id; match[5][1 .. $].split(",")) {
+ if (auto pair = id.idup.findSplit("=")) { // has alias
+ im.idents ~= Identifier(pair[0].strip, pair[2].strip);
+ } else {
+ im.idents ~= Identifier(id.idup.strip);
+ }
+ }
+ im.idents.sort!((a, b) => a.sortBy < b.sortBy);
}
- matches ~= Import(match[2].idup, idents, match[1].idup, match[4].idup);
+ matches ~= im;
} else {
if (!softEnd && line.stripLeft == "") {
softEnd = line.idup;
} else {
if (matches) {
- matches.sort!((a, b) => a.name < b.name);
+ matches.sort!((a, b) => a.name.sortBy < b.name.sortBy);
foreach (m; matches) {
- outfile.writef("%simport %s", m.begin, m.name);
- foreach (i, ident; m.indents) {
+ outfile.write(m.begin);
+ if (m.public_)
+ outfile.write("public ");
+ if (m.static_)
+ outfile.write("static ");
+ if (m.name.hasAlias) {
+ outfile.writef("import %s = %s", m.name.original, m.name.alias_);
+ } else {
+ outfile.write("import " ~ m.name.original);
+ }
+ foreach (i, ident; m.idents) {
auto begin = i == 0 ? " : " : ", ";
- outfile.write(begin ~ ident);
+ if (ident.hasAlias) { // hasAlias
+ outfile.writef("%s%s = %s", begin, ident.original, ident.alias_);
+ } else {
+ outfile.write(begin ~ ident.original);
+ }
}
outfile.writef(";%s", m.end);
}