commit b209c0de1775ac8990b1b3baa99413a7fddb9f87
parent ea2d2f6435eaa2babdafd8a14c26cc07e147e737
Author: Christian Köstlin <[email protected]>
Date:   Fri, 22 Dec 2023 13:10:27 +0100
feature: Add option to ignore case
This should match what code-d does when sorting imports.
Diffstat:
3 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/assets/help.txt b/assets/help.txt
@@ -2,7 +2,7 @@
 
 Usage: {binary} [-h] [-v] [-r] [-i] [-o <out>] [-k] [-a] [-r] <input...>
   <input> can be set to '-' to read from stdin
-` 
+`
 Options:
   -h, --help .......... prints this message
   -v, --verbose ....... prints useful messages
@@ -11,7 +11,8 @@ Options:
   -a, --attribute ..... public and static imports first
   -b, --binding ....... sorts by binding rather then the original
   -m, --merge ......... merge imports which uses same file
-  
+  -c, --ignoreCase .... ignore case
+
   -r, --recursive ..... recursively search in directories
   -i, --inline ........ writes to the input
-  -o, --output <path> . writes to `path` instead of stdout
-\ No newline at end of file
+  -o, --output <path> . writes to `path` instead of stdout
diff --git a/src/main.d b/src/main.d
@@ -85,6 +85,8 @@ void main(string[] args) {
 			config.byBinding = true;
 		} else if (arg == "--merge" || arg == "-m") {
 			config.merge = true;
+		} else if (arg == "--ignoreCase" || arg == "-c") {
+			config.ignoreCase = true;
 		} else if (arg == "--inline" || arg == "-i") {
 			inline = true;
 		} else if (arg == "--recursive" || arg == "-r") {
@@ -106,7 +108,7 @@ void main(string[] args) {
 				exit(1);
 			}
 			nextOutput = true;
-		} else if (arg[0] == '-') {
+                } else if (arg[0] == '-') {
 			stderr.writef("error: unknown option '%s'\n", arg);
 			stderr.writeln(HELP);
 			exit(1);
diff --git a/src/sort.d b/src/sort.d
@@ -10,6 +10,8 @@ import std.stdio : File, stderr;
 import std.string : strip, stripLeft;
 import std.traits : isIterable;
 import std.typecons : Yes;
+import std.conv : to;
+import std.uni : asLowerCase;
 
 /// the pattern to determinate a line is an import or not
 enum PATTERN = ctRegex!`^(\s*)(?:(public|static)\s+)?import\s+(?:(\w+)\s*=\s*)?([a-zA-Z._]+)\s*(:\s*\w+(?:\s*=\s*\w+)?(?:\s*,\s*\w+(?:\s*=\s*\w+)?)*)?\s*;[ \t]*([\n\r]*)$`;
@@ -30,6 +32,9 @@ struct SortConfig {
 
 	/// merges imports of the same source
 	bool merge = false;
+
+	/// ignore case when sorting
+	bool ignoreCase = false;
 }
 
 /// helper-struct for identifiers and its bindings
@@ -92,6 +97,11 @@ struct Import {
 	}
 }
 
+bool less(SortConfig config, string a, string b)
+{
+    return config.ignoreCase ? a.asLowerCase.to!string < b.asLowerCase.to!string : a < b;
+}
+
 /// write import-statements to `outfile` with `config`
 void writeImports(File outfile, SortConfig config, Import[] matches) {
 	if (!matches)
@@ -112,7 +122,7 @@ void writeImports(File outfile, SortConfig config, Import[] matches) {
 		}
 	}
 
-	matches.sort!((a, b) => a.sortBy < b.sortBy);
+	matches.sort!((a, b) => less(config, a.sortBy, b.sortBy));
 	bool first;
 
 	foreach (m; matches) {
@@ -203,7 +213,7 @@ void sortImports(File infile, File outfile, SortConfig config) {
 						im.idents ~= Identifier(config.byBinding, id.strip);
 					}
 				}
-				im.idents.sort!((a, b) => a.sortBy < b.sortBy);
+				im.idents.sort!((a, b) => less(config, a.sortBy, b.sortBy));
 			}
 			matches ~= im;
 		} else {