/// <summary> /// Create a new instance of <see cref="CommandLine"/> from <see cref="PredictiveCommand" />. /// </summary> /// <param name="predictiveCommand">The command information.</param> /// <param name="azContext">The current PowerShell conext.</param> public CommandLine(PredictiveCommand predictiveCommand, IAzContext azContext = null) { Validation.CheckArgument(predictiveCommand, $"{nameof(predictiveCommand)} cannot be null."); var predictionText = CommandLineUtilities.EscapePredictionText(predictiveCommand.Command); var commandAst = CommandLineUtilities.GetCommandAst(predictionText); var commandName = commandAst?.GetCommandName(); Validation.CheckInvariant <CommandLineException>(!string.IsNullOrWhiteSpace(commandName), $"Cannot get the command name from the model {predictiveCommand.Command}"); var parameterSet = new ParameterSet(commandAst, azContext); Name = commandName; Description = predictiveCommand.Description; ParameterSet = parameterSet; SourceText = predictiveCommand.Command; }
/// <summary> /// Create a new instance of <see cref="CommandLine"/> from <see cref="PredictiveCommand" />. /// </summary> /// <param name="predictiveCommand">The command information.</param> /// <param name="azContext">The current PowerShell conext.</param> public CommandLine(PredictiveCommand predictiveCommand, IAzContext azContext = null) { Validation.CheckArgument(predictiveCommand, $"{nameof(predictiveCommand)} cannot be null."); var predictionText = CommandLineUtilities.EscapePredictionText(predictiveCommand.Command); Ast ast = Parser.ParseInput(predictionText, out Token[] tokens, out _); var commandAst = ast.Find((ast) => ast is CommandAst, searchNestedScriptBlocks: false) as CommandAst; var commandName = commandAst?.GetCommandName(); Validation.CheckInvariant <CommandLineException>(!string.IsNullOrWhiteSpace(commandName), $"Cannot get the command name from the model {predictiveCommand.Command}"); var parameterSet = new ParameterSet(commandAst, azContext); Name = commandName; Description = predictiveCommand.Description; ParameterSet = parameterSet; SourceText = predictiveCommand.Command; }
/// <summary> /// Creates a new instance of <see cref="CommandLinePredictor"/>. /// </summary> /// <param name="modelPredictions">List of suggestions from the model, sorted by frequency (most to least).</param> /// <param name="parameterValuePredictor">Provide the prediction to the parameter values.</param> public CommandLinePredictor(IList <PredictiveCommand> modelPredictions, ParameterValuePredictor parameterValuePredictor) { Validation.CheckArgument(modelPredictions, $"{nameof(modelPredictions)} cannot be null."); _parameterValuePredictor = parameterValuePredictor; var commnadLines = new List <CommandLine>(); foreach (var predictiveCommand in modelPredictions ?? Enumerable.Empty <PredictiveCommand>()) { var predictionText = CommandLineUtilities.EscapePredictionText(predictiveCommand.Command); Ast ast = Parser.ParseInput(predictionText, out Token[] tokens, out _); var commandAst = (ast.Find((ast) => ast is CommandAst, searchNestedScriptBlocks: false) as CommandAst); if (commandAst?.CommandElements[0] is StringConstantExpressionAst commandName) { var parameterSet = new ParameterSet(commandAst); this._commandLinePredictions.Add(new CommandLine(commandName.Value, predictiveCommand.Description, parameterSet)); } } }
public ParameterSet(CommandAst commandAst, IAzContext azContext = null) { Validation.CheckArgument(commandAst, $"{nameof(commandAst)} cannot be null."); _commandAst = commandAst; _azContext = azContext; var parameters = new List <Parameter>(); CommandParameterAst param = null; Ast arg = null; // positional parameters must be before named parameters. // This loop will convert them to named parameters. // Loop through all the parameters. The first element of CommandElements is the command name, so skip it. bool hasSeenNamedParameter = false; bool hasSeenIncompleteParameter = false; for (var i = 1; i < commandAst.CommandElements.Count(); ++i) { var elem = commandAst.CommandElements[i]; if (elem is CommandParameterAst p) { if (hasSeenIncompleteParameter) { throw new CommandLineException("'-' is in the middle of the parameter list."); } hasSeenNamedParameter = true; AddNamedParameter(param, arg); // In case there is a switch parameter, we store the parameter name/value and add them when we see the next pair. param = p; arg = null; } else if (AzPredictorConstants.ParameterIndicator == elem?.ToString().Trim().FirstOrDefault()) { // We have an incomplete command line such as // `New-AzResourceGroup -Name ResourceGroup01 -Location WestUS -` // We'll ignore the incomplete parameter. AddNamedParameter(param, arg); param = null; arg = null; hasSeenIncompleteParameter = true; parameters.Add(new Parameter(AzPredictorConstants.DashParameterName, null, false)); } else { if (hasSeenIncompleteParameter || (hasSeenNamedParameter && param == null)) { throw new CommandLineException("Positional parameters must be before named parameters."); } if (param == null) { // This is a positional parameter. var pair = BoundParameters.First((pair) => pair.Value.Value == elem); var parameterName = pair.Key; var parameterValue = CommandLineUtilities.EscapePredictionText(pair.Value.Value.ToString()); parameters.Add(new Parameter(parameterName, parameterValue, true)); BoundParameters.Remove(pair); // Remove it so that we can match another parameter with the same value. } else { arg = elem; AddNamedParameter(param, arg); param = null; arg = null; } } } Validation.CheckInvariant <CommandLineException>((param != null) || (arg == null)); AddNamedParameter(param, arg); Parameters = parameters; void AddNamedParameter(CommandParameterAst parameter, Ast parameterValue) { if (parameter != null) { var value = parameterValue?.ToString(); if (value == null) { value = parameter.Argument?.ToString(); } if (value != null) { value = CommandLineUtilities.UnescapePredictionText(value); } parameters.Add(new Parameter(parameter.ParameterName, value, false)); } } }
public void VerifyEscapingText(string expected, string input) { var actual = CommandLineUtilities.EscapePredictionText(input); Assert.Equal(expected, actual); }