예제 #1
0
        public static OptionDefinition <TSettings> Create <TPropertyValue>(
            string longForm,
            string?shortForm,
            Expression <Func <TSettings, TPropertyValue> > property,
            Conversion <TPropertyValue> conversion)
        {
            if (property is null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            if (conversion is null)
            {
                throw new ArgumentNullException(nameof(conversion));
            }

            var        longFormOptionName  = OptionName.FromLongForm(longForm);
            OptionName?shortFormOptionName = default;

            if (!(shortForm is null))
            {
                shortFormOptionName = OptionName.FromShortForm(shortForm);
            }

            var applicator = Converter <TPropertyValue> .CreateOptionConverter(longFormOptionName, shortFormOptionName, property, conversion);

            return(new OptionDefinition <TSettings>(longFormOptionName, shortFormOptionName, applicator));
        }
예제 #2
0
 private OptionDefinition(
     OptionName longForm,
     OptionName?shortForm,
     Func <object, string, ApplicationResult> applicator)
 {
     this.longForm   = longForm;
     this.shortForm  = shortForm;
     this.applicator = applicator;
 }
예제 #3
0
 internal UntypedOptionDefinition(
     OptionName longForm,
     OptionName?shortForm,
     Func <object, string, ApplicationResult> applicator)
 {
     this.LongForm   = longForm;
     this.ShortForm  = shortForm;
     this.Applicator = applicator;
 }
예제 #4
0
 public UntypedSwitchDefinition(
     OptionName longForm,
     OptionName?shortForm,
     Action <object> applicator)
 {
     this.LongForm   = longForm;
     this.ShortForm  = shortForm;
     this.Applicator = applicator;
 }
 private SwitchDefinition(
     OptionName longForm,
     OptionName?shortForm,
     Action <TSettings> applicator)
 {
     this.longForm   = longForm;
     this.shortForm  = shortForm;
     this.Applicator = applicator;
 }
예제 #6
0
        private static string CombineLongAndShortFormForError(OptionName longForm, OptionName?shortForm)
        {
            var value = longForm.ToString();

            if (!(shortForm is null))
            {
                value += $", {shortForm}";
            }

            return(value);
        }
        public static SwitchDefinition <TSettings> Create(
            string longForm,
            string?shortForm,
            Action <TSettings> applicator)
        {
            if (applicator is null)
            {
                throw new ArgumentNullException(nameof(applicator));
            }

            var        longFormOptionName  = OptionName.FromLongForm(longForm);
            OptionName?shortFormOptionName = default;

            if (!(shortForm is null))
            {
                shortFormOptionName = OptionName.FromShortForm(shortForm);
            }

            return(new SwitchDefinition <TSettings>(longFormOptionName, shortFormOptionName, applicator));
        }
예제 #8
0
        public bool TryConsume(
            ParseContext parseContext,
            ReadOnlySpan <string> args,
            [NotNullWhen(true)]
            out IEntrypoint?entrypoint)
        {
            // the root command should always try and consume.
            if (!this.IsRootCommand())
            {
                if (args.Length == 0 ||
                    !CommandName.TryConstruct(args[0], out var name) ||
                    !this.name.Equals(name))
                {
                    entrypoint = null;
                    return(false);
                }

                // consume the name of this command
                args = args.Slice(1);
            }

            // we've matched this command. So go ahead and add all the setting defaults since
            // we want to apply them hierarchically in order
            if (this.settingDefaultApplicators != null)
            {
                parseContext.SettingDefaultApplicators.AddRange(
                    this.settingDefaultApplicators.Select(x => x.Applicator));
            }

            while (
                this.TryConsumeSwitch(parseContext, ref args) ||
                this.TryConsumeOption(parseContext, ref args))
            {
                // this will eventually fail
            }

            // Recursively consume if this command has children
            foreach (var tokenConsumer in this.children)
            {
                if (tokenConsumer.TryConsume(parseContext, args, out entrypoint))
                {
                    return(true);
                }
            }

            var positionalIndex = 0;

            while (this.TryConsumeSwitch(parseContext, ref args) ||
                   this.TryConsumeOption(parseContext, ref args) ||
                   this.TryConsumePositional(parseContext, ref args, ref positionalIndex))
            {
                // this will fail eventually
            }

            // at this point there is nothing left to consume. Start error checking.
            // error check leftover arguments
            if (args.Length > 0)
            {
                string error;
                if (OptionName.LooksLikeOptionOrSwitch(args[0]))
                {
                    error = $"Unrecognized option or switch { args[0] }";
                }
                else if (this.IsTerminalCommand())
                {
                    error = $"Unrecognized positional: { args[0] }";
                }
                else
                {
                    error = $"Unrecognized command: { args[0] }";
                }
                entrypoint = new ErrorEntrypoint(parseContext, error);
                return(true);
            }

            // If positionals exist, ensure all required ones were given a value
            if (this.positionalApplicators != null &&
                positionalIndex < this.positionalApplicators.Count &&
                this.positionalApplicators[positionalIndex].Required)
            {
                string error;
                if (this.positionalApplicators.Count - positionalIndex == 1)
                {
                    error = $"Required positional '{this.positionalApplicators[positionalIndex].Name}' was not given a value.";
                }
                else
                {
                    error = $"Required positionals '{string.Join("', '", this.positionalApplicators.Skip(positionalIndex).Select(x => x.Name)) }' were not given values.";
                }
                entrypoint = new ErrorEntrypoint(parseContext, error);
                return(true);
            }

            if (this.IsTerminalCommand())
            {
                if (this.settingsType != null)
                {
                    var settings = Activator.CreateInstance(this.settingsType);
                    if (settings == null)
                    {
                        throw new Exception($"Unable to create settings type { this.settingsType.FullName }");
                    }

                    foreach (var applicator in parseContext.SettingDefaultApplicators)
                    {
                        applicator(settings);
                    }

                    foreach (var applicator in parseContext.OptionApplicators)
                    {
                        var result = applicator(settings);
                        if (!result.IsSuccess)
                        {
                            entrypoint = new ErrorEntrypoint(parseContext, result.Error);
                            return(true);
                        }
                    }

                    foreach (var applicator in parseContext.SwitchApplicators)
                    {
                        applicator(settings);
                    }

                    if (this.positionalApplicators != null)
                    {
                        foreach (var applicator in parseContext.PositionalApplicators)
                        {
                            var application = applicator(settings);
                            if (!application.IsSuccess)
                            {
                                entrypoint = new ErrorEntrypoint(parseContext, application.Error);
                                return(true);
                            }
                        }
                    }

                    var actualEntrypoint = Activator.CreateInstance(this.entrypointType !) !;

                    entrypoint = (IEntrypoint?)Activator.CreateInstance(
                        typeof(EntrypointWithSettingThunk <>).MakeGenericType(this.settingsType !),
                        new object[]
                    {
                        actualEntrypoint,
                        settings
                    });

                    return(true);
                }
                else
                {
                    entrypoint = (IEntrypoint?)Activator.CreateInstance(this.entrypointType !);
                    return(true);
                }
            }
            else
            {
                string error;
                if (this.IsRootCommand())
                {
                    error = $"No subcommand given.";
                }
                else
                {
                    error = $"Command { this.name } requires a subcommand.";
                }

                entrypoint = new HelpEntrypoint(parseContext, this, error);
                return(true);
            }
        }
예제 #9
0
 internal static Func <object, string, ApplicationResult> CreateOptionConverter <TSettings>(OptionName longForm, OptionName?shortForm, Expression <Func <TSettings, T> > property, Conversion <T> converter)
 => CreateConverter <TSettings>(property, converter, s => $"Value '{ s }' was not convertable for option [{ CombineLongAndShortFormForError(longForm, shortForm) }].");