/// <summary> /// Checks to see if the current argument is allowed to have a value based on which other arguments are present and based on the expression /// passed to the constructor. If it's not allowed and has been specified then an UnexpectedArgException is thrown. /// </summary> /// <param name="context">The current PowerArgs processing context</param> public override void AfterPopulateProperties(ArgHook.HookContext context) { if(IsCurrentArgumentAllowed(context) == false && context.CurrentArgument.RevivedValue != null) { throw new UnexpectedArgException("The argument '" + context.CurrentArgument.DefaultAlias + "' cannot be used with one or more arguments: " + ExpressionText); } }
/// <summary> /// Makes sure the target is a boolean /// </summary> /// <param name="context">Context passed by the parser</param> public override void BeforePopulateProperty(ArgHook.HookContext context) { base.BeforePopulateProperty(context); if (context.CurrentArgument.ArgumentType != typeof(bool)) { throw new InvalidArgDefinitionException(typeof(HelpHook).Name +" attributes can only be used with boolean properties or parameters"); } }
/// <summary> /// Writes the help as long as WriteHelp is true /// </summary> /// <param name="context">Context passed by the parser</param> public override void AfterCancel(ArgHook.HookContext context) { base.AfterCancel(context); if (WriteHelp == false) return; ArgUsage.GetStyledUsage(context.Definition, EXEName, new ArgUsageOptions() { ShowPosition = ShowPositionColumn, ShowType = ShowTypeColumn, ShowPossibleValues = ShowPossibleValues, }).Write(); }
public override void BeforeInvoke(ArgHook.HookContext context) { var action = context.SpecifiedAction; var storageAccountNameArgument = action.FindMatchingArgument("StorageAccountName"); var storageAccountKeyArgument = action.FindMatchingArgument("StorageAccountKey"); if (storageAccountNameArgument != null && storageAccountKeyArgument != null) { CommandLineStorageConfigProvider.CommandLineAccountName = "" + storageAccountNameArgument.RevivedValue; CommandLineStorageConfigProvider.CommandLineAccountKey = "" + storageAccountKeyArgument.RevivedValue; SharedStorageAccount.Reset(new CommandLineStorageConfigProvider()); } }
/// <summary> /// Determines if the current argument is allowed to be populated based on which other arguments are present and based on the expression passed to the constructor. /// </summary> /// <param name="context">The current PowerArgs processing context</param> /// <returns>True if this argument can be specified, false otherwise</returns> public bool IsCurrentArgumentAllowed(ArgHook.HookContext context) { if (context.CurrentArgument == null) { throw new InvalidArgDefinitionException("The " + GetType().Name + " metadata must be applied to a particular argument"); } try { bool eval = this.Expression.Evaluate(context.Definition.CreateVariableResolver()); if (eval == true) { return false; } } catch (Exception ex) { var targetText = context.CurrentArgument.DefaultAlias; throw new InvalidArgDefinitionException("Failed to evaluate conditional " + GetType().Name + " clause on target '" + targetText + "' - " + ex.Message); } return true; }
/// <summary> /// Prompts the user to enter a value for the given property in the case that the option was specified with no value /// </summary> /// <param name="context">the parser context</param> public override void BeforePopulateProperty(ArgHook.HookContext context) { if (context.ArgumentValue == string.Empty) { var cli = new CliHelper(); ITabCompletionHandler tabHandler; IHighlighterConfigurator highlighterConfigurator; if (TabCompletionHandlerType.TryCreate<ITabCompletionHandler>(out tabHandler)) { cli.Reader.TabHandler.TabCompletionHandlers.Add(tabHandler); } if (HighlighterConfiguratorType.TryCreate<IHighlighterConfigurator>(out highlighterConfigurator)) { cli.Reader.Highlighter = new SimpleSyntaxHighlighter(); highlighterConfigurator.Configure(cli.Reader.Highlighter); } context.ArgumentValue = cli.PromptForLine("Enter value for " + context.CurrentArgument.DefaultAlias); } }
/// <summary> /// If the current argument is a boolean and it is specified on the command line then /// this hook sets the IsNonInteractive flag on the current argument definition. /// </summary> /// <param name="context"></param> public override void BeforeParse(ArgHook.HookContext context) { if(context.CurrentArgument.ArgumentType != typeof(bool)) { throw new InvalidArgDefinitionException(GetType().Name + " can only be used on boolean arguments"); } for (int i = 0; i < context.CmdLineArgs.Length; i++ ) { var arg = context.CmdLineArgs[i]; string key; if (ArgParser.TryParseKey(arg, out key)) { var nextArg = i == context.CmdLineArgs.Length - 1 ? "" : context.CmdLineArgs[i + 1].ToLower(); // TODO - Find a better way to detect explicit 'false' if (context.CurrentArgument.IsMatch(key) && nextArg != "false" && nextArg != "0") { context.Definition.IsNonInteractive = true; } } } }
public override void BeforeParse(ArgHook.HookContext context) { context.SetProperty("Year", 2013); context.SetProperty("Year", 2013); context.SetProperty("Name", "Adam"); context.SetProperty("Name", "Adam"); }
public override void AfterPopulateProperties(ArgHook.HookContext context) { Assert.IsTrue(context.HasProperty("Year")); Assert.IsTrue(context.HasProperty("Name")); var year = context.GetProperty<int>("Year"); var name = context.GetProperty<string>("Name"); Assert.AreEqual(2013, year); Assert.AreEqual("Adam", name); context.ClearProperty("Year"); context.SetProperty<string>("Name", null); Assert.IsFalse(context.HasProperty("Year")); Assert.IsFalse(context.HasProperty("Name")); Assert.IsNull(context.GetProperty<string>("Name")); try { context.GetProperty<int>("Year"); Assert.Fail("An exception should have been thrown"); } catch (KeyNotFoundException) { // Throw for value types, return null for reference types } WasRun = true; }
private bool TryPreventExceptionWithPrompt(ArgHook.HookContext context) { if (parent.PromptIfMissing && ArgHook.HookContext.Current.Definition.IsNonInteractive == false) { var cli = new Cli(); ITabCompletionHandler tabHandler; IHighlighterConfigurator highlighterConfigurator; if (TabCompletionHandlerType.TryCreate<ITabCompletionHandler>(out tabHandler)) { cli.Reader.TabHandler.TabCompletionHandlers.Add(tabHandler); } if (HighlighterConfiguratorType.TryCreate<IHighlighterConfigurator>(out highlighterConfigurator)) { cli.Reader.Highlighter = new SimpleSyntaxHighlighter(); highlighterConfigurator.Configure(cli.Reader.Highlighter); } context.ArgumentValue = cli.PromptForLine("Enter value for " + context.CurrentArgument.DefaultAlias); context.CurrentArgument.Populate(context); return true; } else { return false; } }
private void Evaluate(ArgHook.HookContext context, string expressionText, bool not) { try { var newExpressionText = expressionText; if(not) { newExpressionText = "!(" + expressionText + ")"; } var expression = BooleanExpressionParser.Parse(newExpressionText); var eval = expression.Evaluate(context.Definition.CreateVariableResolver()); if(not) { if (eval == true && context.CurrentArgument.RevivedValue == null) { if (TryPreventExceptionWithPrompt(context) == false) { throw new MissingArgException("The argument '" + context.CurrentArgument.DefaultAlias + "' is required if the following argument(s) are not specified: " + expressionText); } } } else { if (eval == true && context.CurrentArgument.RevivedValue == null) { if (TryPreventExceptionWithPrompt(context) == false) { throw new MissingArgException("The argument '" + context.CurrentArgument.DefaultAlias + "' is required if the following argument(s) are specified: " + expressionText); } } } } catch(MissingArgException) { throw; } catch (Exception ex) { var targetText = context.CurrentArgument.DefaultAlias + " (" + expressionText + ")"; throw new InvalidArgDefinitionException("Failed to evaluate conditional ArgRequired clause on target '" + targetText + "'" + ex.Message); } }
internal static void PopulateArguments(List<CommandLineArgument> arguments, ArgHook.HookContext context) { foreach (var argument in arguments) { argument.FindMatchingArgumentInRawParseData(context); argument.Populate(context); } }
/// <summary> /// Writes the help as long as WriteHelp is true /// </summary> /// <param name="context">Context passed by the parser</param> public override void AfterCancel(ArgHook.HookContext context) { base.AfterCancel(context); if (iDidTheCancel == false) return; if (WriteHelp == false) return; var usage = UsageTemplateProvider.GetUsage(UsageTemplateProviderType, context.Definition); usage.Write(); FireUsageWritten(usage); }
public override void BeforeInvoke(ArgHook.HookContext context) { context.CancelAllProcessing(); }
internal static void PopulateArguments(List<CommandLineArgument> arguments, ArgHook.HookContext context) { var oldCurrent = context.CurrentArgument; try { foreach (var argument in arguments) { context.CurrentArgument = argument; argument.FindMatchingArgumentInRawParseData(context); argument.Populate(context); } } finally { context.CurrentArgument = oldCurrent; } }
/// <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 (Indicator == "" && context.CmdLineArgs.Length != 0) return; else if (Indicator != "" && (context.CmdLineArgs.Length != 1 || context.CmdLineArgs[0] != Indicator)) return; var existingColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Cyan; try { if (REPL && ShowREPLWelcome) { Console.WriteLine(); var message = REPLWelcomeMessage.Replace("{{Indicator}}", REPLExitIndicator); Console.WriteLine(message); Console.WriteLine(); Console.Write(Indicator + "> "); ShowREPLWelcome = false; } else if (REPL) { Console.Write(Indicator + "> "); } 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 + "> "); } } } finally { Console.ForegroundColor = existingColor; } List<string> completions = FindTabCompletions(context.Definition.Arguments, context.Definition.Actions); List<ITabCompletionSource> completionSources = new List<ITabCompletionSource>(); if(this.completionSource != null) completionSources.Add((ITabCompletionSource)Activator.CreateInstance(this.completionSource)); completionSources.Add(new EnumTabCompletionSource(context.Definition)); completionSources.Add(new SimpleTabCompletionSource(completions) { MinCharsBeforeCyclingBegins = 0 }); completionSources.Add(new FileSystemTabCompletionSource()); string str = null; var newCommandLine = ConsoleHelper.ReadLine(ref str, LoadHistory(), new MultiTabCompletionSource(completionSources)); if (REPL && newCommandLine.Length == 1 && string.Equals(newCommandLine[0], REPLExitIndicator, StringComparison.OrdinalIgnoreCase)) { throw new REPLExitException(); } if (REPL && newCommandLine.Length == 1 && newCommandLine[0] == "cls") { ConsoleHelper.ConsoleImpl.Clear(); throw new REPLContinueException(); } else if (REPL && newCommandLine.Length == 0 && string.IsNullOrWhiteSpace(REPLExitIndicator) == false) { throw new REPLContinueException(); } context.CmdLineArgs = newCommandLine; AddToHistory(str); }
private void FindMatchingArgumentInRawParseData(ArgHook.HookContext context) { var match = from k in context.ParserData.ExplicitParameters.Keys where IsMatch(k) select k; if (match.Count() > 1) { throw new DuplicateArgException("Argument specified more than once: " + Aliases.First()); } else if (match.Count() == 1) { var key = match.First(); context.ArgumentValue = context.ParserData.ExplicitParameters[key]; context.ParserData.ExplicitParameters.Remove(key); } else if (context.ParserData.ImplicitParameters.ContainsKey(Position)) { var position = Position; context.ArgumentValue = context.ParserData.ImplicitParameters[position]; context.ParserData.ImplicitParameters.Remove(position); } else { context.ArgumentValue = null; } }
internal void RunBeforePopulateProperty(ArgHook.HookContext context) { RunArgumentHook(context, h => h.BeforePopulatePropertyPriority, (h) => { h.BeforePopulateProperty(context); }); }
internal void RunArgumentHook(ArgHook.HookContext context, Func<ArgHook, int> orderby, Action<ArgHook> hookAction) { context.Property = Source as PropertyInfo; context.CurrentArgument = this; foreach (var hook in Hooks.OrderBy(orderby)) { hookAction(hook); } context.Property = null; context.CurrentArgument = null; }
internal void Populate(ArgHook.HookContext context) { RunBeforePopulateProperty(context); if (RevivedValueOverride == null) { Validate(ref context.ArgumentValue); Revive(context.ArgumentValue); } else { RevivedValue = RevivedValueOverride; RevivedValueOverride = null; } RunAfterPopulateProperty(context); }
/// <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 (indicator == "" && context.CmdLineArgs.Length != 0)return; else if (indicator != "" && (context.CmdLineArgs.Length != 1 || context.CmdLineArgs[0] != indicator)) return; try { // 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 var color = Console.ForegroundColor; var lastLine = ConsoleHelper.StdConsoleProvider.ReadALineOfConsoleOutput(Console.CursorTop - 1); Console.CursorTop--; Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine(lastLine); Console.ForegroundColor = color; Console.CursorTop--; Console.CursorLeft = lastLine.Length + 1; } catch (Exception) { Console.Write(indicator + "> "); } List<string> completions = FindTabCompletions(context.Args.GetType()); List<ITabCompletionSource> completionSources = new List<ITabCompletionSource>(); if(this.completionSource != null) completionSources.Add((ITabCompletionSource)Activator.CreateInstance(this.completionSource)); completionSources.Add(new EnumTabCompletionSource(context.Args.GetType())); completionSources.Add(new SimpleTabCompletionSource(completions) { MinCharsBeforeCyclingBegins = 0 }); completionSources.Add(new FileSystemTabCompletionSource()); string str = null; context.CmdLineArgs = ConsoleHelper.ReadLine(ref str, LoadHistory(), new MultiTabCompletionSource(completionSources)); AddToHistory(str); }
public override void AfterCancel(ArgHook.HookContext context) { AfterCancelCalled = true; }
/// <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); }
internal void Validate(ArgHook.HookContext context) { context.RunBeforeValidateDefinition(); ValidateArguments(Arguments); ValidateActionAliases(); foreach (var action in Actions) { if (action.Aliases.Count == 0) throw new InvalidArgDefinitionException("One of your actions has no aliases"); ValidateArguments(Arguments.Union(action.Arguments)); if (action.ActionMethod == null) throw new InvalidArgDefinitionException("The action '"+action.DefaultAlias+"' has no ActionMethod defined"); } }
public override void AfterPopulateProperties(ArgHook.HookContext context) { if(parent.If != null && parent.IfNot != null) { throw new InvalidArgDefinitionException("You cannot specify both the 'If' and the 'IfNot' properties on the ArgRequired metadata"); } else if(parent.If != null) { Evaluate(context, parent.If, false); } else if (parent.IfNot != null) { Evaluate(context, parent.IfNot, true); } else { throw new InvalidOperationException("ArgRequired could not determine if the given argument was required. This is likely a bug in PowerArgs."); } }
private bool TryPreventExceptionWithPrompt(ArgHook.HookContext context) { if (parent.PromptIfMissing && ArgHook.HookContext.Current.Definition.IsNonInteractive == false) { var cli = new CliHelper(); ITabCompletionHandler tabHandler; IHighlighterConfigurator highlighterConfigurator; if (TabCompletionHandlerType.TryCreate<ITabCompletionHandler>(out tabHandler)) { cli.Reader.TabHandler.TabCompletionHandlers.Add(tabHandler); } if (HighlighterConfiguratorType.TryCreate<IHighlighterConfigurator>(out highlighterConfigurator)) { cli.Reader.Highlighter = new SimpleSyntaxHighlighter(); highlighterConfigurator.Configure(cli.Reader.Highlighter); } cli.Reader.UnregisterHandler(ConsoleKey.Escape); cli.Reader.RegisterHandler(KeyHandler.FromAction((searchReaderContext) => { TabCompletion tabCompletionInfo; if (context.Definition.IsNonInteractive == false && context.Definition.Metadata.TryGetMeta<TabCompletion>(out tabCompletionInfo) && tabCompletionInfo.REPL == true) { // if this is an interactive REPL then continue the REPL in this case as the user may have changed their mind about taking // this action - Note there are two places in this file that have this logic throw new REPLContinueException(); } else { throw new MissingArgException("The argument '" + context.CurrentArgument.DefaultAlias + "' is required", new ArgumentNullException(context.CurrentArgument.DefaultAlias)); } }, ConsoleKey.Escape)); context.ArgumentValue = cli.PromptForLine("Enter value for " + context.CurrentArgument.DefaultAlias); context.CurrentArgument.Populate(context); return true; } else { return false; } }
internal static void PopulateArguments(List<CommandLineArgument> arguments, ArgHook.HookContext context) { foreach (var argument in arguments) { argument.FindMatchingArgumentInRawParseData(context); argument.RunBeforePopulateProperty(context); argument.Validate(ref context.ArgumentValue); argument.Revive(context.ArgumentValue); argument.RunAfterPopulateProperty(context); } }