Skip to content

Commit 0b6a982

Browse files
committed
help command & small refactorings
1 parent fecc1f0 commit 0b6a982

File tree

11 files changed

+190
-73
lines changed

11 files changed

+190
-73
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ csharp_style_expression_bodied_methods = when_on_single_line
2323

2424
# IDE0023: Use block body for conversion operator
2525
csharp_style_expression_bodied_operators = when_on_single_line
26+
27+
# CA2201: Do not raise reserved exception types
28+
dotnet_diagnostic.CA2201.severity = none

Program.cs

Lines changed: 81 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,138 @@
1-
namespace MMM;
1+
#pragma warning disable CS0162
2+
#pragma warning disable IDE0060
3+
4+
namespace MMM;
25

36
public static class Program
47
{
58
public static void Main(string[] args)
9+
{
10+
CancellationTokenSource cts = new();
11+
Console.CancelKeyPress += (sender, e) =>
12+
{
13+
cts.Cancel();
14+
};
15+
16+
using Task task = Run(args, cts.Token);
17+
18+
while (!task.IsCompleted)
19+
{
20+
Thread.Yield();
21+
}
22+
23+
if (task.Exception is not null)
24+
{
25+
Log.Error(task.Exception);
26+
}
27+
}
28+
29+
static async Task Run(string[] args, CancellationToken ct)
630
{
731
if (!File.Exists(Context.ModlistPath))
832
{
9-
Log.Error($"No package.json found");
10-
return;
33+
throw new ApplicationArgumentsException($"No package.json found");
1134
}
1235

1336
if (args.Length == 0)
1437
{
15-
Log.Error($"No arguments passed");
38+
Help.PrintHelp(null);
1639
return;
1740
}
1841

19-
CancellationTokenSource cts = new();
20-
Console.CancelKeyPress += (sender, e) =>
21-
{
22-
cts.Cancel();
23-
};
24-
Task task;
25-
2642
switch (args[0])
2743
{
2844
case "update":
45+
if (args.ContainsAny("--help", "-h"))
46+
{
47+
Help.PrintHelp(args[0]);
48+
break;
49+
}
50+
2951
if (args.Length != 1)
3052
{
31-
Log.Error($"Wrong number of arguments passed");
32-
return;
53+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
3354
}
3455

35-
task = Actions.Update.PerformUpdate(cts.Token);
56+
await Actions.Update.PerformUpdate(ct);
3657
break;
3758
case "check":
59+
if (args.ContainsAny("--help", "-h"))
60+
{
61+
Help.PrintHelp(args[0]);
62+
break;
63+
}
64+
3865
if (args.Length != 1)
3966
{
40-
Log.Error($"Wrong number of arguments passed");
41-
return;
67+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
4268
}
4369

44-
task = Actions.Check.PerformCheck(cts.Token);
70+
await Actions.Check.PerformCheck(ct);
4571
break;
4672
case "add":
73+
if (args.ContainsAny("--help", "-h"))
74+
{
75+
Help.PrintHelp(args[0]);
76+
break;
77+
}
78+
4779
if (args.Length < 2)
4880
{
49-
Log.Error($"Wrong number of arguments passed");
50-
return;
81+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
5182
}
5283

53-
task = Actions.Add.PerformAdd(args[1..], cts.Token);
84+
await Actions.Add.PerformAdd(args[1..], ct);
5485
break;
5586
case "remove":
87+
if (args.ContainsAny("--help", "-h"))
88+
{
89+
Help.PrintHelp(args[0]);
90+
break;
91+
}
92+
5693
if (args.Length < 2)
5794
{
58-
Log.Error($"Wrong number of arguments passed");
59-
return;
95+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
6096
}
6197

62-
task = Actions.Remove.PerformRemove(args[1..], cts.Token);
98+
await Actions.Remove.PerformRemove(args[1..], ct);
6399
break;
64100
case "list":
101+
if (args.ContainsAny("--help", "-h"))
102+
{
103+
Help.PrintHelp(args[0]);
104+
break;
105+
}
106+
65107
if (args.Length != 1)
66108
{
67-
Log.Error($"Wrong number of arguments passed");
68-
return;
109+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
69110
}
70111

71-
task = Actions.List.PerformList(cts.Token);
112+
await Actions.List.PerformList(ct);
72113
break;
73114
case "change":
115+
if (args.ContainsAny("--help", "-h"))
116+
{
117+
Help.PrintHelp(args[0]);
118+
break;
119+
}
120+
74121
if (args.Length != 2)
75122
{
76-
Log.Error($"Wrong number of arguments passed");
77-
return;
123+
throw new ApplicationArgumentsException($"Wrong number of arguments passed");
78124
}
79125

80-
task = Actions.Change.PerformChange(args[1], cts.Token);
126+
await Actions.Change.PerformChange(args[1], ct);
81127
break;
82128
default:
83-
Log.Error($"Invalid action {args[0]}");
84-
return;
85-
}
129+
if (args.ContainsAny("--help", "-h"))
130+
{
131+
Help.PrintHelp(null);
132+
break;
133+
}
86134

87-
using (task)
88-
{
89-
while (!task.IsCompleted)
90-
{
91-
Thread.Yield();
92-
}
93-
94-
if (task.Exception is not null)
95-
{
96-
Log.Error(task.Exception);
97-
}
135+
throw new ApplicationArgumentsException($"Invalid action {args[0]}");
98136
}
99137
}
100138
}

Source/Exceptions/Arguments.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace MMM;
2+
3+
public class ApplicationArgumentsException(string message, Exception? inner = null) : ApplicationException(message, inner);

Source/Help.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
static class Help
2+
{
3+
public static void PrintHelp(string? action)
4+
{
5+
switch (action)
6+
{
7+
case "update":
8+
Console.WriteLine($"mmm {action}");
9+
Console.WriteLine();
10+
Console.WriteLine($"Checks for updates and downloads the newer versions.");
11+
break;
12+
case "add":
13+
Console.WriteLine($"mmm {action} id <id>");
14+
Console.WriteLine();
15+
Console.WriteLine($"Adds the mod with the specified Modrinth id.");
16+
break;
17+
case "remove":
18+
Console.WriteLine($"mmm {action} id <id|name>");
19+
Console.WriteLine();
20+
Console.WriteLine($"Removes the mod with the specified Modrinth id, display name (ie. Fabric API) or id (ie. fabric-api).");
21+
break;
22+
case "check":
23+
Console.WriteLine($"mmm {action} id <id>");
24+
Console.WriteLine();
25+
Console.WriteLine($"Checks for dependencies and conflicts, and tries to download the missing mods. And also checks the validity of the lock-file. (untracked/missing files)");
26+
break;
27+
case "change":
28+
Console.WriteLine($"mmm {action} id <version>");
29+
Console.WriteLine();
30+
Console.WriteLine($"Replaces all the mods with the specified Minecraft version. (unsupported mods will be deleted)");
31+
break;
32+
case null:
33+
Console.WriteLine($"mmm [update|add|remove|check] [-h|--help]");
34+
break;
35+
}
36+
}
37+
}

Source/ModReader.cs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,12 @@ public static class ModReader
99
{
1010
static async Task<FabricMod> ReadMod(ZipArchive archive, string filename, CancellationToken ct)
1111
{
12-
string text;
13-
12+
try
1413
{
1514
ZipArchiveEntry fabricMod = archive.GetEntry("fabric.mod.json") ?? throw new ModLoadException($"File {Path.GetFileName(filename)} is not a fabric mod");
1615
using Stream stream = await fabricMod.OpenAsync(ct);
1716
using StreamReader reader = new(stream);
18-
text = reader.ReadToEnd();
19-
}
20-
21-
try
22-
{
17+
string text = reader.ReadToEnd();
2318
return JsonSerializer.Deserialize(Utils.SanitizeJson(text), FabricModJsonSerializerContext.Default.FabricMod)!;
2419
}
2520
catch (JsonException e)

Source/Models/Fabric/Items.cs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55

66
namespace MMM.Fabric;
77

8-
public class Items<T>
8+
public abstract class Items<T> : IEnumerable<T>
99
{
10-
10+
public abstract IEnumerator<T> GetEnumerator();
11+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
1112
}
1213

1314
public class SingleItem<T>(T item) : Items<T>
@@ -16,6 +17,11 @@ public class SingleItem<T>(T item) : Items<T>
1617

1718
public static implicit operator T(SingleItem<T> v) => v.Item;
1819

20+
public override IEnumerator<T> GetEnumerator()
21+
{
22+
yield return item;
23+
}
24+
1925
public override string? ToString() => (item ?? throw new NullReferenceException()).ToString();
2026
public override bool Equals(object? obj)
2127
{
@@ -41,7 +47,7 @@ public T this[int index]
4147
public void Clear() => items.Clear();
4248
public bool Contains(T item) => items.Contains(item);
4349
public void CopyTo(T[] array, int arrayIndex) => items.CopyTo(array, arrayIndex);
44-
public IEnumerator<T> GetEnumerator() => items.GetEnumerator();
50+
public override IEnumerator<T> GetEnumerator() => items.GetEnumerator();
4551
public int IndexOf(T item) => items.IndexOf(item);
4652
public void Insert(int index, T item) => items.Insert(index, item);
4753
public bool Remove(T item) => items.Remove(item);
@@ -53,33 +59,22 @@ public T this[int index]
5359
public override int GetHashCode() => items.GetHashCode();
5460
}
5561

62+
[JsonConverter(typeof(ItemsJsonConverter<>))]
5663
public class ItemsJsonConverter<T> : JsonConverter<Items<T>>
5764
{
5865
public override Items<T> Read(
5966
ref Utf8JsonReader reader,
6067
Type typeToConvert,
6168
JsonSerializerOptions options)
6269
{
63-
reader.SkipJunk();
64-
if (reader.TokenType == JsonTokenType.StartArray)
70+
JsonDocument doc = JsonDocument.ParseValue(ref reader);
71+
if (doc.RootElement.ValueKind == JsonValueKind.Array)
6572
{
66-
reader.Read();
67-
List<T> items = [];
68-
while (reader.TokenType != JsonTokenType.EndArray)
69-
{
70-
reader.SkipJunk();
71-
if (reader.TokenType == JsonTokenType.EndArray)
72-
{
73-
reader.Read();
74-
break;
75-
}
76-
items.Add(JsonSerializer.Deserialize<T>(ref reader, options) ?? throw new JsonException());
77-
}
78-
return new MultipleItems<T>(items);
73+
return new MultipleItems<T>([.. doc.RootElement.EnumerateArray().Select(v => v.Deserialize<T>(options) ?? throw new JsonException())]);
7974
}
8075
else
8176
{
82-
return new SingleItem<T>(JsonSerializer.Deserialize<T>(ref reader, options) ?? throw new JsonException());
77+
return new SingleItem<T>(doc.Deserialize<T>(options) ?? throw new JsonException());
8378
}
8479
}
8580

@@ -91,7 +86,7 @@ public override void Write(
9186
switch (value)
9287
{
9388
case SingleItem<T> single:
94-
writer.WriteStringValue(single.ToString());
89+
JsonSerializer.Serialize(writer, single.Item, options);
9590
break;
9691
case MultipleItems<T> multiple:
9792
writer.WriteStartArray();

Source/Utils/Logger/Interactive.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
namespace MMM;
33

4-
static partial class Log
4+
public static partial class Log
55
{
66
public static bool AskYesNo(string question, bool? defaultValue = null)
77
{

Source/Utils/Logger/LogEntry.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace MMM;
44

5-
readonly struct LogEntry(string text) : IAdditionOperators<LogEntry, LogEntry, LogEntry>, IEquatable<LogEntry>
5+
public readonly struct LogEntry(string text) : IAdditionOperators<LogEntry, LogEntry, LogEntry>, IEquatable<LogEntry>
66
{
77
readonly string _text = text;
88

@@ -47,4 +47,7 @@ public void Back()
4747
public static implicit operator LogEntry(string? v) => new(v ?? string.Empty);
4848

4949
public override int GetHashCode() => _text.GetHashCode();
50+
51+
public static bool operator ==(LogEntry left, LogEntry right) => left.Equals(right);
52+
public static bool operator !=(LogEntry left, LogEntry right) => !left.Equals(right);
5053
}

Source/Utils/Logger/Print.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace MMM;
33
static partial class Log
44
{
55
static LogEntry LastLogEntry;
6-
public static List<Lock> InteractiveLocks = [];
6+
internal static List<Lock> InteractiveLocks = [];
77

88
readonly struct AutoScope : IDisposable
99
{

Source/Utils/Logger/Progress.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,31 @@
22

33
namespace MMM;
44

5+
public static class ProgressExtensions
6+
{
7+
public static IEnumerable<T> WithProgress<T>(this IReadOnlyCollection<T> collection, ProgressBar progressBar, string title)
8+
{
9+
int current = 0;
10+
int total = collection.Count;
11+
foreach (T item in collection)
12+
{
13+
progressBar.Report(title, current++, total);
14+
yield return item;
15+
}
16+
}
17+
18+
public static IEnumerable<T> WithProgress<T>(this IReadOnlyCollection<T> collection, ProgressBar progressBar)
19+
{
20+
int current = 0;
21+
int total = collection.Count;
22+
foreach (T item in collection)
23+
{
24+
progressBar.Report(current++, total);
25+
yield return item;
26+
}
27+
}
28+
}
29+
530
public class ProgressBar : IDisposable, IProgress<float>
631
{
732
static readonly TimeSpan AnimationInterval = TimeSpan.FromSeconds(1.0 / 8);

0 commit comments

Comments
 (0)