diff --git a/CMLeonOS.csproj b/CMLeonOS.csproj index 3a69ccd..fd8f5d8 100644 --- a/CMLeonOS.csproj +++ b/CMLeonOS.csproj @@ -15,7 +15,7 @@ False Pipe: Cosmos\Serial Serial: COM1 - HyperV + VMware VMware Use VMware Player or Workstation to deploy and debug. 192.168.0.8 diff --git a/shell/Commands/Environment/EnvCommand.cs b/shell/Commands/Environment/EnvCommand.cs index 93fb17c..60df581 100644 --- a/shell/Commands/Environment/EnvCommand.cs +++ b/shell/Commands/Environment/EnvCommand.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using CMLeonOS; namespace CMLeonOS.Commands.Environment { @@ -11,7 +13,41 @@ namespace CMLeonOS.Commands.Environment if (parts.Length == 0) { - envManager.ListVariables(); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "list", + Description = "List all environment variables", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "see ", + Description = "View environment variable value", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "add ", + Description = "Add environment variable", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "change ", + Description = "Change environment variable", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "delete ", + Description = "Delete environment variable", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("env", commandInfos)); return; } @@ -39,7 +75,7 @@ namespace CMLeonOS.Commands.Environment else { showError("Error: Please specify variable name"); - showError("Usage: env see "); + showError(UsageGenerator.GenerateSimpleUsage("env", "see ")); } break; case "add": @@ -60,7 +96,7 @@ namespace CMLeonOS.Commands.Environment else { showError("Error: Please specify variable name and value"); - showError("Usage: env add "); + showError(UsageGenerator.GenerateSimpleUsage("env", "add ")); } break; case "change": @@ -81,7 +117,7 @@ namespace CMLeonOS.Commands.Environment else { showError("Error: Please specify variable name and value"); - showError("Usage: env change "); + showError(UsageGenerator.GenerateSimpleUsage("env", "change ")); } break; case "delete": @@ -101,12 +137,46 @@ namespace CMLeonOS.Commands.Environment else { showError("Error: Please specify variable name"); - showError("Usage: env delete "); + showError(UsageGenerator.GenerateSimpleUsage("env", "delete ")); } break; default: + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "list", + Description = "List all environment variables", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "see ", + Description = "View environment variable value", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "add ", + Description = "Add environment variable", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "change ", + Description = "Change environment variable", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "delete ", + Description = "Delete environment variable", + IsOptional = false + } + }; + showError("Error: Invalid env command"); - showError("Usage: env [list] | env see | env add | env change | env delete "); + showError(UsageGenerator.GenerateUsage("env", commandInfos)); break; } } diff --git a/shell/Commands/FileSystem/RmCommand.cs b/shell/Commands/FileSystem/RmCommand.cs index 771ce27..2358629 100644 --- a/shell/Commands/FileSystem/RmCommand.cs +++ b/shell/Commands/FileSystem/RmCommand.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using CMLeonOS; namespace CMLeonOS.Commands.FileSystem { @@ -8,7 +10,24 @@ namespace CMLeonOS.Commands.FileSystem { if (string.IsNullOrEmpty(args)) { - showError("Please specify a file name"); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Delete file", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = " -norisk", + Description = "Delete file in sys folder without confirmation", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("rm", commandInfos)); + return; } else { @@ -29,7 +48,7 @@ namespace CMLeonOS.Commands.FileSystem if (!hasNorisk) { showError("Cannot delete files in sys folder without -norisk parameter"); - showError("Usage: rm -norisk"); + showError(UsageGenerator.GenerateSimpleUsage("rm", " -norisk")); } else { diff --git a/shell/Commands/Script/BransweCommand.cs b/shell/Commands/Script/BransweCommand.cs index d7f9142..74af039 100644 --- a/shell/Commands/Script/BransweCommand.cs +++ b/shell/Commands/Script/BransweCommand.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using CMLeonOS; namespace CMLeonOS.Commands.Script { @@ -9,8 +11,17 @@ namespace CMLeonOS.Commands.Script { if (string.IsNullOrEmpty(args)) { - showError("Error: Please specify file name"); - showError("Usage: branswe "); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Execute Branswe file", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("branswe", commandInfos)); return; } diff --git a/shell/Commands/Script/ComCommand.cs b/shell/Commands/Script/ComCommand.cs index 07c6b7b..59499a1 100644 --- a/shell/Commands/Script/ComCommand.cs +++ b/shell/Commands/Script/ComCommand.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using CMLeonOS; namespace CMLeonOS.Commands.Script { @@ -9,7 +11,17 @@ namespace CMLeonOS.Commands.Script { if (string.IsNullOrEmpty(args)) { - showError("Usage: com "); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Execute command file", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("com", commandInfos)); return; } diff --git a/shell/Commands/Script/LuaCommand.cs b/shell/Commands/Script/LuaCommand.cs index b67e463..50c5cf8 100644 --- a/shell/Commands/Script/LuaCommand.cs +++ b/shell/Commands/Script/LuaCommand.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.IO; using UniLua; +using CMLeonOS; namespace CMLeonOS.Commands.Script { @@ -12,8 +14,23 @@ namespace CMLeonOS.Commands.Script if (parts.Length == 0) { - showError("Error: Please specify Lua script file or use --shell for interactive mode"); - showError("Usage: lua or lua --shell"); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Execute Lua script file", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "--shell", + Description = "Enter Lua interactive shell", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("lua", commandInfos)); return; } diff --git a/shell/Commands/User/HostnameCommand.cs b/shell/Commands/User/HostnameCommand.cs index 8851d8c..ab55c4e 100644 --- a/shell/Commands/User/HostnameCommand.cs +++ b/shell/Commands/User/HostnameCommand.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using CMLeonOS; namespace CMLeonOS.Commands.User { @@ -8,7 +10,17 @@ namespace CMLeonOS.Commands.User { if (string.IsNullOrEmpty(args)) { - showError("Usage: hostname "); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "", + Description = "Set new hostname", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("hostname", commandInfos)); return; } diff --git a/shell/Commands/User/UserCommand.cs b/shell/Commands/User/UserCommand.cs index 060842f..2417b35 100644 --- a/shell/Commands/User/UserCommand.cs +++ b/shell/Commands/User/UserCommand.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using CMLeonOS; namespace CMLeonOS.Commands.User { @@ -15,19 +17,41 @@ namespace CMLeonOS.Commands.User { if (userSystem == null || userSystem.CurrentLoggedInUser == null || !userSystem.CurrentLoggedInUser.IsAdmin) { - showError("Error: Only administrators can use the user command."); + showError("Error: Only administrators can use this command."); return; } if (string.IsNullOrEmpty(args)) { - showError("Error: Please specify a user command"); - showError("Please specify a user command"); - showError("user [args]"); - showError(" user add admin - Add admin user"); - showError(" user add user - Add regular user"); - showError(" user delete - Delete user"); - showError(" user list - List all users"); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "add admin ", + Description = "Add admin user", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "add user ", + Description = "Add regular user", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "delete ", + Description = "Delete user", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "list", + Description = "List all users", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateUsage("user", commandInfos)); return; } @@ -35,7 +59,7 @@ namespace CMLeonOS.Commands.User if (parts.Length < 1) { showError("Error: Please specify a user command"); - showError("Usage: user [args]"); + showError(UsageGenerator.GenerateSimpleUsage("user", " [args]")); return; } @@ -46,8 +70,8 @@ namespace CMLeonOS.Commands.User if (parts.Length < 4) { showError("Error: Please specify user type and username and password"); - showError("Usage: user add admin "); - showError("Usage: user add user "); + showError(UsageGenerator.GenerateSimpleUsage("user", "add admin ")); + showError(UsageGenerator.GenerateSimpleUsage("user", "add user ")); return; } @@ -63,7 +87,7 @@ namespace CMLeonOS.Commands.User if (parts.Length < 2) { showError("Error: Please specify username"); - showError("Usage: user delete "); + showError(UsageGenerator.GenerateSimpleUsage("user", "delete ")); return; } diff --git a/shell/Commands/Utility/Base64Command.cs b/shell/Commands/Utility/Base64Command.cs index 351566f..e0dadff 100644 --- a/shell/Commands/Utility/Base64Command.cs +++ b/shell/Commands/Utility/Base64Command.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using CMLeonOS; namespace CMLeonOS.Commands.Utility { @@ -10,8 +12,23 @@ namespace CMLeonOS.Commands.Utility if (parts.Length == 0) { - showError("Error: Please specify subcommand"); - showError("Usage: base64 encrypt | base64 decrypt "); + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "encrypt ", + Description = "Encode text to Base64", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "decrypt ", + Description = "Decode Base64 to text", + IsOptional = false + } + }; + + showError(UsageGenerator.GenerateCompactUsage("base64", commandInfos)); return; } @@ -19,15 +36,31 @@ namespace CMLeonOS.Commands.Utility if (subcommand != "encrypt" && subcommand != "decrypt") { + var commandInfos = new List + { + new UsageGenerator.CommandInfo + { + Command = "encrypt ", + Description = "Encode text to Base64", + IsOptional = false + }, + new UsageGenerator.CommandInfo + { + Command = "decrypt ", + Description = "Decode Base64 to text", + IsOptional = false + } + }; + showError("Error: Invalid subcommand"); - showError("Usage: base64 encrypt | base64 decrypt "); + showError(UsageGenerator.GenerateCompactUsage("base64", commandInfos)); return; } if (parts.Length < 2) { showError("Error: Please specify text to process"); - showError($"Usage: base64 {subcommand} "); + showError(UsageGenerator.GenerateSimpleUsage("base64", $"{subcommand} ")); return; } diff --git a/shell/UsageGenerator.cs b/shell/UsageGenerator.cs new file mode 100644 index 0000000..3780185 --- /dev/null +++ b/shell/UsageGenerator.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; + +namespace CMLeonOS +{ + public class UsageGenerator + { + public class CommandInfo + { + public string Command { get; set; } + public List SubCommands { get; set; } = new List(); + public string Description { get; set; } + public bool IsOptional { get; set; } + } + + public class SubCommandInfo + { + public string Command { get; set; } + public string Description { get; set; } + public bool IsOptional { get; set; } + } + + public static string GenerateUsage(string commandName, List commandInfos) + { + List lines = new List(); + + lines.Add("Usage: " + commandName + " [subcommand] [args]"); + lines.Add(""); + + foreach (var commandInfo in commandInfos) + { + string cmdDisplay = commandInfo.IsOptional ? "[" + commandInfo.Command + "]" : commandInfo.Command; + string commandLine = " " + commandName + " " + cmdDisplay; + if (!string.IsNullOrEmpty(commandInfo.Description)) + { + int padding = 50 - commandLine.Length; + if (padding < 1) padding = 1; + commandLine += new string(' ', padding) + "- " + commandInfo.Description; + } + lines.Add(commandLine); + + if (commandInfo.SubCommands.Count > 0) + { + foreach (var subCommand in commandInfo.SubCommands) + { + string subCmdDisplay = subCommand.IsOptional ? "[" + subCommand.Command + "]" : subCommand.Command; + string subCommandLine = " " + commandName + " " + commandInfo.Command + " " + subCmdDisplay; + if (!string.IsNullOrEmpty(subCommand.Description)) + { + int padding = 50 - subCommandLine.Length; + if (padding < 1) padding = 1; + subCommandLine += new string(' ', padding) + "- " + subCommand.Description; + } + lines.Add(subCommandLine); + } + } + } + + return BuildStringList(lines); + } + + public static string GenerateSimpleUsage(string commandName, string usagePattern) + { + return "Usage: " + commandName + " " + usagePattern; + } + + public static string GenerateMultiLineUsage(string commandName, List commandInfos) + { + List lines = new List(); + + lines.Add("Usage: " + commandName + " [subcommand] [args]"); + lines.Add(""); + + foreach (var commandInfo in commandInfos) + { + string cmdDisplay = commandInfo.IsOptional ? "[" + commandInfo.Command + "]" : commandInfo.Command; + string commandLine = " " + commandName + " " + cmdDisplay; + if (!string.IsNullOrEmpty(commandInfo.Description)) + { + int padding = 50 - commandLine.Length; + if (padding < 1) padding = 1; + commandLine += new string(' ', padding) + "- " + commandInfo.Description; + } + lines.Add(commandLine); + } + + return BuildStringList(lines); + } + + public static string GenerateDetailedUsage(string commandName, List commandInfos) + { + List lines = new List(); + + lines.Add("Usage: " + commandName + " [subcommand] [args]"); + lines.Add(""); + lines.Add("Available subcommands:"); + lines.Add(""); + + foreach (var commandInfo in commandInfos) + { + string cmdDisplay = commandInfo.IsOptional ? "[" + commandInfo.Command + "]" : commandInfo.Command; + string commandLine = " " + cmdDisplay; + if (!string.IsNullOrEmpty(commandInfo.Description)) + { + int padding = 30 - commandLine.Length; + if (padding < 1) padding = 1; + commandLine += new string(' ', padding) + "- " + commandInfo.Description; + } + lines.Add(commandLine); + + if (commandInfo.SubCommands.Count > 0) + { + lines.Add(""); + lines.Add(" " + commandInfo.Command + " options:"); + lines.Add(""); + + foreach (var subCommand in commandInfo.SubCommands) + { + string subCmdDisplay = subCommand.IsOptional ? "[" + subCommand.Command + "]" : subCommand.Command; + string subCommandLine = " " + subCmdDisplay; + if (!string.IsNullOrEmpty(subCommand.Description)) + { + int padding = 30 - subCommandLine.Length; + if (padding < 1) padding = 1; + subCommandLine += new string(' ', padding) + "- " + subCommand.Description; + } + lines.Add(subCommandLine); + } + lines.Add(""); + } + } + + return BuildStringList(lines); + } + + public static string GenerateCompactUsage(string commandName, List commandInfos) + { + List lines = new List(); + + string commandPattern = BuildCommandPattern(commandInfos); + lines.Add("Usage: " + commandName + " <" + commandPattern + "> [args]"); + lines.Add(""); + + int maxCommandLength = FindMaxCommandLength(commandInfos); + + foreach (var commandInfo in commandInfos) + { + string cmdDisplay = commandInfo.IsOptional ? "[" + commandInfo.Command + "]" : commandInfo.Command; + string commandLine = " " + cmdDisplay; + if (!string.IsNullOrEmpty(commandInfo.Description)) + { + int padding = maxCommandLength + 4 - commandLine.Length; + if (padding < 1) padding = 1; + commandLine += new string(' ', padding) + "- " + commandInfo.Description; + } + lines.Add(commandLine); + } + + return BuildStringList(lines); + } + + public static string GenerateVerticalUsage(string commandName, List commandInfos) + { + List lines = new List(); + + lines.Add("Usage: " + commandName + " [subcommand] [args]"); + lines.Add(""); + lines.Add("Available subcommands:"); + lines.Add(""); + + foreach (var commandInfo in commandInfos) + { + string cmdDisplay = commandInfo.IsOptional ? "[" + commandInfo.Command + "]" : commandInfo.Command; + lines.Add(" " + cmdDisplay); + if (!string.IsNullOrEmpty(commandInfo.Description)) + { + lines.Add(" " + commandInfo.Description); + } + + if (commandInfo.SubCommands.Count > 0) + { + lines.Add(" Options:"); + foreach (var subCommand in commandInfo.SubCommands) + { + string subCmdDisplay = subCommand.IsOptional ? "[" + subCommand.Command + "]" : subCommand.Command; + lines.Add(" " + subCmdDisplay); + if (!string.IsNullOrEmpty(subCommand.Description)) + { + lines.Add(" " + subCommand.Description); + } + } + } + lines.Add(""); + } + + return BuildStringList(lines); + } + + private static string BuildCommandPattern(List commandInfos) + { + string result = ""; + for (int i = 0; i < commandInfos.Count; i++) + { + if (i > 0) + { + result += " | "; + } + string cmdDisplay = commandInfos[i].IsOptional ? "[" + commandInfos[i].Command + "]" : commandInfos[i].Command; + result += cmdDisplay; + } + return result; + } + + private static int FindMaxCommandLength(List commandInfos) + { + int maxLen = 0; + foreach (var commandInfo in commandInfos) + { + int len = commandInfo.Command.Length; + if (len > maxLen) + { + maxLen = len; + } + } + return maxLen; + } + + private static string BuildStringList(List lines) + { + string result = ""; + for (int i = 0; i < lines.Count; i++) + { + if (i > 0) + { + result += "\n"; + } + result += lines[i]; + } + return result; + } + } +} \ No newline at end of file