diff --git a/Program.cs b/Program.cs index 98d4f0e..76ebe79 100644 --- a/Program.cs +++ b/Program.cs @@ -50,6 +50,7 @@ public static async Task Main(string[] args) Console.WriteLine(); ConsoleKeyInfo key; + ConsoleKeyInfo promptKey; string inputBuffer = ""; history.ResetIndex(); @@ -124,6 +125,85 @@ public static async Task Main(string[] args) Console.Write(new string('\b', inputBuffer.Length) + new string(' ', inputBuffer.Length) + new string('\b', inputBuffer.Length)); Console.Write(inputBuffer); } + } else if (inputBuffer.Length > 0) { + HashSet suggestCommands = new(); + HashSet allCommands = CommandParser.CustomCommands.Keys + .Concat(CommandParser.SystemCommands) + .ToHashSet(); + + foreach (var suggestion in allCommands) + { + if (suggestion.StartsWith(inputBuffer)) + { + suggestCommands.Add(suggestion); + } + } + + if (suggestCommands.Count > 15) + { + bool showFullList = false; + AnsiConsole.MarkupLine($"[[[yellow]*[/]]] - Do you want to list all [yellow]{suggestCommands.Count}[/] commands ? ([yellow]y[/]/[yellow]n[/]) >> "); + while (true) + { + promptKey = Console.ReadKey(intercept: true); + if (promptKey.Key == ConsoleKey.Y || promptKey.Key == ConsoleKey.N) + { + if (promptKey.Key == ConsoleKey.Y) + { + showFullList = true; + } + break; + } + } + if (showFullList) + { + var sortedCommands = suggestCommands.OrderBy(c => c.Length).ToArray(); + int i = 0; + + foreach (var cmd in sortedCommands) + { + if (i == 7) + { + AnsiConsole.MarkupLine(""); + i = 0; + } + AnsiConsole.Markup($"{cmd} "); + i++; + } + + inputBuffer = string.Empty; + AnsiConsole.MarkupLine(""); + AnsiConsole.MarkupLine("[[[yellow]*[/]]] - Press enter to continue..."); + } + } + else + { + var sortedCommands = suggestCommands.OrderBy(c => c.Length).ToArray(); + List commandsList = sortedCommands.ToList(); + + int currentIndex = 0; + + if (!string.IsNullOrEmpty(inputBuffer)) + { + for (int i = 0; i < commandsList.Count; i++) + { + if (commandsList[i].StartsWith(inputBuffer)) + { + currentIndex = (i + 1) % commandsList.Count; + inputBuffer = commandsList[currentIndex]; + break; + } + } + } + + Console.SetCursorPosition(0, Console.CursorTop - 1); + Console.SetCursorPosition(0, Console.CursorTop); + Console.Write(new string(' ', Console.WindowWidth)); + Console.SetCursorPosition(0, Console.CursorTop); + + AnsiConsole.Markup(context.GetPrompt()); + Console.Write(inputBuffer); + } } } else if (!char.IsControl(key.KeyChar)) diff --git a/Shell/Commands/CommandParser.cs b/Shell/Commands/CommandParser.cs index 2b9d7f1..742bfd4 100644 --- a/Shell/Commands/CommandParser.cs +++ b/Shell/Commands/CommandParser.cs @@ -11,8 +11,8 @@ namespace NihilistShell.Shell; public class CommandParser { - private readonly Dictionary _commands = new(); - private readonly HashSet _systemCommands = new(); + public static readonly Dictionary CustomCommands = new(); + public static readonly HashSet SystemCommands = new(); private static readonly HashSet InteractiveCommands = new() { "vim", "nano", "less", "more", "top", "htop", "man", "ssh", "apt" @@ -33,11 +33,11 @@ private void LoadCommands() { foreach (var command in CommandRegistry.GetAll()) { - _commands[command.Name] = command; + CustomCommands[command.Name] = command; AnsiConsole.MarkupLine($"\t[[[green]+[/]]] - Loaded custom command: [yellow]{command.Name}[/]"); } - var TotalCommands = _commands.Count + _systemCommands.Count; + var TotalCommands = CustomCommands.Count + SystemCommands.Count; LoadSystemCommands(); @@ -69,7 +69,7 @@ private void LoadSystemCommands() foreach (var cmd in commands) { - _systemCommands.Add(cmd); + SystemCommands.Add(cmd); var safeCmd = EscapeMarkup(cmd); //AnsiConsole.MarkupLine($"\t[[[green]+[/]]] Loaded system command: [yellow]{safeCmd}[/]"); } @@ -143,7 +143,7 @@ public bool TryExecute(string commandLine, ShellContext context) } } - if (_commands.TryGetValue(cmdName, out var command)) + if (CustomCommands.TryGetValue(cmdName, out var command)) { if (command is IMetadataCommand meta && meta.RequiresRoot && !(usedSudo || IsRootUser())) { @@ -155,7 +155,7 @@ public bool TryExecute(string commandLine, ShellContext context) return true; } - if (_systemCommands.Contains(cmdName)) + if (SystemCommands.Contains(cmdName)) { var fullPath = ResolveSystemCommandPath(cmdName); if (fullPath != null)