From 6db9516a2a55bff81f008e6a7448da6b957480bc Mon Sep 17 00:00:00 2001 From: PaddiM8 Date: Mon, 13 Nov 2023 00:09:18 +0100 Subject: [PATCH] cli: Hints for custom completions (if enabled) --- cli/HighlightHandler.cs | 2 +- cli/HintHandler.cs | 6 +++++- src/Resources/completions/git.elk | 12 ++++++++++-- src/Std/Cli.cs | 2 ++ .../Serialization/CommandLine/CliArgument.cs | 2 ++ .../DataTypes/Serialization/CommandLine/CliFlag.cs | 2 ++ .../Serialization/CommandLine/RuntimeCliParser.cs | 8 +++++--- 7 files changed, 27 insertions(+), 7 deletions(-) diff --git a/cli/HighlightHandler.cs b/cli/HighlightHandler.cs index 8e25c1b7..6084c0b5 100644 --- a/cli/HighlightHandler.cs +++ b/cli/HighlightHandler.cs @@ -471,7 +471,7 @@ private string NextPath() return ( Color(string.Concat(highlightedTextArguments), 36), - new(textArguments, caretAtArgumentIndex) + new TextArgumentsInfo(textArguments, caretAtArgumentIndex) ); } diff --git a/cli/HintHandler.cs b/cli/HintHandler.cs index 8ef5a276..d486d07f 100644 --- a/cli/HintHandler.cs +++ b/cli/HintHandler.cs @@ -55,7 +55,10 @@ private string GetFileHint() return ""; var completionTarget = activeTextArgument ?? invocationInfo.Name; + // For some reason TextArgumentsInfo.Arguments contains elements for the spaces + // that separate the arguments. This should probably be fixed at some point. var completions = GetCompletions( + string.Concat(invocationInfo.TextArgumentsInfo.Arguments).TrimStart(), completionTarget, invocationInfo, isTextArgument: activeTextArgument != null @@ -81,6 +84,7 @@ private string GetFileHint() } private IEnumerable GetCompletions( + string allTextArguments, string completionTarget, ShellStyleInvocationInfo? invocationInfo, bool isTextArgument) @@ -89,7 +93,7 @@ private IEnumerable GetCompletions( ? null : _customCompletionProvider.Get(invocationInfo.Name); if (completionParser != null) - return completionParser.GetCompletions(completionTarget, null, CompletionKind.Hint); + return completionParser.GetCompletions(allTextArguments, null, CompletionKind.Hint); return FileUtils.GetPathCompletions( Utils.Unescape(completionTarget), diff --git a/src/Resources/completions/git.elk b/src/Resources/completions/git.elk index f5a61780..f17426e9 100644 --- a/src/Resources/completions/git.elk +++ b/src/Resources/completions/git.elk @@ -38,12 +38,20 @@ fn handleHelp(parser) { fn handleAdd(parser) { parser - | cli::addArgument({ "identifier": "file", "completionHandler": &unstagedFilesHandler, "variadic": true }) + | cli::addArgument({ + "identifier": "file", + "completionHandler": &unstagedFilesHandler, + "allowCustomCompletionHints": true, + "variadic": true + }) } fn handleBranch(parser) { parser - | cli::addArgument({ "completionHandler": &branchHandler }) + | cli::addArgument({ + "completionHandler": &branchHandler, + "allowCustomCompletionHints": true, + }) | cli::addFlag({ "short": "u", "valueKind": "text" }) | cli::addFlag({ "long": "unset-upstream" }) | cli::addFlag({ "short": "d" }) diff --git a/src/Std/Cli.cs b/src/Std/Cli.cs index 67d80291..225c6dc6 100644 --- a/src/Std/Cli.cs +++ b/src/Std/Cli.cs @@ -93,6 +93,7 @@ public static RuntimeObject AddFlag(RuntimeCliParser parser, RuntimeDictionary f _ => CliValueKind.None, }, IsRequired = flag.GetValue("required")?.IsTrue ?? false, + AllowCustomCompletionHints = flag.GetValue("allowCustomCompletionHints")?.IsTrue ?? false, CompletionHandler = completionHandler, }); @@ -160,6 +161,7 @@ public static RuntimeObject AddArgument(RuntimeCliParser parser, RuntimeDictiona _ => CliValueKind.None, }, IsVariadic = argument.GetValue("variadic")?.IsTrue ?? false, + AllowCustomCompletionHints = argument.GetValue("allowCustomCompletionHints")?.IsTrue ?? false, CompletionHandler = completionHandler, }; parser.AddArgument(typedArgument); diff --git a/src/Std/DataTypes/Serialization/CommandLine/CliArgument.cs b/src/Std/DataTypes/Serialization/CommandLine/CliArgument.cs index 20ee2784..2eda62df 100644 --- a/src/Std/DataTypes/Serialization/CommandLine/CliArgument.cs +++ b/src/Std/DataTypes/Serialization/CommandLine/CliArgument.cs @@ -16,5 +16,7 @@ public class CliArgument public bool IsVariadic { get; init; } + public bool AllowCustomCompletionHints { get; init; } + public Func>? CompletionHandler { get; init; } } \ No newline at end of file diff --git a/src/Std/DataTypes/Serialization/CommandLine/CliFlag.cs b/src/Std/DataTypes/Serialization/CommandLine/CliFlag.cs index 6d7816f7..e872ca08 100644 --- a/src/Std/DataTypes/Serialization/CommandLine/CliFlag.cs +++ b/src/Std/DataTypes/Serialization/CommandLine/CliFlag.cs @@ -20,5 +20,7 @@ public class CliFlag public bool IsRequired { get; init; } + public bool AllowCustomCompletionHints { get; init; } + public Func>? CompletionHandler { get; init; } } \ No newline at end of file diff --git a/src/Std/DataTypes/Serialization/CommandLine/RuntimeCliParser.cs b/src/Std/DataTypes/Serialization/CommandLine/RuntimeCliParser.cs index fa879920..6519f24d 100644 --- a/src/Std/DataTypes/Serialization/CommandLine/RuntimeCliParser.cs +++ b/src/Std/DataTypes/Serialization/CommandLine/RuntimeCliParser.cs @@ -201,7 +201,7 @@ private IEnumerable GetCompletions( : x.completion ); var collectedTokens = tokens.ToList(); - if (collectedTokens.Count == 1 && _verbs.Any() && !last.StartsWith("-")) + if (collectedTokens.Count == 1 && _verbs.Any() && !last.StartsWith('-')) { // Also include matchedFlags, in case the token is empty, // which would mean it could either be a verb or a flag. @@ -226,7 +226,8 @@ private IEnumerable GetCompletions( flag = _flags.FirstOrDefault(x => x.ShortName == secondLast[1..]); } - if (completionKind != CompletionKind.Hint && flag?.CompletionHandler != null && cliResult != null) + var allowCustom = completionKind != CompletionKind.Hint || flag?.AllowCustomCompletionHints is true; + if (allowCustom && flag?.CompletionHandler != null && cliResult != null) return flag.CompletionHandler(last, cliResult); if (flag is { ValueKind: CliValueKind.Path or CliValueKind.Directory }) @@ -254,7 +255,8 @@ private IEnumerable GetCompletions( var currentArgument = lastIsArgument ? _arguments.ElementAtOrDefault(argumentCount - 1) ?? _arguments.Last() : null; - if (completionKind != CompletionKind.Hint && currentArgument?.CompletionHandler != null && cliResult != null) + var allowCustomCompletion = completionKind != CompletionKind.Hint || currentArgument?.AllowCustomCompletionHints is true; + if (allowCustomCompletion && currentArgument?.CompletionHandler != null && cliResult != null) return currentArgument.CompletionHandler(last, cliResult); if (currentArgument is { ValueKind: CliValueKind.Path or CliValueKind.Directory })