mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-21 23:00:43 -08:00
Utils: generate solution and project files
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using static System.IO.Path;
|
||||||
|
|
||||||
namespace DotnetUtils;
|
namespace DotnetUtils;
|
||||||
|
|
||||||
@@ -18,10 +19,7 @@ public static class Extensions {
|
|||||||
rootPath.IsNullOrWhitespace()
|
rootPath.IsNullOrWhitespace()
|
||||||
) { return path; }
|
) { return path; }
|
||||||
|
|
||||||
var path1 = path.TrimEnd('\\');
|
path = path.TrimEnd('\\'); // remove trailing backslash, if present
|
||||||
rootPath = rootPath.TrimEnd('\\');
|
return GetRelativePath(rootPath, path.TrimEnd('\\'));
|
||||||
if (!path1.StartsWith(rootPath, StringComparison.InvariantCultureIgnoreCase)) { return path; }
|
|
||||||
|
|
||||||
return path1[(rootPath.Length + 1)..]; // ignore the initial /
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
00_Utilities/DotnetUtils/DotnetUtils/Methods.cs
Normal file
56
00_Utilities/DotnetUtils/DotnetUtils/Methods.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace DotnetUtils;
|
||||||
|
|
||||||
|
public static class Methods {
|
||||||
|
public static ProcessResult RunProcess(string filename, string arguments) {
|
||||||
|
var process = new Process() {
|
||||||
|
StartInfo = {
|
||||||
|
FileName = filename,
|
||||||
|
Arguments = arguments,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
},
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
return RunProcess(process);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ProcessResult RunProcess(Process process, string input = "") {
|
||||||
|
var (output, error) = ("", "");
|
||||||
|
var (redirectOut, redirectErr) = (
|
||||||
|
process.StartInfo.RedirectStandardOutput,
|
||||||
|
process.StartInfo.RedirectStandardError
|
||||||
|
);
|
||||||
|
if (redirectOut) {
|
||||||
|
process.OutputDataReceived += (s, ea) => output += ea.Data + "\n";
|
||||||
|
}
|
||||||
|
if (redirectErr) {
|
||||||
|
process.ErrorDataReceived += (s, ea) => error += ea.Data + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.Start()) {
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (redirectOut) { process.BeginOutputReadLine(); }
|
||||||
|
if (redirectErr) { process.BeginErrorReadLine(); }
|
||||||
|
if (!string.IsNullOrEmpty(input)) {
|
||||||
|
process.StandardInput.WriteLine(input);
|
||||||
|
process.StandardInput.Close();
|
||||||
|
}
|
||||||
|
process.WaitForExit();
|
||||||
|
return new ProcessResult(process.ExitCode, output, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed record ProcessResult(int ExitCode, string StdOut, string StdErr) {
|
||||||
|
public override string? ToString() =>
|
||||||
|
StdOut +
|
||||||
|
(StdOut is not (null or "") && ExitCode > 0 ? "\n" : "") +
|
||||||
|
(ExitCode > 0 ?
|
||||||
|
$"{ExitCode}\n{StdErr}" :
|
||||||
|
"");
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Reflection;
|
using static System.IO.Directory;
|
||||||
using static System.IO.Directory;
|
|
||||||
using static System.IO.Path;
|
using static System.IO.Path;
|
||||||
using static DotnetUtils.Globals;
|
using static DotnetUtils.Globals;
|
||||||
|
|
||||||
@@ -17,6 +16,14 @@ public record PortInfo(
|
|||||||
MatchCasing = MatchCasing.CaseInsensitive
|
MatchCasing = MatchCasing.CaseInsensitive
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// .NET namespaces cannot have a digit as the first character
|
||||||
|
// For games whose name starts with a digit, we map the name to a specific string
|
||||||
|
private static readonly Dictionary<string, string> specialGameNames = new() {
|
||||||
|
{ "3-D_Plot", "ThreeDPlot" },
|
||||||
|
{ "3-D_Tic-Tac-Toe", "ThreeDTicTacToe" },
|
||||||
|
{ "23_Matches", "TwentyThreeMatches"}
|
||||||
|
};
|
||||||
|
|
||||||
public static PortInfo? Create(string fullPath, string langKeyword) {
|
public static PortInfo? Create(string fullPath, string langKeyword) {
|
||||||
var folderName = GetFileName(fullPath);
|
var folderName = GetFileName(fullPath);
|
||||||
var parts = folderName.Split('_', 2);
|
var parts = folderName.Split('_', 2);
|
||||||
@@ -27,9 +34,11 @@ public record PortInfo(
|
|||||||
(int?)null;
|
(int?)null;
|
||||||
|
|
||||||
var gameName =
|
var gameName =
|
||||||
parts.Length > 1 ?
|
parts.Length == 0 ?
|
||||||
parts[1].Replace("_", "") :
|
null :
|
||||||
null;
|
specialGameNames.TryGetValue(parts[1], out var specialName) ?
|
||||||
|
specialName :
|
||||||
|
parts[1].Replace("_", "").Replace("-", "");
|
||||||
|
|
||||||
if (index is 0 or null || gameName is null) { return null; }
|
if (index is 0 or null || gameName is null) { return null; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using DotnetUtils;
|
using System.Diagnostics;
|
||||||
|
using DotnetUtils;
|
||||||
using static System.Console;
|
using static System.Console;
|
||||||
using static System.IO.Path;
|
using static System.IO.Path;
|
||||||
|
using static DotnetUtils.Methods;
|
||||||
|
|
||||||
var infos = PortInfos.Get;
|
var infos = PortInfos.Get;
|
||||||
|
|
||||||
@@ -11,7 +13,10 @@ var actions = new (Action action, string description)[] {
|
|||||||
(multipleSlns, "Output multiple sln files"),
|
(multipleSlns, "Output multiple sln files"),
|
||||||
(missingProj, "Output missing project file"),
|
(missingProj, "Output missing project file"),
|
||||||
(unexpectedProjName, "Output misnamed project files"),
|
(unexpectedProjName, "Output misnamed project files"),
|
||||||
(multipleProjs, "Output multiple project files")
|
(multipleProjs, "Output multiple project files"),
|
||||||
|
|
||||||
|
(generateMissingSlns, "Generate solution files when missing"),
|
||||||
|
(generateMissingProjs, "Generate project files when missing")
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var (_, description, index) in actions.WithIndex()) {
|
foreach (var (_, description, index) in actions.WithIndex()) {
|
||||||
@@ -159,8 +164,52 @@ void multipleProjs() {
|
|||||||
WriteLine(item.LangPath);
|
WriteLine(item.LangPath);
|
||||||
WriteLine();
|
WriteLine();
|
||||||
printProjs(item);
|
printProjs(item);
|
||||||
|
|
||||||
}
|
}
|
||||||
WriteLine();
|
WriteLine();
|
||||||
WriteLine($"Count: {data.Length}");
|
WriteLine($"Count: {data.Length}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void generateMissingSlns() {
|
||||||
|
foreach (var item in infos.Where(x => !x.Slns.Any())) {
|
||||||
|
var result = RunProcess("dotnet", $"new sln -n {item.GameName} -o {item.LangPath}");
|
||||||
|
WriteLine(result);
|
||||||
|
|
||||||
|
var slnFullPath = Combine(item.LangPath, $"{item.GameName}.sln");
|
||||||
|
foreach (var proj in item.Projs) {
|
||||||
|
result = RunProcess("dotnet", $"sln {slnFullPath} add {proj}");
|
||||||
|
WriteLine(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateMissingProjs() {
|
||||||
|
foreach (var item in infos.Where(x => !x.Projs.Any())) {
|
||||||
|
var (langArg, langVersion) = item.Lang switch {
|
||||||
|
"csharp" => ("\"C#\"", 10),
|
||||||
|
"vbnet" => ("\"VB\"", 16.9),
|
||||||
|
_ => throw new InvalidOperationException()
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = RunProcess("dotnet", $"new console --language {langArg} --name {item.GameName}.{item.ProjExt} -o {item.LangPath} -f net6.0 --langversion {langVersion}");
|
||||||
|
WriteLine(result);
|
||||||
|
|
||||||
|
var projFullPath = Combine(item.LangPath, $"{item.GameName}.{item.ProjExt}");
|
||||||
|
if (item.Slns.Length == 1) {
|
||||||
|
result = RunProcess("dotnet", $"sln {item.Slns[0]} add {projFullPath}");
|
||||||
|
WriteLine(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkProjects() {
|
||||||
|
// warn if project files do not:
|
||||||
|
// target .NET 6
|
||||||
|
// implicit using
|
||||||
|
// nullable enable
|
||||||
|
// warn if none og the projects have:
|
||||||
|
// output type exe
|
||||||
|
}
|
||||||
|
|
||||||
|
void tryBuild() {
|
||||||
|
// if has code files, try to build
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user