internal static void PrintHelpInternal(Parser.Configuration configuration, Parser.Command command, IHelpFormatter helpFormatter, Operation.Items operationMessages, bool error = true)
        {
            var f    = (helpFormatter ?? new Formatters.Console());
            var exit = (f as Formatters.FormatterBase)?.ExitOnError ?? true;

            // Print help using the help formatter, or create a default console messenger for this
            f.PrintHelp(configuration, command, operationMessages);
            PrintDebug(operationMessages);

            if (error && exit)
            {
                Environment.Exit(Int32.MinValue);
            }
        }
        /// <summary>
        /// Parses the specified types and retrieves all possible commands
        /// </summary>
        /// <param name="types">List of types in which to get all assemblies, or nothing to scan all assembly</param>
        /// <param name="configurationBuilder">Configuration builder action, or nothing to use defaults</param>
        /// <returns>Configuration retrieved from parse operation</returns>
        public static Parser.Configuration Parse(Type[] types, Action <Parser.Configuration> configurationBuilder = null)
        {
            // Create configuration
            var configuration = new Parser.Configuration();

            configurationBuilder?.Invoke(configuration);

            // Ensure we got types, otherwise, extract from entry assembly
            types = types == null || types.Count() == 0 ?
                    Assembly.GetEntryAssembly().DefinedTypes.Select(i => i.AsType()).ToArray() :
                    types;

            // Extract all commands
            var commandsParsed = types
                                 .SelectMany(t =>
                                             t
                                             .GetTypeInfo()
                                             .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
                                             .Select(i => new
            {
                MethodInfo = i,
                Attr       = i.GetCustomAttribute <CommandAttribute>(),
                Default    = i.GetCustomAttribute <CommandDefaultAttribute>()
            })
                                             .Where(i => i.Attr != null)
                                             .Select(i => new { C = new Parser.Command(configuration, i.MethodInfo, i.Attr), D = i.Default })
                                             )
                                 .ToArray();

            // Save commands
            configuration.Commands = commandsParsed
                                     .Select(i => i.C)
                                     .ToArray();

            // For each command, extract parameters
            foreach (var cmd in configuration.Commands)
            {
                var cmdParameters = cmd.MethodInfo.GetParameters()
                                    .Select(i => new
                {
                    ParameterInfo     = i,
                    ParameterPosition = 0,
                    Attr   = i.GetCustomAttribute <ParameterAttribute>(),
                    Hidden = i.GetCustomAttribute <ParameterHiddenAttribute>(),
                    Rules  = i.GetCustomAttributes <ParameterRuleAttribute>(),
                    System =
                        typeof(Parser.InputArguments).GetTypeInfo().IsAssignableFrom(i.ParameterType) ||
                        typeof(Operation.OperationResult).GetTypeInfo().IsAssignableFrom(i.ParameterType)
                })
                                    .Select(i => new { S = i.System, P = new Parser.CommandParameter(cmd, i.ParameterInfo, i.Rules, i.Attr, i.Hidden) });
                cmd.Parameters       = cmdParameters.Where(i => !i.S).Select(i => i.P).ToArray();
                cmd.SystemParameters = cmdParameters.Where(i => i.S).Select(i => i.P).ToArray();
            }

            // Validate the configuration
            var vr = configuration.Validate(commandsParsed.Count(c => c.D != null));

            if (!vr.Valid)
            {
                throw new CommandLineEngineDevelopperException(vr);
            }

            // Get default command
            configuration.DefaultCommand = commandsParsed.FirstOrDefault(i => i.D != null)?.C;

            return(configuration);
        }