public int Try()
        {
            var theUsageWriter = new CmdLineUsageWriter(myDefinition);

            if (myDefinition.HasDifferentiatedSubcommands && !myDefinition.Subcommands.Any())
            {
                throw new InvalidOperationException("At least one subcommand must be added to the definition.");
            }

            if (myDefinition.HasDifferentiatedSubcommands && myArgs.Length < 1)
            {
                theUsageWriter.WriteAndExit();
                return(-1);
            }

            // Default Command suchen
            CmdLineSubcommand?theSubcommand = myDefinition.Subcommands.SingleOrDefault(
                sc => sc.Name == CmdLineSubcommand.DefaultName
                );

            if (!myDefinition.HasDifferentiatedSubcommands && theSubcommand == null)
            {
                throw new InvalidOperationException(
                          "Without differentiated commands a subcommand with the name \"default\" must be added to the definition."
                          );
            }

            // Token-List erstellen und passenden Subcommand ermitteln (im Fehlerfall wird
            // hier die Usage erklärt und mit ReturnCode -1 der Prozess beendet)
            var theTokenizer = new CmdLineTokenizer(myDefinition, theUsageWriter);
            List <CmdLineToken> theTokens = theTokenizer.Tokenize(myArgs, ref theSubcommand);

            // Subcommand ausführen
            return(theSubcommand !.Execute(theTokens, myDefinition));
        }
        /// <summary>Writes the usage help for the specified subcommand to
        /// the console.</summary>
        /// <param name="subcommandName">Name of the subcommand</param>
        public void ShowHelp(string subcommandName)
        {
            if (subcommandName == null)
            {
                throw new ArgumentNullException(nameof(subcommandName));
            }

            CmdLineSubcommand theSubcommand = Subcommands.SingleOrDefault(sc => sc.Name == subcommandName);

            if (theSubcommand == null)
            {
                throw new ArgumentException($"Subcommand \"{subcommandName}\" is not defined.");
            }

            var theUsageWriter = new CmdLineUsageWriter(this);

            theUsageWriter.WriteAndExit(theSubcommand);
        }
        /// <summary>Writes the usage help to the console.</summary>
        public void ShowHelp()
        {
            var theUsageWriter = new CmdLineUsageWriter(this);

            theUsageWriter.WriteAndExit();
        }
        public List <CmdLineToken> Tokenize(string[] args, ref CmdLineSubcommand?subcommand)
        {
            var theResult = new List <CmdLineToken>();
            var theExclusionGroupCounts = new Dictionary <string, List <CmdLineOption> >();

            int theParameterIndex = 0;

            for (int theIndex = 0; theIndex < args.Length; theIndex++)
            {
                string theArg = args[theIndex];
                if (theIndex == 0 && myDefinition.HasDifferentiatedSubcommands)
                {
                    // Muss Subcommand sein
                    subcommand = myDefinition.Subcommands.SingleOrDefault(sc => sc.Name == theArg);
                    if (subcommand != null)
                    {
                        theResult.Add(new CmdLineToken(CmdLineTokenKind.Subcommand, theArg));
                        continue;
                    }
                    else
                    {
                        if (theArg.StartsWith("-"))
                        {
                            myUsageWriter.WriteAndExit("Subcommand is missing.");
                        }
                        else
                        {
                            myUsageWriter.WriteAndExit($"Unknown subcommand: {theArg}");
                        }
                    }
                }

                if (theArg.StartsWith("-"))
                {
                    // Option
                    if (subcommand == null)
                    {
                        myUsageWriter.WriteAndExit();
                    }
                    else
                    {
                        bool isLongNameOption = theArg.StartsWith("--");

                        string theOptionTextWithoutDashes = isLongNameOption ? theArg.Substring(2) : theArg.Substring(1);

                        CmdLineOption theOption =
                            isLongNameOption ?
                            subcommand.Options.SingleOrDefault(o => o.LongName == theOptionTextWithoutDashes) :
                            subcommand.Options.SingleOrDefault(o => o.Letter.ToString() == theOptionTextWithoutDashes);

                        if (theOption != null)
                        {
                            foreach (string theExclusionGroup in theOption.ExclusionGroups)
                            {
                                if (theExclusionGroupCounts.TryGetValue(theExclusionGroup,
                                                                        out List <CmdLineOption> theOptions))
                                {
                                    theOptions.Add(theOption);
                                    theExclusionGroupCounts[theExclusionGroup] = theOptions;
                                }
                                else
                                {
                                    theOptions = new List <CmdLineOption> {
                                        theOption
                                    };
                                    theExclusionGroupCounts[theExclusionGroup] = theOptions;
                                }
                            }

                            object?theValue = true;
                            if (!theOption.IsSwitch)
                            {
                                if (theIndex < args.Length - 1)
                                {
                                    theIndex++;
                                    string theRawValue = args[theIndex];

                                    theValue = ParseUtils.ParseOption(theOption, theRawValue, out string?theErrorMessage);

                                    if (theErrorMessage != null)
                                    {
                                        myUsageWriter.WriteAndExit(subcommand, theErrorMessage);
                                    }
                                }
                                else
                                {
                                    // Value kommt nicht
                                    myUsageWriter.WriteAndExit(
                                        subcommand,
                                        $"Missing value for option {theOption.ToLongCmdLineString()}."
                                        );
                                }
                            }

                            theResult.Add(
                                new CmdLineToken(CmdLineTokenKind.Option, theOption.Letter.ToString())
                            {
                                Value = theValue !
                            }