public override bool CanAssist(RichCommandLineContext context) { Providers.Clear(); Providers.AddRange(standardProviders); CommandLineArgument targetArgument = null; if (context.PreviousNonWhitespaceToken != null && ArgParser.IsDashSpecifiedArgumentIdentifier(context.PreviousNonWhitespaceToken.Value)) { var candidate = context.PreviousNonWhitespaceToken.Value.Substring(1); targetArgument = (from a in Definition.AllGlobalAndActionArguments where a.IsMatch(candidate) select a).SingleOrDefault(); } if (targetArgument != null) { foreach (var assistant in targetArgument.Metadata.Metas <ArgContextualAssistant>()) { var dynamicProvider = assistant.GetContextAssistProvider(Definition); Providers.Add(dynamicProvider); } } foreach (var provider in Providers) { if (provider is PowerArgsContextAwareAssistant) { (provider as PowerArgsContextAwareAssistant).TargetArgument = targetArgument; } } var ret = base.CanAssist(context); return(ret); }
public static CommandLineArgument FindContextualArgument(FindContextualArgumentArgs args) { args.Definition = PassThroughOrTryGetAmbientDefinition(args.Definition); string currentTokenArgumentNameValue = null; if (args.PreviousToken != null && ArgParser.IsDashSpecifiedArgumentIdentifier(args.PreviousToken)) { currentTokenArgumentNameValue = args.PreviousToken.Substring(1); } else if (args.PreviousToken != null && args.PreviousToken.StartsWith("/")) { currentTokenArgumentNameValue = args.PreviousToken.Substring(1); } else { // strange behavior outside of this method where we need to look back one if the current token has a non whitespace value var targetPosition = string.IsNullOrWhiteSpace(args.CurrentToken) ? args.CurrentTokenIndex : args.CurrentTokenIndex - 1; if (targetPosition < 0) { return(null); } var positionArg = args.ActionContext == null? args.Definition.Arguments.Where(a => a.Position == targetPosition).FirstOrDefault() : args.ActionContext.Arguments.Where(a => a.Position == targetPosition).FirstOrDefault(); var argsArray = Args.Convert(args.CommandLine); if (positionArg == null) { return(positionArg); } for (var i = 0; i < Math.Min(argsArray.Length, targetPosition + 1); i++) { // positional args must occur before any named args if (argsArray[i].StartsWith("/") || Regex.IsMatch(argsArray[i], @"^-[^\d]")) { return(null); } } return(positionArg); } CommandLineArgument currentTokenArgument = null; if (currentTokenArgumentNameValue != null) { currentTokenArgument = args.Definition.Arguments.Where(arg => arg.IsMatch(currentTokenArgumentNameValue) && arg.ArgumentType != typeof(bool)).SingleOrDefault(); if (currentTokenArgument == null && args.ActionContext != null) { currentTokenArgument = args.ActionContext.Arguments.Where(arg => arg.IsMatch(currentTokenArgumentNameValue) && arg.ArgumentType != typeof(bool)).SingleOrDefault(); } } return(currentTokenArgument); }
public bool TryComplete(TabCompletionContext context, out string completion) { var fixedUpCandidate = context.CompletionCandidate; if (ArgParser.IsDashSpecifiedArgumentIdentifier(fixedUpCandidate)) { fixedUpCandidate = fixedUpCandidate.Substring(1); } else if (fixedUpCandidate.StartsWith("/")) { fixedUpCandidate = fixedUpCandidate.Substring(1); } else { completion = null; return(false); } var match = definition.Arguments.Where(arg => arg.IsMatch(fixedUpCandidate)).SingleOrDefault(); if (match == null) { foreach (var action in definition.Actions) { match = action.Arguments.Where(arg => arg.IsMatch(fixedUpCandidate)).SingleOrDefault(); if (match != null) { break; } } } if (match == null) { completion = null; return(false); } if (match != argument) { completion = null; return(false); } return(TryComplete(new ArgumentAwareTabCompletionContext() { InnerContext = context, Argument = argument } , out completion)); }
private ArgAction ParseInternal(Type t, string[] input) { ArgShortcut.RegisterShortcuts(t); ValidateArgScaffold(t); var context = new ArgHook.HookContext(); context.Args = Activator.CreateInstance(t); context.CmdLineArgs = input; t.RunBeforeParse(context); var specifiedActionProperty = FindSpecifiedAction(t, ref context.CmdLineArgs); context.ParserData = ArgParser.Parse(context.CmdLineArgs); PopulateProperties(context); if (specifiedActionProperty != null) { var actionPropertyValue = Activator.CreateInstance(specifiedActionProperty.PropertyType); var toRestore = context.Args; context.Args = actionPropertyValue; PopulateProperties(context); context.Args = toRestore; specifiedActionProperty.SetValue(context.Args, actionPropertyValue, null); } if (context.ParserData.ImplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected unnamed argument: " + context.ParserData.ImplicitParameters.First().Value); } if (context.ParserData.ExplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected named argument: " + context.ParserData.ExplicitParameters.First().Key); } return(new ArgAction() { Value = context.Args, ActionArgs = specifiedActionProperty != null?specifiedActionProperty.GetValue(context.Args, null) : null, ActionArgsProperty = specifiedActionProperty }); }
/// <summary> /// A helper that detects the argument represented by the current token given a definition. /// </summary> /// <param name="contextualAction">An action to inspect for a match if the current token does not match a global argument. Pass null to only check global arguments.</param> /// <param name="currentToken">The token to inspect. If you pass null you will get null back.</param> /// <param name="expectMatchingArg">This will be set to true if the current token starts with a '-' or a '/' meaning that the token was an argument indicator, even if it didn't match an argument in the definition.</param> /// <param name="def">The definition to inspect. If null, the ambient definition will be used. If there is no ambient definition and null is passed then this method throws a NullReferenceException.</param> /// <returns>An argument that is matched by the given token or null if there was no match</returns> public static CommandLineArgument FindCurrentTokenArgument(CommandLineAction contextualAction, string currentToken, out bool expectMatchingArg, CommandLineArgumentsDefinition def = null) { def = PassThroughOrTryGetAmbientDefinition(def); if (currentToken == null) { expectMatchingArg = false; return(null); } string currentTokenArgumentNameValue = null; expectMatchingArg = false; if (ArgParser.IsDashSpecifiedArgumentIdentifier(currentToken)) { currentTokenArgumentNameValue = currentToken.Substring(1); expectMatchingArg = true; } else if (currentToken.StartsWith("/")) { currentTokenArgumentNameValue = currentToken.Substring(1); expectMatchingArg = true; } CommandLineArgument currentTokenArgument = null; if (currentTokenArgumentNameValue != null) { currentTokenArgument = def.Arguments.Where(arg => arg.IsMatch(currentTokenArgumentNameValue)).SingleOrDefault(); if (currentTokenArgument == null && contextualAction != null) { currentTokenArgument = contextualAction.Arguments.Where(arg => arg.IsMatch(currentTokenArgumentNameValue)).SingleOrDefault(); } } return(currentTokenArgument); }
/// <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; } } } }
private ArgAction ParseInternal(CommandLineArgumentsDefinition definition, string[] input) { // TODO - Validation should be consistently done against the definition, not against the raw type if (definition.ArgumentScaffoldType != null) { ValidateArgScaffold(definition.ArgumentScaffoldType); } var context = ArgHook.HookContext.Current; context.Definition = definition; _ambientDefinition = definition; definition.Validate(context); if (definition.ArgumentScaffoldType != null) { context.Args = Activator.CreateInstance(definition.ArgumentScaffoldType); } context.CmdLineArgs = input; context.RunBeforeParse(); context.ParserData = ArgParser.Parse(definition, context.CmdLineArgs); var actionToken = context.CmdLineArgs.FirstOrDefault(); var actionQuery = context.Definition.Actions.Where(a => a.IsMatch(actionToken)); if (actionQuery.Count() == 1) { context.SpecifiedAction = actionQuery.First(); } else if (actionQuery.Count() > 1) { throw new InvalidArgDefinitionException("There are multiple actions that match argument '" + actionToken + "'"); } context.RunBeforePopulateProperties(); CommandLineArgument.PopulateArguments(context.Definition.Arguments, context); context.Definition.SetPropertyValues(context.Args); object actionArgs = null; object[] actionParameters = null; if (context.SpecifiedAction == null && context.Definition.Actions.Count > 0) { if (context.CmdLineArgs.FirstOrDefault() == null) { throw new MissingArgException("No action was specified"); } else { throw new UnknownActionArgException(string.Format("Unknown action: '{0}'", context.CmdLineArgs.FirstOrDefault())); } } else if (context.SpecifiedAction != null) { PropertyInfo actionProp = null; if (context.Definition.ArgumentScaffoldType != null) { actionProp = ArgAction.GetActionProperty(context.Definition.ArgumentScaffoldType); } if (actionProp != null) { actionProp.SetValue(context.Args, context.SpecifiedAction.Aliases.First(), null); } context.ParserData.ImplicitParameters.Remove(0); CommandLineArgument.PopulateArguments(context.SpecifiedAction.Arguments, context); } context.RunAfterPopulateProperties(); if (context.SpecifiedAction != null) { actionArgs = context.SpecifiedAction.PopulateArguments(context.Args, ref actionParameters); } if (context.Definition.Metadata.HasMeta <AllowUnexpectedArgs>() == false) { if (context.ParserData.ImplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected unnamed argument: " + context.ParserData.ImplicitParameters.First().Value); } if (context.ParserData.ExplicitParameters.Count > 0) { throw new UnexpectedArgException("Unexpected named argument: " + context.ParserData.ExplicitParameters.First().Key); } } else { definition.UnexpectedExplicitArguments = context.ParserData.ExplicitParameters; definition.UnexpectedImplicitArguments = context.ParserData.ImplicitParameters; } if (definition.ArgumentScaffoldType != null) { if (AmbientArgs.ContainsKey(definition.ArgumentScaffoldType)) { AmbientArgs[definition.ArgumentScaffoldType] = context.Args; } else { AmbientArgs.Add(definition.ArgumentScaffoldType, context.Args); } } PropertyInfo actionArgsPropertyInfo = null; if (context.SpecifiedAction != null) { if (context.SpecifiedAction.Source is PropertyInfo) { actionArgsPropertyInfo = context.SpecifiedAction.Source as PropertyInfo; } else if (context.SpecifiedAction.Source is MethodInfo) { actionArgsPropertyInfo = new ArgActionMethodVirtualProperty(context.SpecifiedAction.Source as MethodInfo); } } return(new ArgAction() { Value = context.Args, ActionArgs = actionArgs, ActionParameters = actionParameters, ActionArgsProperty = actionArgsPropertyInfo, ActionArgsMethod = context.SpecifiedAction != null ? context.SpecifiedAction.ActionMethod : null, Definition = context.Definition, Context = context, }); }