Esempio n. 1
0
#pragma warning disable RS0026 // Do not add multiple public overloads with optional parameters

        /// <summary>
        /// Constructor that requires an explicit implementation of
        /// <see cref="ILoopClient"/>.
        /// </summary>
        /// <param name="commandType">Type that defines syntax for commands.</param>
        /// <param name="loopClient">The client to use.</param>
        /// <param name="argSetAttribute">Optionally provides attribute info
        /// for the argument set that will be dynamically created for this loop.</param>
        /// <param name="options">Optionally provides additional options for
        /// this loop's execution.</param>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="commandType" />
        /// is null.</exception>
        public Loop(Type commandType, ILoopClient loopClient, ArgumentSetAttribute argSetAttribute = null, LoopOptions options = null)
        {
            if (commandType == null)
            {
                throw new ArgumentNullException(nameof(commandType));
            }

            _client = loopClient ?? throw new ArgumentNullException(nameof(loopClient));
            _client.TokenCompleter = new TokenCompleter(this);

            _options = options?.DeepClone() ?? new LoopOptions();
            _options.ParserOptions.DisplayUsageInfoOnError = false;
            _options.ParserOptions.Reporter = error => _client.OnError(error.ToString().TrimEnd());

            var inputConfigurer = _options.ParserOptions.ServiceConfigurer;

            _options.ParserOptions.ServiceConfigurer = collection => ConfigureServices(collection, inputConfigurer);

            var constructedType = ConstructCommandTypeFactory(commandType, out _objectFactory);

            _argSet = AttributeBasedArgumentDefinitionFactory.CreateArgumentSet(
                constructedType,
                attribute: argSetAttribute,
                serviceConfigurer: _options.ParserOptions.ServiceConfigurer);
        }
Esempio n. 2
0
        private static ArgumentDefinition CreateArgumentDescriptor(
            IMutableMemberInfo member,
            ArgumentBaseAttribute attribute,
            object defaultValues,
            ArgumentSetAttribute setAttribute,
            CommandLineParserOptions options,
            object fixedDestination)
        {
            if (!member.IsReadable || !member.IsWritable)
            {
                var declaringType = member.MemberInfo.DeclaringType;

                throw new InvalidArgumentSetException(member, string.Format(
                                                          CultureInfo.CurrentCulture,
                                                          Strings.MemberNotSupported,
                                                          member.MemberInfo.Name,
                                                          declaringType?.Name));
            }

            var defaultFieldValue = (defaultValues != null) ? member.GetValue(defaultValues) : null;

            return(new ArgumentDefinition(member,
                                          attribute,
                                          setAttribute,
                                          options,
                                          defaultFieldValue,
                                          fixedDestination: fixedDestination));
        }
Esempio n. 3
0
        public void InvalidSeparators()
        {
            var    attribs       = new ArgumentSetAttribute();
            Action setSeparators = () => attribs.ArgumentValueSeparators = null;

            setSeparators.ShouldThrow <ArgumentNullException>();
        }
Esempio n. 4
0
        public override CommandResult Execute()
        {
            Console.WriteLine("Entering loop.");

            var keyBindingSet = ConsoleKeyBindingSet.CreateDefaultSet();

            keyBindingSet.Bind('c', ConsoleModifiers.Control, ConsoleInputOperation.Abort);

            ++_count;

            var parameters = new LoopInputOutputParameters
            {
                Prompt                    = new ColoredString($"Loop{new string('>', _count)} ", ConsoleColor.Cyan),
                KeyBindingSet             = keyBindingSet,
                EndOfLineCommentCharacter = '#'
            };

            var attrib = new ArgumentSetAttribute
            {
                Style = ArgumentSetStyle.GetOpt
            };

            new Loop(typeof(MainCommandType), parameters, attrib).Execute();

            --_count;

            Console.WriteLine("Exited loop.");

            return(CommandResult.Success);
        }
        public void InvalidSeparators()
        {
            var attribs = new ArgumentSetAttribute();

            attribs.ArgumentValueSeparators = null;
            attribs.ArgumentValueSeparators.Should().NotBeNull();
            attribs.ArgumentValueSeparators.Should().BeEmpty();
        }
        public void SelectingInvalidStyleThrows()
        {
            var attrib = new ArgumentSetAttribute();

            Action a = () => attrib.Style = (ArgumentSetStyle)0xFF;

            a.Should().Throw <ArgumentOutOfRangeException>();
        }
        public void StyleIsUnreadable()
        {
            var attrib = new ArgumentSetAttribute();

            Action a = () => { var x = attrib.Style; };

            a.Should().Throw <NotSupportedException>();
        }
        public void TestThatLogoIsSettableWithString()
        {
            var attrib = new ArgumentSetAttribute {
                Logo = "Test"
            };

            attrib.Logo.Should().BeOfType <string>().And.Be("Test");
        }
        public void TestThatLogoIsNotSettableWithColoredString()
        {
            var attrib = new ArgumentSetAttribute();

            Action a = () => attrib.Logo = new ColoredString("Test", ConsoleColor.Yellow);

            a.Should().Throw <ArgumentOutOfRangeException>();
        }
        public void TestThatLogoThrowsOnUnsupportedTypes()
        {
            var attrib = new ArgumentSetAttribute();

            Action a = () => { attrib.Logo = 3; };

            a.Should().Throw <ArgumentOutOfRangeException>();
        }
Esempio n. 11
0
        public void LogoIsSettableWithString()
        {
            var attrib = new ArgumentSetAttribute {
                Logo = "Test"
            };

            attrib.LogoString.ToString().Should().Be("Test");
        }
        public void TestThatLogoStringIsFixedToNull()
        {
            var attrib = new ArgumentSetAttribute();

#pragma warning disable CS0618 // Type or member is obsolete
            attrib.LogoString.Should().BeNull();
#pragma warning restore CS0618 // Type or member is obsolete
        }
Esempio n. 13
0
        /// <summary>
        /// Primary constructor.
        /// </summary>
        /// <param name="member">Field to describe.</param>
        /// <param name="attribute">Argument attribute on the field.</param>
        /// <param name="setAttribute">Attribute on the containing argument set.</param>
        /// <param name="options">Provides parser options.</param>
        /// <param name="defaultFieldValue">Default value for the field.</param>
        /// <param name="parentMember">Parent member under which this field sits.</param>
        /// <param name="fixedDestination">Optionally provides fixed parse destination object.</param>
        public ArgumentDefinition(IMutableMemberInfo member,
                                  ArgumentBaseAttribute attribute,
                                  ArgumentSetAttribute setAttribute,
                                  CommandLineParserOptions options,
                                  object defaultFieldValue        = null,
                                  IMutableMemberInfo parentMember = null,
                                  object fixedDestination         = null)
        {
            Debug.Assert(attribute != null);
            Debug.Assert(member != null);

            Member                = member;
            ParentMember          = parentMember;
            Attribute             = attribute;
            _setAttribute         = setAttribute;
            FixedDestination      = fixedDestination;
            _isPositional         = attribute is PositionalArgumentAttribute;
            _reporter             = options?.Reporter ?? (s => { });
            ArgumentType          = Attribute.GetArgumentType(member.MemberType);
            _collectionArgType    = AsCollectionType(ArgumentType);
            HasDefaultValue       = attribute.ExplicitDefaultValue || attribute.DynamicDefaultValue;
            _validationAttributes = GetValidationAttributes(ArgumentType, Member);
            _argumentParseContext = CreateParseContext(attribute, _setAttribute, options);

            LongName          = GetLongName(attribute, setAttribute, member.MemberInfo);
            ExplicitShortName = HasExplicitShortName(attribute);
            ShortName         = GetShortName(attribute, setAttribute, member.MemberInfo);
            DefaultValue      = GetDefaultValue(attribute, member, defaultFieldValue);

            var nullableBase = Nullable.GetUnderlyingType(member.MemberType);

            if (_collectionArgType != null)
            {
                _collectionValues = new ArrayList();
                _valueType        = _collectionArgType.ElementType;
            }
            else if (nullableBase != null)
            {
                // For nullable arguments, we use the wrapped type (T in
                // Nullable<T>) as the value type. Parsing an enum or int is the
                // same as parsing an enum? or int?, for example, since null can
                // only arise if the value was not provided at all.
                _valueType = Attribute.GetArgumentType(nullableBase);
            }
            else
            {
                _valueType = ArgumentType;
            }

            Debug.Assert(_valueType != null);

            if (Unique && !IsCollection)
            {
                throw new InvalidArgumentSetException(member, Strings.UniqueUsedOnNonCollectionArgument);
            }

            Debug.Assert(!string.IsNullOrEmpty(LongName));
        }
Esempio n. 14
0
        /// <summary>
        /// Constructs an empty argument set.
        /// </summary>
        /// <param name="options">Optionally provides additional options
        /// controlling how parsing proceeds.</param>
        /// <param name="setAttribute">Optionally provides attribute information
        /// describing the attribute set.</param>
        public ArgumentSetDefinition(CommandLineParserOptions options = null, ArgumentSetAttribute setAttribute = null)
        {
            // Save off the options provided; if none were provided, construct some defaults.
            _options = options?.Clone() ?? new CommandLineParserOptions();

            // Save off set attributes; if none were provided, construct some defaults.
            Attribute = setAttribute ?? new ArgumentSetAttribute();

            // Set up private fields dependent on the ArgumentSetAttribute.
            _namedArgumentsByName = new Dictionary <string, ArgumentDefinition>(StringComparerToUse);
        }
Esempio n. 15
0
        public void LogoIsSettableWithColoredString()
        {
            var attrib = new ArgumentSetAttribute
            {
                Logo = new ColoredString("Test", ConsoleColor.Yellow)
            };

            attrib.LogoString.Content.Should().HaveCount(1);
            attrib.LogoString.Content[0].Content.Should().Be("Test");
            attrib.LogoString.Content[0].ForegroundColor.Should().Be(ConsoleColor.Yellow);
        }
Esempio n. 16
0
        public void InvalidPrefixes()
        {
            var attribs = new ArgumentSetAttribute();

            Action setPrefixes = () => attribs.NamedArgumentPrefixes = null;

            setPrefixes.ShouldThrow <ArgumentNullException>();

            setPrefixes = () => attribs.ShortNameArgumentPrefixes = null;
            setPrefixes.ShouldThrow <ArgumentNullException>();
        }
        public void TestThatAllowingElidingSeparatorAfterShortNameIsUnsupportedIfNamedArgPrefixesOverlap()
        {
            var attrib = new ArgumentSetAttribute {
                Style = ArgumentSetStyle.WindowsCommandLine
            };

            attrib.NamedArgumentPrefixes.Overlaps(attrib.ShortNameArgumentPrefixes).Should().BeTrue();

            attrib.AllowElidingSeparatorAfterShortName = true;
            attrib.Invoking(a => a.Validate()).Should().Throw <InvalidArgumentSetException>();
        }
        public void TestThatMultipleShortNamesInOneTokenIsUnsupportedIfNamedArgPrefixesOverlap()
        {
            var attrib = new ArgumentSetAttribute {
                Style = ArgumentSetStyle.WindowsCommandLine
            };

            attrib.NamedArgumentPrefixes.Overlaps(attrib.ShortNameArgumentPrefixes).Should().BeTrue();

            attrib.AllowMultipleShortNamesInOneToken = true;
            attrib.Invoking(a => a.Validate()).Should().Throw <InvalidArgumentSetException>();
        }
Esempio n. 19
0
        /// <summary>
        /// Constructs an empty argument set.
        /// </summary>
        /// <param name="setAttribute">Optionally provides attribute information describing the
        /// argument set.</param>
        public ArgumentSetDefinition(ArgumentSetAttribute setAttribute = null)
        {
            // Save off set attributes; if none were provided, construct some defaults.
            // Make sure to validate the attributes.
            Attribute = setAttribute ?? new ArgumentSetAttribute();
            Attribute.Validate();

            // Set up private fields dependent on the ArgumentSetAttribute.
            _namedArgumentsByName      = new Dictionary <string, ArgumentDefinition>(StringComparerToUse);
            _namedArgumentsByShortName = new Dictionary <string, ArgumentDefinition>(StringComparerToUse);
            _namedArgumentsByLongName  = new Dictionary <string, ArgumentDefinition>(StringComparerToUse);
        }
        public void NullPrefixes()
        {
            var attribs = new ArgumentSetAttribute();

            attribs.NamedArgumentPrefixes = null;
            attribs.NamedArgumentPrefixes.Should().NotBeNull();
            attribs.NamedArgumentPrefixes.Should().BeEmpty();

            attribs.ShortNameArgumentPrefixes = null;
            attribs.ShortNameArgumentPrefixes.Should().NotBeNull();
            attribs.ShortNameArgumentPrefixes.Should().BeEmpty();
        }
        public void LongNameArgPrefixesCannotOverlapShortNameArgPrefixes()
        {
            var attrib = new ArgumentSetAttribute
            {
                NamedArgumentPrefixes     = Array.Empty <string>(),
                ShortNameArgumentPrefixes = Array.Empty <string>()
            };

            attrib.AllowMultipleShortNamesInOneToken = true;
            attrib.ShortNameArgumentPrefixes         = new[] { "-", "/" };
            attrib.NamedArgumentPrefixes             = new[] { ":", "-" };

            attrib.Invoking(a => a.Validate()).Should().Throw <InvalidArgumentSetException>();
        }
Esempio n. 22
0
        public void LongNameArgPrefixesCannotOverlapShortNameArgPrefixes()
        {
            var attrib = new ArgumentSetAttribute
            {
                NamedArgumentPrefixes     = Array.Empty <string>(),
                ShortNameArgumentPrefixes = Array.Empty <string>()
            };

            attrib.AllowMultipleShortNamesInOneToken = true;
            attrib.ShortNameArgumentPrefixes         = new[] { "-", "/" };

            Action a = () => attrib.NamedArgumentPrefixes = new[] { ":", "-" };

            a.ShouldThrow <ArgumentOutOfRangeException>();
        }
Esempio n. 23
0
        public void CertainOptionsAreUnsupportedIfNamedArgPrefixesOverlap()
        {
            var attrib = new ArgumentSetAttribute {
                Style = ArgumentSetStyle.WindowsCommandLine
            };

            attrib.NamedArgumentPrefixes.Overlaps(attrib.ShortNameArgumentPrefixes).Should().BeTrue();

            Action a = () => attrib.AllowMultipleShortNamesInOneToken = true;

            a.ShouldThrow <NotSupportedException>();

            a = () => attrib.AllowElidingSeparatorAfterShortName = true;
            a.ShouldThrow <NotSupportedException>();
        }
        public void TestThatGetLogoYieldsEmptyStringLogoCannotBeExpanded()
        {
            var attrib = new ArgumentSetAttribute
            {
                Logo       = "{",
                ExpandLogo = true
            };

            var argSet    = new ArgumentSetDefinition(attrib);
            var usageInfo = new ArgumentSetUsageInfo(argSet, null);

            var logo = usageInfo.Logo;

            logo.Should().BeEmpty();
        }
Esempio n. 25
0
        private static string GetLongName(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member)
        {
            if (attribute.LongName != null)
            {
                return(attribute.LongName);
            }

            var longName = member.Name;

            if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.GenerateHyphenatedLowerCaseLongNames))
            {
                longName = longName.ToHyphenatedLowerCase();
            }

            return(longName);
        }
Esempio n. 26
0
        public void LogoIsSettableWithColoredMultistring()
        {
            var attrib = new ArgumentSetAttribute
            {
                Logo = new ColoredMultistring(new[]
                {
                    new ColoredString("Test", ConsoleColor.Yellow),
                    new ColoredString("String", null, ConsoleColor.Cyan)
                })
            };

            attrib.LogoString.Content.Should().HaveCount(2);
            attrib.LogoString.Content[0].Content.Should().Be("Test");
            attrib.LogoString.Content[0].ForegroundColor.Should().Be(ConsoleColor.Yellow);
            attrib.LogoString.Content[1].Content.Should().Be("String");
            attrib.LogoString.Content[1].BackgroundColor.Should().Be(ConsoleColor.Cyan);
        }
Esempio n. 27
0
        private static string GetShortNameOrNull(ArgumentBaseAttribute attribute, ArgumentSetAttribute argSetAttribute, MemberInfo member)
        {
            if (attribute is PositionalArgumentAttribute)
            {
                return(null);
            }

            if (HasExplicitShortName(attribute))
            {
                var namedAttribute = (NamedArgumentAttribute)attribute;
                return(namedAttribute.ShortName.Length == 0 ? null : namedAttribute.ShortName);
            }

            var longName  = GetLongName(attribute, argSetAttribute, member);
            var shortName = longName.Substring(0, 1);

            if (argSetAttribute.NameGenerationFlags.HasFlag(ArgumentNameGenerationFlags.PreferLowerCaseForShortNames))
            {
                shortName = shortName.ToLower();
            }

            return(shortName);
        }
Esempio n. 28
0
        public static ArgumentSetDefinition CreateArgumentSet(
            Type typeToReflectOn,
            ArgumentSetAttribute attribute      = null,
            object defaultValues                = null,
            object fixedDestination             = null,
            ServiceConfigurer serviceConfigurer = null)
        {
            // Find high-level metadata for the argument set.
            var argSetAttrib = attribute ?? GetSetAttributeOrDefault(typeToReflectOn);

            // Construct an empty definition.
            var argSet = new ArgumentSetDefinition(argSetAttrib);

            // Add arguments.
            AddToArgumentSet(
                argSet,
                typeToReflectOn,
                defaultValues: defaultValues,
                fixedDestination: fixedDestination,
                serviceConfigurer: serviceConfigurer);

            return(argSet);
        }
Esempio n. 29
0
 /// <summary>
 /// Constructor that creates a loop with a default client.
 /// </summary>
 /// <param name="commandType">Type that defines syntax for commands.</param>
 /// <param name="parameters">Optionally provides parameters controlling
 /// the loop's input and output behaviors; if not provided, default
 /// parameters are used.</param>
 /// <param name="argSetAttribute">Optionally provides attribute info
 /// for the argument set that will be dynamically created for this loop.</param>
 /// <param name="options">Optionally provides additional options for
 /// this loop's execution.</param>
 public Loop(Type commandType, LoopInputOutputParameters parameters = null, ArgumentSetAttribute argSetAttribute = null, LoopOptions options = null)
     : this(commandType, CreateClient(parameters ?? new LoopInputOutputParameters()), argSetAttribute, options)
 {
 }
 public void CanSelectWindowsCommandLineStyleWithoutThrowingException()
 {
     var attrib = new ArgumentSetAttribute {
         Style = ArgumentSetStyle.WindowsCommandLine
     };
 }