Hermod
A cross-platform, modular and fully GDPR-compliant email archival solution!
Loading...
Searching...
No Matches
Hermod.Commands.cs
Go to the documentation of this file.
1using System;
2
3namespace Hermod {
4
5 using Core.Commands;
6 using Core.Commands.Results;
7 using PluginFramework;
8
9 using System.Text;
10
11 public partial class Hermod {
12
13 private bool TryGetCommand(string cmdName, out ICommand? outCommand) {
14 bool Predicate(ICommand x) => x.Name.Equals(cmdName, StringComparison.CurrentCulture);
15
16 // built-ins have priority
17 outCommand = Commands.FirstOrDefault(Predicate);
18
19 if (outCommand != null) { return true; }
20
21 foreach (var plugin in PluginRegistry.Instance.Plugins) {
22 outCommand = plugin.PluginCommands.FirstOrDefault(Predicate);
23
24 if (outCommand != null) {
25 return true;
26 }
27 }
28
29 return false;
30 }
31
32 List<ICommand> Commands => m_commands ??= new List<ICommand> {
34 "clear", "Clears the terminal of any text",
35 "Clears the internal buffers of the terminal.",
36 x => { Console.Clear(); return CommandResult.Empty; }
37 ),
39 "quit", "Gracefully terminates Hermod.",
40 "Unloads all plugins, shuts down internal services,\n" +
41 "and gracfully shuts Hermod down. Useful for maintenance.",
42 x => { m_keepAlive = false; return CommandResult.Empty; }
43 ),
45 "help", "Displays a help text",
46 "Prints general help about all commands found\n" +
47 "in Hermod and any loaded plugins.\n" +
48 "Type help <command> for detailled information.",
49 HandleDisplayHelp
50 ),
52 "load-plugin", "Loads one or more plugins",
53 "Loads one or more plugins from disk and places\n" +
54 "them in the application's namespace.\n" +
55 "Usage:\n" +
56 "\tload-plugin <plugin-file [<plugin-file>]>",
57 HandleLoadPlugin
58 ),
60 "unload-plugin", "Unloads one or more plugins from Hermod",
61 "Unloads one or more plugins from Hermod's namespace.\n" +
62 "Plugins are gracefully stopped before being unloaded.\n" +
63 "Usage:\n" +
64 "\tunload-plugin <plugin-name> # unload a single plugin\n" +
65 "\tunload-plugin <plugin-name [<plugin-name>]> # unload multiple plugins\n" +
66 "\tunload-plugin --all, -a # unload all plugins",
67 HandleUnloadPlugin,
68 new getopt.net.Option { Name = "all", ArgumentType = getopt.net.ArgumentType.None, Value = 'a' }
69 )
70 };
71
72 private ICommandResult HandleDisplayHelp(params string[] args) {
73 if (args.Length > 0) { return HandleDisplayCommandHelp(args.First()); }
74
75 var sBuilder = new StringBuilder();
76
77 void DumpCommandShortHelp(ICommand command) {
78 sBuilder.AppendLine($"{ command.Name,-30 }{ command.ShortDescription,-80 }");
79 }
80
81 sBuilder.AppendLine("Built-ins:");
82
83 foreach (var command in Commands) {
84 DumpCommandShortHelp(command);
85 }
86 sBuilder.AppendLine();
87
88 sBuilder.AppendLine("Plugin provided:");
89 foreach (var plugin in PluginRegistry.Instance.Plugins) {
90 sBuilder.AppendLine($"{ plugin.PluginName }:");
91 foreach (var command in plugin.PluginCommands) {
92 DumpCommandShortHelp(command);
93 }
94 sBuilder.AppendLine();
95 }
96
97 return new CommandResult(sBuilder.ToString(), null);
98 }
99
101 var command =
103 .FirstOrDefault(c => c.Name.Equals(arg, StringComparison.InvariantCulture));
104 if (command is null) {
105 return new CommandErrorResult($"Command \"{ arg }\" doesn't exist!");
106 }
107
108 return new CommandResult(command.LongDescription, null);
109 }
110
111 private ICommandResult HandleLoadPlugin(params string[] args) {
112 if (args.Length == 0) {
113 return new CommandErrorResult("Missing input parameters!", new ArgumentNullException(nameof(args), "Input args must not be null or empty!"));
114 }
115
116 foreach (var arg in args) {
117 if (string.IsNullOrEmpty(arg)) {
118 m_appLogger.Warning($"Encountered empty argument in { nameof(HandleLoadPlugin) }. Ignoring...");
119 continue;
120 }
121
122 try {
123 var fInfo = new FileInfo(arg);
126 } catch (Exception ex) {
127 return new CommandErrorResult("Failed to load one or more plugins!", ex);
128 }
129 }
130
131 return new CommandResult($"Successfully loaded plugin(s).", null);
132 }
133
134 private ICommandResult HandleUnloadPlugin(params string[] args) {
135 return new CommandErrorResult("This command has not yet been implemented!");
136 }
137
138 private ICommandResult HandleGetPlugins(params string[] args) {
139 var sBuilder = new StringBuilder();
140 PluginRegistry.Instance.Plugins
141 .Select(x => $"{ x.PluginName } v{ x.PluginVersion }")
142 .ToList()
143 .ForEach(x => sBuilder.AppendLine(x));
144
145 return new CommandResult(sBuilder.ToString(), null);
146 }
147
148 }
149}
150
A ICommandResult which implicates the command encountered an error.
The most basic of CommandResult implementations.
Definition: CommandResult.cs:8
static CommandResult Empty
Provides an empty CommandResult for commands which do not require a result.
Represents a single command that can only be executed on the (interactive) terminal.
ICommandResult HandleUnloadPlugin(params string[] args)
ICommandResult HandleDisplayHelp(params string[] args)
ICommandResult HandleGetPlugins(params string[] args)
ICommandResult HandleDisplayCommandHelp(string arg)
ICommandResult HandleLoadPlugin(params string[] args)
bool TryGetCommand(string cmdName, out ICommand? outCommand)
Handles the loading, unloading, and general management of plugins.
List< IPlugin > Plugins
Gets a list of all loaded IPlugin instances.
IPlugin? LastRegisteredPlugin
Gets or sets the last IPlugin to be registered.
void LoadPlugin(FileInfo pluginFile)
Loads one or plugins from an Assembly on disk.
static PluginRegistry Instance
Gets the current instance of this object.
List< ICommand > GetAllCommands()
Gets a list containing all ICommand instances known to the application at the current time.
Specialised variation of ICommand with generic typing.
Definition: ICommand.cs:49
string Name
The (callable) name for the command.
Definition: ICommand.cs:14
A generic, object-based variation of ICommandResult<T>.
void OnStart()
Method that is called once Hermod has completed its startup procedures and is ready to run.