<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace OpenSoftware.OptionParsing
{
    /// <summary>
    ///     Abstract option parser class.
    /// </summary>
    public abstract class OptionParser
    {
        private const string SwitchEscape = "--";

        /// <summary>
        ///     Creates a new instance of the OptionParser class.
        /// </summary>
        /// <param name="args">An array of strings holding the command line arguments and switches</param>
        protected OptionParser(IEnumerable<string> args)
        {
            Parse(args);
        }

        protected OptionParser()
        {
            Initialize();
        }

        /// <summary>
        ///     Returns the name of the application.
        /// </summary>
        public abstract string Name { get; }

        /// <summary>
        ///     Returns a description of the application
        /// </summary>
        public abstract string Description { get; }

        /// <summary>
        ///     Returns the collection of remaining (unparsed) command line arguments after processing.
        /// </summary>
        public List<string> Arguments { get; private set; }

        /// <summary>
        ///     Returns the collection of switches defined in the CommandLineParser
        /// </summary>
        public List<Option> Options { get; private set; }

        /// <summary>
        ///     Gets a list of all the options that have successfully been processed.
        /// </summary>
        public List<Option> ProcessedOptions { get; private set; }

        [Option(Name = "--help", ShortName = "/?", Description = "Shows this usage information.", DefaultValue = "false"
            , Index = 999)]
        internal BoolOption Usage { get; set; }

        protected virtual string Copyright => null;

        private void Initialize()
        {
            SwitchValues.Reset();
            Options = new List<Option>();
            ProcessedOptions = new List<Option>();
            const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
                                              BindingFlags.FlattenHierarchy;
            var optionProperties =
                GetType().GetProperties(bindingFlags).Where(prop => typeof(Option).IsAssignableFrom(prop.PropertyType));
            foreach (var prop in optionProperties)
            {
                var option = (Option)Activator.CreateInstance(prop.PropertyType);
                var optionAttr = (OptionAttribute)prop.GetCustomAttributes(typeof(OptionAttribute), true).SingleOrDefault();
                if (optionAttr != null)
                {
                    option.SetValues(optionAttr);
                }
                if (option.Name == null)
                {
                    throw new SyntaxErrorException($"{prop.Name}.Name ({prop.PropertyType.Name}) property cannot be null.");
                }
                prop.SetValue(this, option, null);
                Options.Add(option);
            }
        }

        public void Parse(params string[] args)
        {
            Parse(args.ToList());
        }
        public void Parse(IEnumerable<string> args)
        {
            Initialize();
            Arguments = args.ToList();
            ProcessArguments();
            ValidateArguments();
        }

        /// <summary>
        ///     Override this method to implement validation of options and arguments after processing.
        /// </summary>
        protected virtual void ValidateArguments()
        {
            if(Usage.Value)
            {
                DisplayUsage(Console.Error);
                Environment.Exit(0);
            }

            // Check if all required options have been specified.
            foreach(var option in Options.Where(arg => arg.Required))
            {
                if(ProcessedOptions.Contains(option) == false)
                {
                    throw new SyntaxErrorException($"Required switch `{option.Name}' is missing.");
                }<commit_msg>No longer display usage info and exit automatically, but let application handle this<commit_after>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace OpenSoftware.OptionParsing
{
    /// <summary>
    ///     Abstract option parser class.
    /// </summary>
    public abstract class OptionParser
    {
        private const string SwitchEscape = "--";

        /// <summary>
        ///     Creates a new instance of the OptionParser class.
        /// </summary>
        /// <param name="args">An array of strings holding the command line arguments and switches</param>
        protected OptionParser(IEnumerable<string> args)
        {
            Parse(args);
        }

        protected OptionParser()
        {
            Initialize();
        }

        /// <summary>
        ///     Returns the name of the application.
        /// </summary>
        public abstract string Name { get; }

        /// <summary>
        ///     Returns a description of the application
        /// </summary>
        public abstract string Description { get; }

        /// <summary>
        ///     Returns the collection of remaining (unparsed) command line arguments after processing.
        /// </summary>
        public List<string> Arguments { get; private set; }

        /// <summary>
        ///     Returns the collection of switches defined in the CommandLineParser
        /// </summary>
        public List<Option> Options { get; private set; }

        /// <summary>
        ///     Gets a list of all the options that have successfully been processed.
        /// </summary>
        public List<Option> ProcessedOptions { get; private set; }

        [Option(Name = "--help", ShortName = "/?", Description = "Shows this usage information.", DefaultValue = "false"
            , Index = 999)]
        public BoolOption Usage { get; set; }

        protected virtual string Copyright => null;

        private void Initialize()
        {
            SwitchValues.Reset();
            Options = new List<Option>();
            ProcessedOptions = new List<Option>();
            const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public |
                                              BindingFlags.FlattenHierarchy;
            var optionProperties =
                GetType().GetProperties(bindingFlags).Where(prop => typeof(Option).IsAssignableFrom(prop.PropertyType));
            foreach (var prop in optionProperties)
            {
                var option = (Option)Activator.CreateInstance(prop.PropertyType);
                var optionAttr = (OptionAttribute)prop.GetCustomAttributes(typeof(OptionAttribute), true).SingleOrDefault();
                if (optionAttr != null)
                {
                    option.SetValues(optionAttr);
                }
                if (option.Name == null)
                {
                    throw new SyntaxErrorException($"{prop.Name}.Name ({prop.PropertyType.Name}) property cannot be null.");
                }
                prop.SetValue(this, option, null);
                Options.Add(option);
            }
        }

        public void Parse(params string[] args)
        {
            Parse(args.ToList());
        }
        public void Parse(IEnumerable<string> args)
        {
            Initialize();
            Arguments = args.ToList();
            ProcessArguments();
            ValidateArguments();
        }

        /// <summary>
        ///     Override this method to implement validation of options and arguments after processing.
        /// </summary>
        protected virtual void ValidateArguments()
        {
            if(Usage.IsDefined)
            {
                // Stop validation when '--help' switch is used 
                return;
            }

            // Check if all required options have been specified.
            foreach(var option in Options.Where(arg => arg.Required))
            {
                if(ProcessedOptions.Contains(option) == false)
                {
                    throw new SyntaxErrorException($"Required switch `{option.Name}' is missing.");
                }
{'fraction_non_alphanumeric': 0.10153256704980843, 'fraction_numerical': 0.0008381226053639847, 'mean_word_length': 1.6441911997467553, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '500576', 'n_tokens_mistral': 1939, 'n_tokens_neox': 1856, 'n_words': 558}