Replaced scripting system with plugin system
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
using System.CommandLine;
|
||||
|
||||
namespace MycroForge.CLI.Commands.Interfaces;
|
||||
|
||||
public interface ISubCommandOf<T> where T : Command
|
||||
{
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user