Replaced scripting system with plugin system
This commit is contained in:
parent
96b74e6048
commit
3829eb0d7f
@ -1,5 +1,6 @@
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
using MycroForge.Core.CodeGen;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
public class DbEnvInitializer
|
||||
{
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
using MycroForge.Core.CodeGen;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
public class DbEnvModifier
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Humanizer;
|
||||
using MycroForge.Core.CodeGen;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Humanizer;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
using MycroForge.Core.CodeGen;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
public class MainModifier
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using Humanizer;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.CodeGen;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
using System.CommandLine;
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
using System.CommandLine;
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.CodeGen;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.CodeGen;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.CodeGen;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
using System.CommandLine;
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
using MycroForge.CLI.Features;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
@ -95,7 +96,7 @@ public partial class MycroForge
|
||||
|
||||
// Create the project directory and change the directory for the ProjectContext
|
||||
var projectRoot = await CreateDirectory(name);
|
||||
_context.ChangeDirectory(projectRoot);
|
||||
_context.ChangeRootDirectory(projectRoot);
|
||||
|
||||
// Create the config file and initialize the config
|
||||
await _context.CreateFile("m4g.json", "{}");
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
68
MycroForge.CLI/Commands/MycroForge.Plugin.Install.cs
Normal file
68
MycroForge.CLI/Commands/MycroForge.Plugin.Install.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System.CommandLine;
|
||||
using Humanizer;
|
||||
using Microsoft.Extensions.FileSystemGlobbing;
|
||||
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Plugin
|
||||
{
|
||||
public class Install : Command, ISubCommandOf<Plugin>
|
||||
{
|
||||
public enum TargetPlatform
|
||||
{
|
||||
linux_arm,
|
||||
linux_arm64,
|
||||
linux_x64,
|
||||
osx_arm64,
|
||||
osx_x64,
|
||||
}
|
||||
|
||||
private static readonly Option<TargetPlatform> PlatformOption = new(
|
||||
aliases: ["-p", "--platform"],
|
||||
description: "The platform to target when building the plugin"
|
||||
) { IsRequired = true };
|
||||
|
||||
private readonly ProjectContext _context;
|
||||
|
||||
public Install(ProjectContext context) : base("install", "Install a plugin")
|
||||
{
|
||||
_context = context;
|
||||
AddAlias("i");
|
||||
AddOption(PlatformOption);
|
||||
this.SetHandler(ExecuteAsync, PlatformOption);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(TargetPlatform target)
|
||||
{
|
||||
var assemblyName = GetAssemblyName();
|
||||
var pluginInstallPath = Path.Join(Plugins.RootDirectory, assemblyName);
|
||||
var platform = target.ToString().Dasherize();
|
||||
await _context.Bash($"dotnet publish -c Release -r {platform} --output {pluginInstallPath}");
|
||||
Console.WriteLine($"Successfully installed plugin {assemblyName}");
|
||||
|
||||
}
|
||||
|
||||
private string GetAssemblyName()
|
||||
{
|
||||
var matcher = new Matcher().AddInclude("*.csproj");
|
||||
var currentDirectory = Environment.CurrentDirectory;
|
||||
|
||||
var result = matcher.Execute(
|
||||
new DirectoryInfoWrapper(
|
||||
new DirectoryInfo(currentDirectory)
|
||||
)
|
||||
);
|
||||
|
||||
if (!result.HasMatches)
|
||||
throw new Exception($"Could not find .csproj file in directory {currentDirectory}");
|
||||
|
||||
return Path.GetFileNameWithoutExtension(result.Files.First().Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
MycroForge.CLI/Commands/MycroForge.Plugin.List.cs
Normal file
26
MycroForge.CLI/Commands/MycroForge.Plugin.List.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Plugin
|
||||
{
|
||||
public class List : Command, ISubCommandOf<Plugin>
|
||||
{
|
||||
public List() : base("list", "List all installed plugins")
|
||||
{
|
||||
AddAlias("l");
|
||||
AddAlias("ls");
|
||||
this.SetHandler(ExecuteAsync);
|
||||
}
|
||||
|
||||
private void ExecuteAsync()
|
||||
{
|
||||
foreach (var plugin in Plugins.Loaded)
|
||||
Console.WriteLine($"name: {plugin.Name}, command: {plugin.Command}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
MycroForge.CLI/Commands/MycroForge.Plugin.Uninstall.cs
Normal file
43
MycroForge.CLI/Commands/MycroForge.Plugin.Uninstall.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Plugin
|
||||
{
|
||||
public class Uninstall : Command, ISubCommandOf<Plugin>
|
||||
{
|
||||
private static readonly Argument<IEnumerable<string>> NamesArgument = new(
|
||||
name: "name",
|
||||
description: "The names of the plugins you want to uninstall"
|
||||
);
|
||||
|
||||
public Uninstall() : base("uninstall", "Uninstall a plugin")
|
||||
{
|
||||
AddAlias("u");
|
||||
AddArgument(NamesArgument);
|
||||
this.SetHandler(ExecuteAsync, NamesArgument);
|
||||
}
|
||||
|
||||
private void ExecuteAsync(IEnumerable<string> names)
|
||||
{
|
||||
foreach (var name in names)
|
||||
{
|
||||
var dir = Path.Join(Plugins.RootDirectory, name);
|
||||
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
Console.WriteLine($"Successfully uninstalled plugin {name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Plugin {name} could not be found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
MycroForge.CLI/Commands/MycroForge.Plugin.cs
Normal file
18
MycroForge.CLI/Commands/MycroForge.Plugin.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Plugin : Command, ISubCommandOf<MycroForge>
|
||||
{
|
||||
public Plugin(IEnumerable<ISubCommandOf<Plugin>> commands) :
|
||||
base("plugin", "Plugin related commands")
|
||||
{
|
||||
AddAlias("p");
|
||||
foreach (var command in commands.Cast<Command>())
|
||||
AddCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
using System.CommandLine;
|
||||
using System.Diagnostics;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Script
|
||||
{
|
||||
public class Create : Command, ISubCommandOf<Script>
|
||||
{
|
||||
private static readonly Argument<string> NameArgument =
|
||||
new(name: "name", description: "The name of the script");
|
||||
|
||||
public Create() : base(name: "create", description: "Create a script")
|
||||
{
|
||||
AddArgument(NameArgument);
|
||||
this.SetHandler(ExecuteAsync, NameArgument);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(string name)
|
||||
{
|
||||
var path = await CreateFile(name);
|
||||
await OpenFile(path);
|
||||
}
|
||||
|
||||
private static async Task<string> CreateFile(string? name = null, string fileExtension = "py")
|
||||
{
|
||||
var folder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g"
|
||||
);
|
||||
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
var filePath = Path.Combine(folder, $"{name}.{fileExtension}");
|
||||
|
||||
if (File.Exists(filePath))
|
||||
throw new Exception($"File {filePath} already exists.");
|
||||
|
||||
await File.WriteAllTextAsync(filePath, string.Empty);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
private static async Task OpenFile(string file)
|
||||
{
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "code",
|
||||
Arguments = $"--wait {file}",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
using System.CommandLine;
|
||||
using System.Diagnostics;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Script
|
||||
{
|
||||
public class Edit : Command, ISubCommandOf<Script>
|
||||
{
|
||||
private static readonly Argument<string> NameArgument =
|
||||
new(name: "name", description: "The name of the script");
|
||||
|
||||
public Edit() : base(name: "edit", description: "Edit a script")
|
||||
{
|
||||
AddArgument(NameArgument);
|
||||
this.SetHandler(ExecuteAsync, NameArgument);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync(string name)
|
||||
{
|
||||
await EditFile(name);
|
||||
}
|
||||
|
||||
private static async Task EditFile(string name)
|
||||
{
|
||||
var folder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g"
|
||||
);
|
||||
|
||||
var file = Path.Combine(folder, $"{name}.py");
|
||||
|
||||
if (!File.Exists(file))
|
||||
throw new Exception($"File {file} does not exists.");
|
||||
|
||||
var process = new Process
|
||||
{
|
||||
StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "code",
|
||||
Arguments = $"--wait {file}",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true,
|
||||
}
|
||||
};
|
||||
|
||||
process.Start();
|
||||
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Script
|
||||
{
|
||||
public class List : Command, ISubCommandOf<Script>
|
||||
{
|
||||
public List() : base("list", "Show available scripts")
|
||||
{
|
||||
this.SetHandler(Execute);
|
||||
}
|
||||
|
||||
private void Execute()
|
||||
{
|
||||
var folder = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g"
|
||||
);
|
||||
|
||||
var files = Directory.GetFiles(folder)
|
||||
.Select(Path.GetFileName)
|
||||
.Select(p => p.Replace(".py", ""));
|
||||
|
||||
foreach (var file in files)
|
||||
Console.WriteLine(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
using System.CommandLine;
|
||||
using System.Dynamic;
|
||||
using System.Text;
|
||||
using IronPython.Hosting;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Script
|
||||
{
|
||||
public class Run : Command, ISubCommandOf<Script>
|
||||
{
|
||||
private readonly ProjectContext _context;
|
||||
|
||||
private static readonly Argument<string> NameArgument =
|
||||
new(name: "name", description: "The name of the script");
|
||||
|
||||
private static readonly Argument<IEnumerable<string>> ArgsArgument =
|
||||
new(name: "args", description: "The args to the script");
|
||||
|
||||
public Run(ProjectContext context) : base("run", "Run a script")
|
||||
{
|
||||
_context = context;
|
||||
AddArgument(NameArgument);
|
||||
AddArgument(ArgsArgument);
|
||||
this.SetHandler(ExecuteAsync, NameArgument, ArgsArgument);
|
||||
}
|
||||
|
||||
private void ExecuteAsync(string name, IEnumerable<string> args)
|
||||
{
|
||||
var engine = Python.CreateEngine();
|
||||
using var output = new MemoryStream();
|
||||
using var error = new MemoryStream();
|
||||
engine.Runtime.IO.SetOutput(output, Encoding.Default);
|
||||
engine.Runtime.IO.SetErrorOutput(error, Encoding.Default);
|
||||
|
||||
var scope = engine.CreateScope();
|
||||
scope.SetVariable("args", args.ToArray());
|
||||
scope.SetVariable("context", CreateScriptContext());
|
||||
|
||||
try
|
||||
{
|
||||
var scriptPath = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g", $"{name}.py"
|
||||
);
|
||||
engine.ExecuteFile(scriptPath, scope);
|
||||
|
||||
if (output.Length > 0)
|
||||
Console.WriteLine(Encoding.Default.GetString(output.ToArray()));
|
||||
if (error.Length > 0)
|
||||
Console.WriteLine(Encoding.Default.GetString(error.ToArray()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
engine.Runtime.Shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private dynamic CreateScriptContext()
|
||||
{
|
||||
var createFile = _context.CreateFile;
|
||||
var readFile = _context.ReadFile;
|
||||
var writeFile = _context.WriteFile;
|
||||
var bash = _context.Bash;
|
||||
|
||||
dynamic context = new ExpandoObject();
|
||||
context.create_file = createFile;
|
||||
context.read_file = readFile;
|
||||
context.write_file = writeFile;
|
||||
context.bash = bash;
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge
|
||||
{
|
||||
public partial class Script : Command, ISubCommandOf<MycroForge>
|
||||
{
|
||||
public Script(IEnumerable<ISubCommandOf<Script>> commands) :
|
||||
base("script", "Script related commands")
|
||||
{
|
||||
AddAlias("s");
|
||||
foreach (var command in commands.Cast<Command>())
|
||||
AddCommand(command);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
|
@ -1,16 +1,23 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.Core.Contract;
|
||||
using Core_RootCommand = MycroForge.Core.RootCommand;
|
||||
using RootCommand = MycroForge.Core.RootCommand;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public partial class MycroForge : RootCommand
|
||||
public sealed partial class MycroForge : Core_RootCommand
|
||||
{
|
||||
public override string Name => "m4g";
|
||||
|
||||
public MycroForge(IEnumerable<ISubCommandOf<MycroForge>> commands) :
|
||||
base("The MycroForge CLI tool.")
|
||||
public MycroForge(
|
||||
IEnumerable<ISubCommandOf<MycroForge>> defaults,
|
||||
IEnumerable<ISubCommandOf<RootCommand>> plugins
|
||||
) : base("The MycroForge CLI tool.")
|
||||
{
|
||||
foreach (var command in commands.Cast<Command>())
|
||||
foreach (var command in defaults.Cast<Command>())
|
||||
AddCommand(command);
|
||||
|
||||
foreach (var command in plugins.Cast<Command>())
|
||||
AddCommand(command);
|
||||
}
|
||||
}
|
57
MycroForge.CLI/Commands/Plugins.cs
Normal file
57
MycroForge.CLI/Commands/Plugins.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System.Reflection;
|
||||
using MycroForge.Core.Contract;
|
||||
|
||||
namespace MycroForge.CLI.Commands;
|
||||
|
||||
public static class Plugins
|
||||
{
|
||||
public static readonly string RootDirectory = Path.Join(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g", "plugins"
|
||||
);
|
||||
|
||||
private static readonly List<ICommandPlugin> _loaded = [];
|
||||
public static IReadOnlyList<ICommandPlugin> Loaded => _loaded;
|
||||
|
||||
static Plugins()
|
||||
{
|
||||
if (!Directory.Exists(RootDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(RootDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<ICommandPlugin> Load()
|
||||
{
|
||||
if (_loaded.Count > 0) return _loaded;
|
||||
|
||||
var pluginDirectories = Directory
|
||||
.GetDirectories(RootDirectory)
|
||||
.ToArray();
|
||||
|
||||
foreach (var directory in pluginDirectories)
|
||||
{
|
||||
var dlls = Directory.GetFiles(directory)
|
||||
.Where(file => file.EndsWith(".dll"))
|
||||
.ToArray();
|
||||
|
||||
foreach (var dll in dlls)
|
||||
{
|
||||
var assembly = Assembly.LoadFrom(dll);
|
||||
|
||||
var plugin = assembly.GetTypes()
|
||||
.Where(IsPluginType)
|
||||
.Select(Activator.CreateInstance)
|
||||
.Cast<ICommandPlugin>()
|
||||
.First();
|
||||
|
||||
_loaded.Add(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
return _loaded;
|
||||
}
|
||||
|
||||
private static bool IsPluginType(Type type) =>
|
||||
type is { IsClass: true, IsAbstract: false } &&
|
||||
typeof(ICommandPlugin).IsAssignableFrom(type);
|
||||
}
|
@ -1,19 +1,21 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MycroForge.CLI.Commands.Interfaces;
|
||||
using MycroForge.CLI.Commands;
|
||||
using MycroForge.Core.Contract;
|
||||
using MycroForge.CLI.Features;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Extensions;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection RegisterServices(this IServiceCollection services)
|
||||
public static IServiceCollection RegisterCommandDefaults(this IServiceCollection services)
|
||||
{
|
||||
// Register ProjectContext & features
|
||||
services.AddScoped<ProjectContext>();
|
||||
services.AddScoped<IFeature, Git>();
|
||||
services.AddScoped<IFeature, Api>();
|
||||
services.AddScoped<IFeature, Db>();
|
||||
|
||||
|
||||
// Register "m4g"
|
||||
services.AddScoped<Commands.MycroForge>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Init>();
|
||||
@ -46,13 +48,22 @@ public static class ServiceCollectionExtensions
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Db.Link>, Commands.MycroForge.Db.Link.One>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Db.Link>, Commands.MycroForge.Db.Link.Many>();
|
||||
|
||||
// Register "m4g script"
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Script>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Script>, Commands.MycroForge.Script.Create>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Script>, Commands.MycroForge.Script.List>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Script>, Commands.MycroForge.Script.Edit>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Script>, Commands.MycroForge.Script.Run>();
|
||||
// Register "m4g plugin"
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Plugin>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Plugin>, Commands.MycroForge.Plugin.List>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Plugin>, Commands.MycroForge.Plugin.Install>();
|
||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Plugin>, Commands.MycroForge.Plugin.Uninstall>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection RegisterCommandPlugins(this IServiceCollection services)
|
||||
{
|
||||
var plugins = Plugins.Load();
|
||||
|
||||
foreach (var plugin in plugins)
|
||||
plugin.RegisterServices(services);
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
namespace MycroForge.CLI.Features;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Features;
|
||||
|
||||
public sealed class Api : IFeature
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
using MycroForge.CLI.CodeGen;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Features;
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Features;
|
||||
|
||||
public class Git : IFeature
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace MycroForge.CLI.Features;
|
||||
using MycroForge.Core;
|
||||
|
||||
namespace MycroForge.CLI.Features;
|
||||
|
||||
|
||||
public interface IFeature
|
||||
|
@ -19,9 +19,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="MycroForge.Parsing">
|
||||
<HintPath>bin\Debug\net8.0\MycroForge.Parsing.dll</HintPath>
|
||||
</Reference>
|
||||
<ProjectReference Include="..\MycroForge.Core\MycroForge.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -5,7 +5,13 @@ using Microsoft.Extensions.Hosting;
|
||||
|
||||
using var host = Host
|
||||
.CreateDefaultBuilder()
|
||||
.ConfigureServices((_, services) => services.RegisterServices())
|
||||
.ConfigureServices((_, services) =>
|
||||
{
|
||||
services
|
||||
.RegisterCommandDefaults()
|
||||
.RegisterCommandPlugins()
|
||||
;
|
||||
})
|
||||
.Build();
|
||||
|
||||
try
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
namespace MycroForge.Core.CodeGen;
|
||||
|
||||
public class Source
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace MycroForge.CLI.CodeGen;
|
||||
namespace MycroForge.Core.CodeGen;
|
||||
|
||||
public class SourceMatch
|
||||
{
|
11
MycroForge.Core/Contract/ICommandPlugin.cs
Normal file
11
MycroForge.Core/Contract/ICommandPlugin.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace MycroForge.Core.Contract;
|
||||
|
||||
public interface ICommandPlugin
|
||||
{
|
||||
public string? Name { get; }
|
||||
public string Command { get; }
|
||||
|
||||
public void RegisterServices(IServiceCollection services);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System.CommandLine;
|
||||
|
||||
namespace MycroForge.CLI.Commands.Interfaces;
|
||||
namespace MycroForge.Core.Contract;
|
||||
|
||||
public interface ISubCommandOf<T> where T : Command
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace MycroForge.CLI.Extensions;
|
||||
namespace MycroForge.Core.Extensions;
|
||||
|
||||
public static class ObjectStreamExtensions
|
||||
{
|
||||
@ -11,7 +11,7 @@ public static class ObjectStreamExtensions
|
||||
{
|
||||
using var stream = new MemoryStream();
|
||||
using var reader = new StreamReader(stream);
|
||||
var options = jsonSerializerOptions ?? Shared.DefaultJsonSerializerOptions.Default;
|
||||
var options = jsonSerializerOptions ?? Serialization.DefaultJsonSerializerOptions.Default;
|
||||
|
||||
await JsonSerializer.SerializeAsync(stream, @object, options);
|
||||
stream.Position = 0;
|
@ -1,9 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace MycroForge.CLI;
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public partial class ProjectConfig
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace MycroForge.CLI;
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public partial class ProjectConfig
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace MycroForge.CLI;
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public partial class ProjectConfig
|
||||
{
|
@ -1,9 +1,9 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using Humanizer;
|
||||
using MycroForge.CLI.Extensions;
|
||||
using MycroForge.Core.Extensions;
|
||||
|
||||
namespace MycroForge.CLI;
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public class ProjectContext
|
||||
{
|
||||
@ -19,7 +19,7 @@ public class ProjectContext
|
||||
|
||||
var config = await JsonSerializer.DeserializeAsync<ProjectConfig>(
|
||||
File.OpenRead(ConfigPath),
|
||||
Shared.DefaultJsonSerializerOptions.CamelCasePrettyPrint
|
||||
Serialization.DefaultJsonSerializerOptions.CamelCasePrettyPrint
|
||||
);
|
||||
|
||||
if (config is null)
|
||||
@ -28,7 +28,7 @@ public class ProjectContext
|
||||
return config;
|
||||
}
|
||||
|
||||
public void ChangeDirectory(string path)
|
||||
public void ChangeRootDirectory(string path)
|
||||
{
|
||||
Directory.SetCurrentDirectory(path);
|
||||
RootDirectory = path;
|
||||
@ -125,7 +125,7 @@ public class ProjectContext
|
||||
|
||||
public async Task SaveConfig(ProjectConfig config)
|
||||
{
|
||||
var json = await config.SerializeAsync(Shared.DefaultJsonSerializerOptions.CamelCasePrettyPrint);
|
||||
var json = await config.SerializeAsync(Serialization.DefaultJsonSerializerOptions.CamelCasePrettyPrint);
|
||||
await File.WriteAllTextAsync(ConfigPath, json);
|
||||
}
|
||||
}
|
8
MycroForge.Core/RootCommand.cs
Normal file
8
MycroForge.Core/RootCommand.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public abstract class RootCommand : System.CommandLine.RootCommand
|
||||
{
|
||||
protected RootCommand(string description = "") : base(description)
|
||||
{
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
using System.Text.Json;
|
||||
|
||||
namespace MycroForge.CLI;
|
||||
namespace MycroForge.Core;
|
||||
|
||||
public static class Shared
|
||||
public static class Serialization
|
||||
{
|
||||
public static class DefaultJsonSerializerOptions
|
||||
{
|
6
MycroForge.TestPlugin/Constants.cs
Normal file
6
MycroForge.TestPlugin/Constants.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace MycroForge.TestPlugin;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public const string MainCommandName = "mj";
|
||||
}
|
25
MycroForge.TestPlugin/MyJewelleryCommand.cs
Normal file
25
MycroForge.TestPlugin/MyJewelleryCommand.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.CommandLine;
|
||||
using MycroForge.Core;
|
||||
using MycroForge.Core.Contract;
|
||||
using RootCommand = MycroForge.Core.RootCommand;
|
||||
|
||||
namespace MycroForge.TestPlugin;
|
||||
|
||||
public class MyJewelleryCommand : Command, ISubCommandOf<RootCommand>
|
||||
{
|
||||
private readonly ProjectContext _context;
|
||||
|
||||
public MyJewelleryCommand(ProjectContext context) :
|
||||
base(Constants.MainCommandName, "Custom command for My Jewellery specific stuff")
|
||||
{
|
||||
_context = context;
|
||||
this.SetHandler(ExecuteAsync);
|
||||
}
|
||||
|
||||
private async Task ExecuteAsync()
|
||||
{
|
||||
await _context.CreateFile("hello_world.txt",
|
||||
"My Jewellery command plugin is working!"
|
||||
);
|
||||
}
|
||||
}
|
16
MycroForge.TestPlugin/MyJewelleryCommandPlugin.cs
Normal file
16
MycroForge.TestPlugin/MyJewelleryCommandPlugin.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MycroForge.Core.Contract;
|
||||
using RootCommand = MycroForge.Core.RootCommand;
|
||||
|
||||
namespace MycroForge.TestPlugin;
|
||||
|
||||
public class MyJewelleryCommandPlugin : ICommandPlugin
|
||||
{
|
||||
public string Name => $"{nameof(MycroForge)}.{nameof(TestPlugin)}";
|
||||
public string Command => Constants.MainCommandName;
|
||||
|
||||
public void RegisterServices(IServiceCollection services)
|
||||
{
|
||||
services.AddScoped<ISubCommandOf<RootCommand>, MyJewelleryCommand>();
|
||||
}
|
||||
}
|
13
MycroForge.TestPlugin/MycroForge.TestPlugin.csproj
Normal file
13
MycroForge.TestPlugin/MycroForge.TestPlugin.csproj
Normal file
@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MycroForge.Core\MycroForge.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MycroForge.CLI", "MycroForg
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MycroForge.Core", "MycroForge.Core\MycroForge.Core.csproj", "{CFF8BD4E-520D-4319-BA80-3F49B5F493BA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MycroForge.TestPlugin", "MycroForge.TestPlugin\MycroForge.TestPlugin.csproj", "{7C479E68-98FA-4FBC-B5E4-7116015774B3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -18,5 +20,9 @@ Global
|
||||
{CFF8BD4E-520D-4319-BA80-3F49B5F493BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CFF8BD4E-520D-4319-BA80-3F49B5F493BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CFF8BD4E-520D-4319-BA80-3F49B5F493BA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C479E68-98FA-4FBC-B5E4-7116015774B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C479E68-98FA-4FBC-B5E4-7116015774B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C479E68-98FA-4FBC-B5E4-7116015774B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C479E68-98FA-4FBC-B5E4-7116015774B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
Loading…
Reference in New Issue
Block a user