public bool ShouldBeHighlighted(RichCommandLineContext readerContext, HighlighterContext highlighterContext) { // don't even try mark tokens as invalid unless the cursor is on it if (readerContext.BufferPosition >= highlighterContext.CurrentToken.StartIndex && readerContext.BufferPosition < highlighterContext.CurrentToken.EndIndex) { return(false); } var currentToken = highlighterContext.CurrentToken.Value; var previousToken = PowerArgsRichCommandLineReader.FindPreviousNonWhitespaceToken(readerContext, highlighterContext); var firstToken = readerContext.Tokens[0].Value; CommandLineAction contextualAction = PowerArgsRichCommandLineReader.FindContextualAction(firstToken, definition); CommandLineArgument contextualArgument = PowerArgsRichCommandLineReader.FindContextualArgument(previousToken, contextualAction, definition); if (contextualArgument != null) { if (contextualArgument.TestIsValidAndRevivable(currentToken) == false) { // the current token either failed validation or could not be revived return(true); } } bool expectMatchingArg; CommandLineArgument currentTokenArgument = PowerArgsRichCommandLineReader.FindCurrentTokenArgument(contextualAction, currentToken, out expectMatchingArg, definition); if (currentTokenArgument == null && expectMatchingArg) { // The current token starts with a - or /, but does not match a global or action specific argument, so we'll highlight the token red return(true); } return(false); }
public void TestArgumentAwareSmartTabCompletion() { var input = "m\t -a\t \t"; // should expand to 'meats -animal Chicken; ConsoleProvider.Current = new TestConsoleProvider(input); var definition = new CommandLineArgumentsDefinition(typeof(ConflictingArgumentsThatAwesomeTabCompletionMakesBetter)); PowerArgsRichCommandLineReader reader = new PowerArgsRichCommandLineReader(definition, new List<ConsoleString>()); reader.ThrowOnSyntaxHighlightException = true; reader.TabHandler.ThrowOnTabCompletionHandlerException = true; var completed = string.Join(" ", reader.ReadCommandLine()); Assert.AreEqual("meats -animal Chicken", completed); }
/// <summary> /// Before PowerArgs parses the args, this hook inspects the command line for the indicator and if found /// takes over the command line and provides tab completion. /// </summary> /// <param name="context">The context used to inspect the command line arguments.</param> public override void BeforeParse(ArgHook.HookContext context) { if (CompletionSourceType != null && CompletionSourceType.GetInterfaces().Contains(typeof(ITabCompletionSource)) == false && CompletionSourceType.GetInterfaces().Contains(typeof(ISmartTabCompletionSource)) == false) { throw new InvalidArgDefinitionException("Type does not implement ITabCompletionSource or ISmartTabCompletionSource: " + CompletionSourceType.FullName); } if (context.Definition.IsNonInteractive) { this.REPL = false; return; } if (Indicator == "" && context.CmdLineArgs.Length != 0) { this.REPL = false; return; } if (Indicator != "" && (context.CmdLineArgs.Length != 1 || context.CmdLineArgs[0] != Indicator)) { this.REPL = false; return; } if (REPL && ShowREPLWelcome) { ConsoleString.Empty.WriteLine(); var message = REPLWelcomeMessage.Replace("{{Indicator}}", REPLExitIndicator); ConsoleString.WriteLine(message, ConsoleColor.Cyan); ConsoleString.Empty.WriteLine(); ConsoleString.Write(Indicator + "> ", ConsoleColor.Cyan); ShowREPLWelcome = false; } else if (REPL) { ConsoleString.Write(Indicator + "> ", ConsoleColor.Cyan); } else { // This is a little hacky, but I could not find a better way to make the tab completion start on the same lime // as the command line input try { var lastLine = StdConsoleProvider.ReadALineOfConsoleOutput(Console.CursorTop - 1); Console.CursorTop--; Console.WriteLine(lastLine); Console.CursorTop--; Console.CursorLeft = lastLine.Length + 1; } catch (Exception) { Console.WriteLine(); Console.Write(Indicator + "> "); } } PowerArgsRichCommandLineReader reader = new PowerArgsRichCommandLineReader(context.Definition, LoadHistory()); IHighlighterConfigurator customConfigurator; if (HighlighterConfiguratorType.TryCreate <IHighlighterConfigurator>(out customConfigurator)) { customConfigurator.Configure(reader.Highlighter); } var newCommandLineString = reader.ReadLine().ToString(); var newCommandLineArray = Args.Convert(newCommandLineString); if (REPL && newCommandLineArray.Length == 1 && string.Equals(newCommandLineArray[0], REPLExitIndicator, StringComparison.OrdinalIgnoreCase)) { throw new REPLExitException(); } if (REPL && newCommandLineArray.Length == 1 && newCommandLineArray[0] == "cls") { ConsoleProvider.Current.Clear(); throw new REPLContinueException(); } else if (REPL && newCommandLineArray.Length == 0 && string.IsNullOrWhiteSpace(REPLExitIndicator) == false) { throw new REPLContinueException(); } context.CmdLineArgs = newCommandLineArray; AddToHistory(newCommandLineString); }
/// <summary> /// Before PowerArgs parses the args, this hook inspects the command line for the indicator and if found /// takes over the command line and provides tab completion. /// </summary> /// <param name="context">The context used to inspect the command line arguments.</param> public override void BeforeParse(ArgHook.HookContext context) { if (CompletionSourceType != null && CompletionSourceType.GetInterfaces().Contains(typeof(ITabCompletionSource)) == false && CompletionSourceType.GetInterfaces().Contains(typeof(ISmartTabCompletionSource)) == false) { throw new InvalidArgDefinitionException("Type does not implement ITabCompletionSource or ISmartTabCompletionSource: " + CompletionSourceType.FullName); } if (context.Definition.IsNonInteractive) { this.REPL = false; return; } if (Indicator == "" && context.CmdLineArgs.Length != 0) { this.REPL = false; return; } if (Indicator != "" && (context.CmdLineArgs.Length != 1 || context.CmdLineArgs[0] != Indicator)) { this.REPL = false; return; } if (REPL && ShowREPLWelcome) { ConsoleString.Empty.WriteLine(); var message = REPLWelcomeMessage.Replace("{{Indicator}}", REPLExitIndicator); ConsoleString.WriteLine(message, ConsoleColor.Cyan); ConsoleString.Empty.WriteLine(); ConsoleString.Write(Indicator + "> ", ConsoleColor.Cyan); ShowREPLWelcome = false; } else if (REPL) { ConsoleString.Write(Indicator + "> ", ConsoleColor.Cyan); } else { // This is a little hacky, but I could not find a better way to make the tab completion start on the same lime // as the command line input try { var lastLine = StdConsoleProvider.ReadALineOfConsoleOutput(Console.CursorTop - 1); Console.CursorTop--; Console.WriteLine(lastLine); Console.CursorTop--; Console.CursorLeft = lastLine.Length + 1; } catch (Exception) { Console.WriteLine(); Console.Write(Indicator + "> "); } } PowerArgsRichCommandLineReader reader = new PowerArgsRichCommandLineReader(context.Definition, LoadHistory()); IHighlighterConfigurator customConfigurator; if(HighlighterConfiguratorType.TryCreate<IHighlighterConfigurator>(out customConfigurator)) { customConfigurator.Configure(reader.Highlighter); } var newCommandLineString = reader.ReadLine().ToString(); var newCommandLineArray = Args.Convert(newCommandLineString); if (REPL && newCommandLineArray.Length == 1 && string.Equals(newCommandLineArray[0], REPLExitIndicator, StringComparison.OrdinalIgnoreCase)) { throw new REPLExitException(); } if (REPL && newCommandLineArray.Length == 1 && newCommandLineArray[0] == "cls") { ConsoleProvider.Current.Clear(); throw new REPLContinueException(); } else if (REPL && newCommandLineArray.Length == 0 && string.IsNullOrWhiteSpace(REPLExitIndicator) == false) { throw new REPLContinueException(); } context.CmdLineArgs = newCommandLineArray; AddToHistory(newCommandLineString); }