Beispiel #1
0
 private static void ShowTemplatesFoundMessage(INewCommandInput commandInput)
 {
     if (!string.IsNullOrWhiteSpace(commandInput.TemplateName) || SupportedFilterOptions.SupportedListFilters.Any(filter => filter.IsFilterSet(commandInput)))
     {
         // Templates found matching the following input parameter(s): {0}
         Reporter.Output.WriteLine(string.Format(LocalizableStrings.TemplatesFoundMatchingInputParameters, GetInputParametersString(commandInput)));
         Reporter.Output.WriteLine();
     }
 }
        private async Task <CreationResultStatus> EnterUpdateFlowAsync(INewCommandInput commandInput, CancellationToken cancellationToken)
        {
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));
            cancellationToken.ThrowIfCancellationRequested();

            bool applyUpdates            = commandInput.ApplyUpdates;
            bool allTemplatesUpToDate    = true;
            CreationResultStatus success = CreationResultStatus.Success;
            var managedTemplatePackages  = await _engineEnvironmentSettings.SettingsLoader.TemplatePackagesManager.GetManagedTemplatePackagesAsync().ConfigureAwait(false);

            foreach (var packagesGrouping in managedTemplatePackages.GroupBy(package => package.ManagedProvider))
            {
                var provider = packagesGrouping.Key;
                IReadOnlyList <CheckUpdateResult> checkUpdateResults = await provider.GetLatestVersionsAsync(packagesGrouping, cancellationToken).ConfigureAwait(false);

                DisplayUpdateCheckResults(checkUpdateResults, commandInput, showUpdates: !applyUpdates);
                if (checkUpdateResults.Any(result => !result.Success))
                {
                    success = CreationResultStatus.CreateFailed;
                }
                allTemplatesUpToDate = checkUpdateResults.All(result => result.Success && result.IsLatestVersion);

                if (applyUpdates)
                {
                    IEnumerable <CheckUpdateResult> updatesToApply = checkUpdateResults.Where(update => update.Success && !update.IsLatestVersion && !string.IsNullOrWhiteSpace(update.LatestVersion));
                    if (!updatesToApply.Any())
                    {
                        continue;
                    }

                    Reporter.Output.WriteLine(LocalizableStrings.TemplatePackageCoordinator_Update_Info_PackagesToBeUpdated);
                    foreach (CheckUpdateResult update in updatesToApply)
                    {
                        Reporter.Output.WriteLine($"{update.TemplatePackage.Identifier}::{update.LatestVersion}".Indent());
                    }
                    Reporter.Output.WriteLine();

                    IReadOnlyList <UpdateResult> updateResults = await provider.UpdateAsync(updatesToApply.Select(update => new UpdateRequest(update.TemplatePackage, update.LatestVersion)), cancellationToken).ConfigureAwait(false);

                    foreach (var updateResult in updateResults)
                    {
                        if (!updateResult.Success)
                        {
                            success = CreationResultStatus.CreateFailed;
                        }
                        await DisplayInstallResultAsync(commandInput, updateResult.UpdateRequest.TemplatePackage.DisplayName, updateResult, cancellationToken).ConfigureAwait(false);
                    }
                }
            }

            if (allTemplatesUpToDate)
            {
                Reporter.Output.WriteLine(LocalizableStrings.TemplatePackageCoordinator_Update_Info_AllPackagesAreUpToDate);
            }

            return(success);
        }
Beispiel #3
0
        public static void ShowUsageHelp(INewCommandInput commandInput, ITelemetryLogger telemetryLogger)
        {
            if (commandInput.IsHelpFlagSpecified)
            {
                telemetryLogger.TrackEvent(commandInput.CommandName + "-Help");
            }

            Reporter.Output.WriteLine(commandInput.HelpText);
            Reporter.Output.WriteLine();
        }
Beispiel #4
0
 internal TemplateInvocationCoordinator(ISettingsLoader settingsLoader, INewCommandInput commandInput, ITelemetryLogger telemetryLogger, string commandName, Func <string> inputGetter, New3Callbacks callbacks)
 {
     _settingsLoader  = settingsLoader;
     _environment     = _settingsLoader.EnvironmentSettings;
     _commandInput    = commandInput;
     _telemetryLogger = telemetryLogger;
     _commandName     = commandName;
     _inputGetter     = inputGetter;
     _callbacks       = callbacks;
 }
Beispiel #5
0
 private static Func <PackInfo, bool> PackageMatchFilter(INewCommandInput command)
 {
     return((pack) =>
     {
         if (string.IsNullOrWhiteSpace(command.PackageFilter))
         {
             return true;
         }
         return pack.Name.IndexOf(command.PackageFilter, StringComparison.OrdinalIgnoreCase) > -1;
     });
 }
        public TemplateInvoker(IEngineEnvironmentSettings environment, INewCommandInput commandInput, ITelemetryLogger telemetryLogger, string commandName, Func <string> inputGetter)
        {
            _environment     = environment;
            _commandInput    = commandInput;
            _telemetryLogger = telemetryLogger;
            _commandName     = commandName;
            _inputGetter     = inputGetter;

            _templateCreator = new TemplateCreator(_environment);
            _hostDataLoader  = new HostSpecificDataLoader(_environment.SettingsLoader);
        }
 public TemplateInvocationAndAcquisitionCoordinator(SettingsLoader settingsLoader, INewCommandInput commandInput, TemplateCreator templateCreator, IHostSpecificDataLoader hostDataLoader, ITelemetryLogger telemetryLogger, string defaultLanguage, string commandName, Func <string> inputGetter)
 {
     _settingsLoader  = settingsLoader;
     _environment     = _settingsLoader.EnvironmentSettings;
     _commandInput    = commandInput;
     _templateCreator = templateCreator;
     _hostDataLoader  = hostDataLoader;
     _telemetryLogger = telemetryLogger;
     _defaultLanguage = defaultLanguage;
     _commandName     = commandName;
     _inputGetter     = inputGetter;
 }
        internal static string UninstallCommandExample(this INewCommandInput command, string packageId = "", bool noArgs = false)
        {
            if (noArgs)
            {
                return($"dotnet {command.CommandName} --uninstall");
            }

            if (string.IsNullOrWhiteSpace(packageId))
            {
                return($"dotnet {command.CommandName} --uninstall <PACKAGE_ID>");
            }
            return($"dotnet {command.CommandName} --uninstall {packageId}");
        }
        // This version relies on the commandInput being in the context desired - so the most recent parse would have to have been
        // for what wants to be validated, either:
        //  - not in the context of any template
        //  - in the context of a specific template.
        public static bool ValidateRemainingParameters(INewCommandInput commandInput, out IReadOnlyList<string> invalidParams)
        {
            List<string> badParams = new List<string>();

            if (commandInput.RemainingParameters.Any())
            {
                foreach (string flag in commandInput.RemainingParameters.Keys)
                {
                    badParams.Add(flag);
                }
            }

            invalidParams = badParams;
            return !invalidParams.Any();
        }
        private static string GetInputParametersString(INewCommandInput commandInput)
        {
            string separator = ", ";
            string filters   = string.Join(
                separator,
                SupportedFilterOptions.SupportedListFilters
                .Where(filter => filter.IsFilterSet(commandInput))
                .Select(filter => $"{filter.Name}='{filter.FilterValue(commandInput)}'"));

            return(string.IsNullOrEmpty(commandInput.TemplateName)
                ? filters
                : string.IsNullOrEmpty(filters)
                    ? $"'{commandInput.TemplateName}'"
                    : $"'{commandInput.TemplateName}'" + separator + filters);
        }
        private static void InitializeNuGetCredentialService(INewCommandInput commandInput)
        {
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));

            try
            {
                DefaultCredentialServiceUtility.SetupDefaultCredentialService(new CliNuGetLogger(), !commandInput.IsInteractiveFlagSpecified);
            }
            catch (Exception ex)
            {
                Reporter.Verbose.WriteLine(
                    string.Format(
                        LocalizableStrings.TemplatePackageCoordinator_Verbose_NuGetCredentialServiceError,
                        ex.ToString()));
            }
        }
        public static CreationResultStatus HandleParseError(INewCommandInput commandInput, ITelemetryLogger telemetryLogger)
        {
            TemplateListResolver.ValidateRemainingParameters(commandInput, out IReadOnlyList <string> invalidParams);
            DisplayInvalidParameters(invalidParams);

            // TODO: get a meaningful error message from the parser
            if (commandInput.IsHelpFlagSpecified)
            {
                telemetryLogger.TrackEvent(commandInput.CommandName + "-Help");
                ShowUsageHelp(commandInput);
            }
            else
            {
                Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunHelpForInformationAboutAcceptedParameters, commandInput.CommandName).Bold().Red());
            }

            return(CreationResultStatus.InvalidParamValues);
        }
        private static bool ValidateCommandInput(INewCommandInput commandInput)
        {
            if (string.IsNullOrWhiteSpace(commandInput.TemplateName) && SupportedFilterOptions.SupportedSearchFilters.All(filter => !filter.IsFilterSet(commandInput)))
            {
                Reporter.Error.WriteLine(string.Format(
                                             LocalizableStrings.SearchOnlineErrorNoTemplateNameOrFilter,
                                             string.Join(", ", SupportedFilterOptions.SupportedSearchFilters.Select(f => $"'{f.Name}'")), commandInput.CommandName).Bold().Red());
                return(false);
            }

            if (!string.IsNullOrWhiteSpace(commandInput.TemplateName) && commandInput.TemplateName.Length < 2)
            {
                Reporter.Error.WriteLine(LocalizableStrings.SearchOnlineErrorTemplateNameIsTooShort.Bold().Red());
                return(false);
            }

            return(true);
        }
        internal static bool IsTemplatePackageManipulationFlow(INewCommandInput commandInput)
        {
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));

            if (commandInput.CheckForUpdates || commandInput.ApplyUpdates)
            {
                return(true);
            }
            if (commandInput.ToUninstallList != null)
            {
                return(true);
            }
            if (commandInput.ToInstallList != null && commandInput.ToInstallList.Count > 0 && commandInput.ToInstallList[0] != null)
            {
                return(true);
            }
            return(false);
        }
Beispiel #15
0
        private static string GetLanguageMismatchErrorMessage(INewCommandInput commandInput)
        {
            string inputFlagForm;

            if (commandInput.Tokens.Contains("-lang"))
            {
                inputFlagForm = "-lang";
            }
            else
            {
                inputFlagForm = "--language";
            }

            string invalidLanguageErrorText = LocalizableStrings.InvalidTemplateParameterValues;

            invalidLanguageErrorText += Environment.NewLine + string.Format(LocalizableStrings.InvalidParameterDetail, inputFlagForm, commandInput.Language, "language");
            return(invalidLanguageErrorText);
        }
        internal static string InstallCommandExample(this INewCommandInput command, bool withVersion = false, string packageID = "", string version = "")
        {
            if (string.IsNullOrWhiteSpace(packageID))
            {
                return(withVersion
                    ? $"dotnet {command.CommandName} --install <PACKAGE_ID>::<VERSION>"
                    : $"dotnet {command.CommandName} --install <PACKAGE_ID>");
            }

            if (string.IsNullOrWhiteSpace(version))
            {
                return($"dotnet {command.CommandName} --install {packageID}");
            }
            else
            {
                return($"dotnet {command.CommandName} --install {packageID}::{version}");
            }
        }
Beispiel #17
0
        public static CreationResultStatus HandleParseError(INewCommandInput commandInput, ITelemetryLogger telemetryLogger)
        {
            TemplateListResolver.ValidateRemainingParameters(commandInput, out IReadOnlyList <string> invalidParams);
            DisplayInvalidParameters(invalidParams);

            // TODO: get a meaningful error message from the parser
            if (commandInput.IsHelpFlagSpecified)
            {
                // this code path doesn't go through the full help & usage stack, so needs it's own call to ShowUsageHelp().
                ShowUsageHelp(commandInput, telemetryLogger);
            }
            else
            {
                Reporter.Error.WriteLine(string.Format(LocalizableStrings.RunHelpForInformationAboutAcceptedParameters, commandInput.CommandName).Bold().Red());
            }

            return(CreationResultStatus.InvalidParamValues);
        }
        public static AliasExpansionStatus TryExpandAliases(INewCommandInput commandInput, AliasRegistry aliasRegistry)
        {
            List <string> inputTokens = commandInput.Tokens.ToList();

            inputTokens.RemoveAt(0);    // remove the command name

            if (aliasRegistry.TryExpandCommandAliases(inputTokens, out IReadOnlyList <string> expandedTokens))
            {
                if (!expandedTokens.SequenceEqual(inputTokens))
                {
                    commandInput.ResetArgs(expandedTokens.ToArray());
                    return(AliasExpansionStatus.Expanded);
                }

                return(AliasExpansionStatus.NoChange);
            }

            return(AliasExpansionStatus.ExpansionError);
        }
Beispiel #19
0
        public static AliasExpansionStatus TryExpandAliases(INewCommandInput commandInput, AliasRegistry aliasRegistry)
        {
            List <string> inputTokens = commandInput.Tokens.ToList();

            inputTokens.RemoveAt(0);    // remove the command name

            if (aliasRegistry.TryExpandCommandAliases(inputTokens, out IReadOnlyList <string> expandedTokens))
            {   // TryExpandCommandAliases() return value indicates error (cycle) or not error. It doesn't indicate whether or not expansions actually occurred.
                if (!expandedTokens.SequenceEqual(inputTokens))
                {
                    commandInput.ResetArgs(expandedTokens.ToArray());
                    return(AliasExpansionStatus.Expanded);
                }

                return(AliasExpansionStatus.NoChange);
            }

            return(AliasExpansionStatus.ExpansionError);
        }
Beispiel #20
0
        /// <summary>
        /// Displays the help in case it is not possible to resolve template to use based on user input on template instantiation.
        /// </summary>
        /// <param name="resolutionResult">template resolution result</param>
        /// <param name="environmentSettings"></param>
        /// <param name="commandInput">command input used in CLI</param>
        /// <param name="defaultLanguage">default language for the host</param>
        /// <param name="installUnitDescriptors">the collection of install unit descriptors</param>
        /// <returns></returns>
        internal static CreationResultStatus CoordinateAmbiguousTemplateResolutionDisplay(
            TemplateResolutionResult resolutionResult,
            IEngineEnvironmentSettings environmentSettings,
            INewCommandInput commandInput,
            string defaultLanguage,
            IEnumerable <IInstallUnitDescriptor> installUnitDescriptors)
        {
            switch (resolutionResult.ResolutionStatus)
            {
            case TemplateResolutionResult.Status.NoMatch:
                Reporter.Error.WriteLine(
                    string.Format(LocalizableStrings.NoTemplatesMatchingInputParameters, GetInputParametersString(commandInput)).Bold().Red());
                Reporter.Error.WriteLine(string.Format(LocalizableStrings.ListTemplatesCommand, commandInput.CommandName).Bold().Red());
                Reporter.Error.WriteLine(string.Format(LocalizableStrings.SearchTemplatesCommand, commandInput.CommandName, commandInput.TemplateName).Bold().Red());
                return(CreationResultStatus.NotFound);

            case TemplateResolutionResult.Status.AmbiguousLanguageChoice:
                Reporter.Error.WriteLine(LocalizableStrings.AmbiguousTemplateGroupListHeader.Bold().Red());
                DisplayTemplateList(resolutionResult.TemplateGroups, environmentSettings, commandInput, defaultLanguage, useErrorOutput: true);
                Reporter.Error.WriteLine(LocalizableStrings.AmbiguousLanguageHint.Bold().Red());
                return(CreationResultStatus.NotFound);

            case TemplateResolutionResult.Status.AmbiguousTemplateGroupChoice:
                Reporter.Error.WriteLine(LocalizableStrings.AmbiguousTemplateGroupListHeader.Bold().Red());
                DisplayTemplateList(resolutionResult.TemplateGroups, environmentSettings, commandInput, defaultLanguage, useErrorOutput: true);
                Reporter.Error.WriteLine(LocalizableStrings.AmbiguousTemplateGroupListHint.Bold().Red());
                return(CreationResultStatus.NotFound);

            case TemplateResolutionResult.Status.AmbiguousParameterValueChoice:
                environmentSettings.Host.LogDiagnosticMessage(LocalizableStrings.Authoring_AmbiguousChoiceParameterValue, "Authoring");
                return(DisplayInvalidParameterError(resolutionResult.UnambiguousTemplateGroup, commandInput));

            case TemplateResolutionResult.Status.AmbiguousTemplateChoice:
                environmentSettings.Host.LogDiagnosticMessage(LocalizableStrings.Authoring_AmbiguousBestPrecedence, "Authoring");
                return(DisplayAmbiguousPrecedenceError(resolutionResult.UnambiguousTemplateGroup, environmentSettings, commandInput, installUnitDescriptors));

            case TemplateResolutionResult.Status.InvalidParameter:
                return(DisplayInvalidParameterError(resolutionResult.UnambiguousTemplateGroup, commandInput));
            }

            return(CreationResultStatus.CreateFailed);
        }
Beispiel #21
0
        public New3Command(string commandName, ITemplateEngineHost host, ITelemetryLogger telemetryLogger, Action <IEngineEnvironmentSettings, IInstaller> onFirstRun, INewCommandInput commandInput, string hivePath)
        {
            _telemetryLogger    = telemetryLogger;
            host                = new ExtendedTemplateEngineHost(host, this);
            EnvironmentSettings = new EngineEnvironmentSettings(host, x => new SettingsLoader(x), hivePath);
            _settingsLoader     = (SettingsLoader)EnvironmentSettings.SettingsLoader;
            Installer           = new Installer(EnvironmentSettings);
            _templateCreator    = new TemplateCreator(EnvironmentSettings);
            _aliasRegistry      = new AliasRegistry(EnvironmentSettings);
            CommandName         = commandName;
            _paths              = new Paths(EnvironmentSettings);
            _onFirstRun         = onFirstRun;
            _hostDataLoader     = new HostSpecificDataLoader(EnvironmentSettings.SettingsLoader);
            _commandInput       = commandInput;

            if (!EnvironmentSettings.Host.TryGetHostParamDefault("prefs:language", out _defaultLanguage))
            {
                _defaultLanguage = null;
            }
        }
        private async Task <CreationResultStatus> EnterUninstallFlowAsync(INewCommandInput commandInput, CancellationToken cancellationToken)
        {
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));
            cancellationToken.ThrowIfCancellationRequested();

            CreationResultStatus result = CreationResultStatus.Success;

            if (commandInput.ToUninstallList.Count <= 0 || commandInput.ToUninstallList[0] == null)
            {
                //display all installed template packages
                await DisplayInstalledTemplatePackages(commandInput, cancellationToken).ConfigureAwait(false);

                return(result);
            }

            Dictionary <IManagedTemplatePackageProvider, List <IManagedTemplatePackage> > sourcesToUninstall;

            (result, sourcesToUninstall) = await DetermineSourcesToUninstall(commandInput, cancellationToken).ConfigureAwait(false);

            foreach (KeyValuePair <IManagedTemplatePackageProvider, List <IManagedTemplatePackage> > providerSourcesToUninstall in sourcesToUninstall)
            {
                IReadOnlyList <UninstallResult> uninstallResults = await providerSourcesToUninstall.Key.UninstallAsync(providerSourcesToUninstall.Value, cancellationToken).ConfigureAwait(false);

                foreach (UninstallResult uninstallResult in uninstallResults)
                {
                    if (uninstallResult.Success)
                    {
                        Reporter.Output.WriteLine(
                            string.Format(
                                LocalizableStrings.TemplatePackageCoordinator_Uninstall_Info_Success,
                                uninstallResult.TemplatePackage.DisplayName));
                    }
                    else
                    {
                        Reporter.Error.WriteLine(string.Format(LocalizableStrings.TemplatePackageCoordinator_Uninstall_Error_GenericError, uninstallResult.TemplatePackage.DisplayName, uninstallResult.ErrorMessage));
                        result = CreationResultStatus.CreateFailed;
                    }
                }
            }
            return(result);
        }
        internal Task <CreationResultStatus> ProcessAsync(INewCommandInput commandInput, CancellationToken cancellationToken = default)
        {
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));
            cancellationToken.ThrowIfCancellationRequested();

            if (commandInput.ToUninstallList != null)
            {
                return(EnterUninstallFlowAsync(commandInput, cancellationToken));
            }

            if (commandInput.CheckForUpdates || commandInput.ApplyUpdates)
            {
                InitializeNuGetCredentialService(commandInput);
                return(EnterUpdateFlowAsync(commandInput, cancellationToken));
            }
            if (commandInput.ToInstallList != null && commandInput.ToInstallList.Count > 0 && commandInput.ToInstallList[0] != null)
            {
                InitializeNuGetCredentialService(commandInput);
                return(EnterInstallFlowAsync(commandInput, cancellationToken));
            }
            throw new NotSupportedException($"The operation is not supported, command: {commandInput}.");
        }
Beispiel #24
0
        internal New3Command(string commandName, ITemplateEngineHost host, ITelemetryLogger telemetryLogger, New3Callbacks callbacks, INewCommandInput commandInput, string?hivePath, bool virtualize = false)
        {
            _telemetryLogger    = telemetryLogger;
            host                = new ExtendedTemplateEngineHost(host, this);
            EnvironmentSettings = new EngineEnvironmentSettings(host, settingsLocation: hivePath, onFirstRun: FirstRun, virtualizeSettings: virtualize);
            _settingsLoader     = EnvironmentSettings.SettingsLoader;
            _templateCreator    = new TemplateCreator(EnvironmentSettings);
            _aliasRegistry      = new AliasRegistry(EnvironmentSettings);
            CommandName         = commandName;
            _hostDataLoader     = new HostSpecificDataLoader(EnvironmentSettings.SettingsLoader);
            _commandInput       = commandInput;
            _callbacks          = callbacks;
            if (callbacks == null)
            {
                callbacks = new New3Callbacks();
            }

            if (!EnvironmentSettings.Host.TryGetHostParamDefault("prefs:language", out _defaultLanguage))
            {
                _defaultLanguage = null;
            }
        }
Beispiel #25
0
        public static CreationResultStatus CoordinateAliasExpansion(INewCommandInput commandInput, AliasRegistry aliasRegistry, ITelemetryLogger telemetryLogger)
        {
            AliasExpansionStatus aliasExpansionStatus = AliasSupport.TryExpandAliases(commandInput, aliasRegistry);

            if (aliasExpansionStatus == AliasExpansionStatus.ExpansionError)
            {
                Reporter.Output.WriteLine(LocalizableStrings.AliasExpansionError);
                return(CreationResultStatus.InvalidParamValues);
            }
            else if (aliasExpansionStatus == AliasExpansionStatus.Expanded)
            {
                Reporter.Output.WriteLine(string.Format(LocalizableStrings.AliasCommandAfterExpansion, string.Join(" ", commandInput.Tokens)));

                if (commandInput.HasParseError)
                {
                    Reporter.Output.WriteLine(LocalizableStrings.AliasExpandedCommandParseError);
                    return(HelpForTemplateResolution.HandleParseError(commandInput, telemetryLogger));
                }
            }

            // this is both for success and for no action.
            return(CreationResultStatus.Success);
        }
        internal void DisplayUpdateCheckResult(CheckUpdateResult versionCheckResult, INewCommandInput commandInput)
        {
            _ = versionCheckResult ?? throw new ArgumentNullException(nameof(versionCheckResult));
            _ = commandInput ?? throw new ArgumentNullException(nameof(commandInput));

            if (versionCheckResult.Success)
            {
                if (!versionCheckResult.IsLatestVersion)
                {
                    string displayString = $"{versionCheckResult.TemplatePackage.Identifier}::{versionCheckResult.TemplatePackage.Version}";         // the package::version currently installed
                    Reporter.Output.WriteLine(string.Format(LocalizableStrings.TemplatePackageCoordinator_Update_Info_UpdateAvailable, displayString));

                    Reporter.Output.WriteLine(LocalizableStrings.TemplatePackageCoordinator_Update_Info_UpdateSingleCommandHeader);
                    Reporter.Output.WriteCommand(commandInput.InstallCommandExample(
                                                     packageID: versionCheckResult.TemplatePackage.Identifier,
                                                     version: versionCheckResult.LatestVersion));
                }
            }
            else
            {
                HandleUpdateCheckErrors(versionCheckResult);
            }
        }
        public TemplateManager()
        {
            var host = new ExtendedTemplateEngineHost(CreateHost(false), this);

            EnvironmentSettings = new EngineEnvironmentSettings(host, x => new SettingsLoader(x), null);
            _settingsLoader     = (SettingsLoader)EnvironmentSettings.SettingsLoader;
            Installer           = new Installer(EnvironmentSettings);
            _templateCreator    = new TemplateCreator(EnvironmentSettings);
            _aliasRegistry      = new AliasRegistry(EnvironmentSettings);
            CommandName         = CommandNameString;
            _paths          = new Paths(EnvironmentSettings);
            _onFirstRun     = FirstRun;
            _hostDataLoader = new HostSpecificDataLoader(EnvironmentSettings.SettingsLoader);
            _commandInput   = new NewCommandInputCli(CommandNameString);

            if (!EnvironmentSettings.Host.TryGetHostParamDefault("prefs:language", out _defaultLanguage))
            {
                _defaultLanguage = null;
            }

            _commandInput.ResetArgs();

            Initialise();
        }
        // adds dispositions to the templates based on matches between the input parameters & the template parameters.
        private static void AddParameterMatchingToTemplates(IReadOnlyCollection<ITemplateMatchInfo> templatesToFilter, IHostSpecificDataLoader hostDataLoader, INewCommandInput commandInput)
        {
            foreach (ITemplateMatchInfo template in templatesToFilter)
            {
                try
                {
                    ParseTemplateArgs(template.Info, hostDataLoader, commandInput);

                    // params are already parsed. But choice values aren't checked
                    foreach (KeyValuePair<string, string> matchedParamInfo in commandInput.InputTemplateParams)
                    {
                        string paramName = matchedParamInfo.Key;
                        string paramValue = matchedParamInfo.Value;

                        if (template.Info.Tags.TryGetValue(paramName, out ICacheTag paramDetails))
                        {
                            if (string.IsNullOrEmpty(paramValue)
                                && paramDetails is IAllowDefaultIfOptionWithoutValue paramDetailsWithNoValueDefault
                                && !string.IsNullOrEmpty(paramDetailsWithNoValueDefault.DefaultIfOptionWithoutValue))
                            {
                                // The user provided the param switch on the command line, without a value.
                                // In this case, the DefaultIfOptionWithoutValue is the effective value.
                                paramValue = paramDetailsWithNoValueDefault.DefaultIfOptionWithoutValue;
                            }

                            // key is the value user should provide, value is description
                            if (string.IsNullOrEmpty(paramValue))
                            {
                                template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.InvalidParameterValue, InputParameterName = paramName, ParameterValue = paramValue });
                            }
                            else if (paramDetails.ChoicesAndDescriptions.ContainsKey(paramValue))
                            {
                                template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.Exact, InputParameterName = paramName, ParameterValue = paramValue });
                            }
                            else
                            {
                                int startsWithCount = paramDetails.ChoicesAndDescriptions.Count(x => x.Key.StartsWith(paramValue, StringComparison.OrdinalIgnoreCase));
                                if (startsWithCount == 1)
                                {
                                    template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.SingleStartsWith, InputParameterName = paramName, ParameterValue = paramValue });
                                }
                                else if (startsWithCount > 1)
                                {
                                    template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.AmbiguousParameterValue, InputParameterName = paramName, ParameterValue = paramValue });
                                }
                                else
                                {
                                    template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.InvalidParameterValue, InputParameterName = paramName, ParameterValue = paramValue });
                                }
                            }
                        }
                        else if (template.Info.CacheParameters.ContainsKey(paramName))
                        {
                            template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.Exact, InputParameterName = paramName, ParameterValue = paramValue });
                        }
                        else
                        {
                            template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.InvalidParameterValue, InputParameterName = paramName, ParameterValue = paramValue });
                        }
                    }

                    foreach (string unmatchedParamName in commandInput.RemainingParameters.Keys.Where(x => !x.Contains(':')))   // filter debugging params
                    {
                        if (commandInput.TryGetCanonicalNameForVariant(unmatchedParamName, out string canonical))
                        {
                            // the name is a known template param, it must have not parsed due to an invalid value
                            // Note (scp 2017-02-27): This probably can't happen, the param parsing doesn't check the choice values.
                            template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.InvalidParameterValue, InputParameterName = unmatchedParamName });
                        }
                        else
                        {
                            // the name is not known
                            // TODO: reconsider storing the canonical in this situation. It's not really a canonical since the param is unknown.
                            template.AddDisposition(new MatchInfo { Location = MatchLocation.OtherParameter, Kind = MatchKind.InvalidParameterName, InputParameterName = unmatchedParamName });
                        }
                    }
                }
                catch (CommandParserException ex)
                {
                    // if we do actually throw, add a non-match
                    template.AddDisposition(new MatchInfo { Location = MatchLocation.Unspecified, Kind = MatchKind.Unspecified, AdditionalInformation = ex.Message });
                }
                catch (Exception ex)
                {
                    template.AddDisposition(new MatchInfo { Location = MatchLocation.Unspecified, Kind = MatchKind.Unspecified, AdditionalInformation = $"Unexpected error: {ex.Message}" });
                }
            }
        }
        // Query for template matches, filtered by everything available: name, language, context, parameters, and the host file.
        // this method is not used for list and help
        public static IReadOnlyCollection<ITemplateMatchInfo> PerformCoreTemplateQuery(IReadOnlyList<ITemplateInfo> templateInfo, IHostSpecificDataLoader hostDataLoader, INewCommandInput commandInput, string defaultLanguage)
        {
            IReadOnlyList<FilterableTemplateInfo> filterableTemplateInfo = SetupFilterableTemplateInfoFromTemplateInfo(templateInfo);

            IReadOnlyCollection<ITemplateMatchInfo> templates = TemplateListFilter.GetTemplateMatchInfo
            (
                filterableTemplateInfo,
                TemplateListFilter.PartialMatchFilter,
                WellKnownSearchFilters.NameFilter(commandInput.TemplateName),
                WellKnownSearchFilters.ClassificationsFilter(commandInput.TemplateName),
                WellKnownSearchFilters.LanguageFilter(commandInput.Language),
                WellKnownSearchFilters.ContextFilter(commandInput.TypeFilter),
                WellKnownSearchFilters.BaselineFilter(commandInput.BaselineName)
            )
            .Where(x => !IsTemplateHiddenByHostFile(x.Info, hostDataLoader)).ToList();

            IReadOnlyList<ITemplateMatchInfo> coreMatchedTemplates = templates.Where(x => x.IsMatch).ToList();

            if (coreMatchedTemplates.Count == 0)
            {
                // No exact matches, take the partial matches and be done.
                coreMatchedTemplates = templates.Where(x => x.IsPartialMatch).ToList();
            }
            else
            {
                IReadOnlyList<ITemplateMatchInfo> matchesWithExactDispositionsInNameFields = coreMatchedTemplates.Where(x => x.MatchDisposition.Any(y => NameFields.Contains(y.Location) && y.Kind == MatchKind.Exact)).ToList();

                if (matchesWithExactDispositionsInNameFields.Count > 0)
                {
                    // Start with the exact name matches, if there are any.
                    coreMatchedTemplates = matchesWithExactDispositionsInNameFields;
                }
            }

            if (string.IsNullOrEmpty(commandInput.Language) && !string.IsNullOrEmpty(defaultLanguage))
            {
                // default language matching only makes sense if the user didn't specify a language.
                AddDefaultLanguageMatchingToTemplates(coreMatchedTemplates, defaultLanguage);
            }

            AddParameterMatchingToTemplates(coreMatchedTemplates, hostDataLoader, commandInput);

            return coreMatchedTemplates;
        }
        /// <summary>
        /// Performs filtering of provided template list for --search option. Filters applied: template name filter, --search option filters, template parameters filter.
        /// Only templates that exactly match the filters are returned.
        /// </summary>
        /// <param name="templateInfo">the list of templates to be filtered</param>
        /// <param name="hostDataLoader">data of the host</param>
        /// <param name="commandInput">new command data used in CLI</param>
        /// <returns>filtered list of templates</returns>
        public static IReadOnlyCollection<ITemplateMatchInfo> PerformCoreTemplateQueryForSearch(IEnumerable<ITemplateInfo> templateInfo, IHostSpecificDataLoader hostDataLoader, INewCommandInput commandInput)
        {
            IReadOnlyList<FilterableTemplateInfo> filterableTemplateInfo = SetupFilterableTemplateInfoFromTemplateInfo(templateInfo.ToList());
            List<Func<ITemplateInfo, MatchInfo?>> searchFilters = new List<Func<ITemplateInfo, MatchInfo?>>()
            {
                WellKnownSearchFilters.NameFilter(commandInput.TemplateName),
            };
            searchFilters.AddRange(SupportedFilterOptions.SupportedSearchFilters
                                    .OfType<TemplateFilterOption>()
                                    .Select(filter => filter.TemplateMatchFilter(commandInput)));

            IReadOnlyCollection<ITemplateMatchInfo> matchedTemplates = TemplateListFilter.GetTemplateMatchInfo(filterableTemplateInfo, TemplateListFilter.ExactMatchFilter, searchFilters.ToArray());

            AddParameterMatchingToTemplates(matchedTemplates, hostDataLoader, commandInput);
            return matchedTemplates.Where(t => t.IsInvokableMatch()).ToList();
        }