Example #1
0
        public static void FullHelp <T>(Action extraHelp, bool skipOpener = false) where T : ICLIFlags
        {
            Type iface = typeof(T);

            SortedList <int, string> positionals = new SortedList <int, string>();
            int maxpositionals = "positional".Length;
            SortedList <int, string> positionalsstr = new SortedList <int, string>();

            List <string> helpflags    = new List <string>();
            int           maxflags     = "flags".Length;
            List <string> helpstrs     = new List <string>();
            int           maxstrs      = "help".Length;
            List <string> helpdefaults = new List <string>();

            FieldInfo[] fields = iface.GetFields();

            foreach (FieldInfo field in fields)
            {
                CLIFlagAttribute flagattr = field.GetCustomAttribute <CLIFlagAttribute>(true);
                if (flagattr == null)
                {
                    continue;
                }
                AliasAttribute[] aliasattrs = field.GetCustomAttributes <AliasAttribute>(true).ToArray();

                string required = "";
                if (flagattr.Required)
                {
                    required = " (Required)";
                }
                if (flagattr.NeedsValue)
                {
                    required += " (Needs Value)";
                }
                List <string> aliases = new List <string>();

                string prefix = "--";
                if (flagattr.Flag?.Length == 1)
                {
                    prefix = "-";
                }
                if (flagattr.Positional > -1)
                {
                    prefix = "";
                }

                aliases.Add(prefix + flagattr.Flag);
                foreach (AliasAttribute aliasattr in aliasattrs)
                {
                    prefix = "--";
                    if (aliasattr.Alias.Length == 1)
                    {
                        prefix = "-";
                    }
                    if (flagattr.Positional > -1)
                    {
                        prefix = "";
                    }
                    aliases.Add(prefix + aliasattr.Alias);
                }

                string helpflag = string.Join(" ", aliases);
                maxflags = Math.Max(maxflags, helpflag.Length);
                string helpstr = $"{flagattr.Help}{required}";
                maxstrs = Math.Max(maxstrs, helpstr.Length);
                string helpdefault = "";
                if (flagattr.Default != null)
                {
                    helpdefault = flagattr.Default.ToString();
                }

                if (flagattr.Positional > -1)
                {
                    positionals.Add(flagattr.Positional, helpflag);
                    maxpositionals = Math.Max(maxpositionals, helpflag.Length);
                    positionalsstr.Add(flagattr.Positional, helpstr);
                }
                else
                {
                    helpstrs.Add(helpstr);
                    helpflags.Add(helpflag);
                    helpdefaults.Add(helpdefault);
                }
            }

            if (!skipOpener)
            {
                Help <T>(true);
            }
            Console.Out.WriteLine();
            if (helpstrs.Count > 0)
            {
                if (!skipOpener)
                {
                    Console.Out.WriteLine("Flags:");
                }
                Console.Out.WriteLine($"  {{0, -{maxflags}}} | {{1, -{maxstrs}}} | {{2}}", "flag", "help", "default");
                Console.Out.WriteLine("".PadLeft(maxflags + maxstrs + 20, '-'));
                for (int i = 0; i < helpstrs.Count; ++i)
                {
                    string helpflag    = helpflags[i];
                    string helpstr     = helpstrs[i];
                    string helpdefault = helpdefaults[i];
                    Console.Out.WriteLine($"  {{0, -{maxflags}}} | {{1, -{maxstrs}}} | {{2}}", helpflag, helpstr, helpdefault);
                }
            }
            int maxindex = Math.Max("index".Length, ((int)Math.Floor(positionals.Count / 10d)) + 1);

            if (positionals.Count > 0)
            {
                Console.Out.WriteLine();
                if (!skipOpener)
                {
                    Console.Out.WriteLine("Positionals:");
                }
                Console.Out.WriteLine($"  {{0, -{maxindex}}} | {{1, -{maxpositionals}}} | {{2}}", "index", "positional", "help");
                Console.Out.WriteLine("".PadLeft(maxindex + maxpositionals + 30, '-'));
                foreach (KeyValuePair <int, string> pair in positionals)
                {
                    string positional    = pair.Value;
                    string positionalstr = positionalsstr[pair.Key];
                    Console.Out.WriteLine($"  {{0, -{maxindex}}} | {{1, -{maxpositionals}}} | {{2}}", pair.Key, positional, positionalstr);
                }
            }
            extraHelp?.Invoke();
        }
Example #2
0
        public static void Help <T>(bool simple) where T : ICLIFlags
        {
            Type iface = typeof(T);

            List <string> positonals = new List <string>();
            List <string> singulars  = new List <string>();
            List <string> help       = new List <string>();
            bool          hasflags   = false;

            FieldInfo[] fields = iface.GetFields();
            foreach (FieldInfo field in fields)
            {
                CLIFlagAttribute flagattr = field.GetCustomAttribute <CLIFlagAttribute>(true);
                if (flagattr == null)
                {
                    continue;
                }
                if (flagattr.Positional > -1)
                {
                    string x = flagattr.Flag;
                    if (!flagattr.Required)
                    {
                        x = $"[{x}]";
                    }
                    positonals.Add(x);
                }
                else if (!simple)
                {
                    if (flagattr.Flag.Length == 1)
                    {
                        singulars.Add(flagattr.Flag);
                    }
                    else
                    {
                        string x = flagattr.Flag;
                        if (flagattr.Default != null && flagattr.NeedsValue)
                        {
                            x = $"[--{x}[={flagattr.Default}]]";
                        }
                        else if (flagattr.NeedsValue)
                        {
                            x = $"[--{x}=value]";
                        }
                        else
                        {
                            x = $"[--{x}]";
                        }
                        help.Add(x);
                    }
                }
                else
                {
                    hasflags = true;
                }
            }

            string helpstr = AppDomain.CurrentDomain.FriendlyName;

            if (simple && hasflags)
            {
                helpstr += $" [--flags]";
            }
            else
            {
                if (singulars.Count > 0)
                {
                    helpstr += $" [-{string.Join("", singulars)}]";
                }
                if (help.Count > 0)
                {
                    helpstr += $" {string.Join(" ", help)}";
                }
            }
            if (positonals.Count > 0)
            {
                helpstr += $" {string.Join(" ", positonals)}";
            }
            Console.Out.WriteLine(helpstr);
        }
Example #3
0
        public static T Parse <T>(Action extraHelp, string[] args) where T : ICLIFlags
        {
            if (args.Length == 0)
            {
                FullHelp <T>(extraHelp);
                return(null);
            }

            Type iface = typeof(T);

            T instance = Activator.CreateInstance(iface) as T;

            if (instance == null)
            {
                return(null);
            }

            HashSet <string>            presence    = new HashSet <string>();
            List <string>               positionals = new List <string>();
            Dictionary <string, string> values      = new Dictionary <string, string>();

            foreach (string arg in args)
            {
                if (arg[0] == '-')
                {
                    if (arg[1] == '-')
                    {
                        string name = arg.Substring(2);
                        if (name.ToLower() == "help")
                        {
                            FullHelp <T>(extraHelp);
                            return(null);
                        }
                        string value = "true";
                        if (name.Contains('='))
                        {
                            value = name.Substring(name.IndexOf('=') + 1);
                            name  = name.Substring(0, name.IndexOf('='));
                        }
                        presence.Add(name);
                        values[name] = value;
                    }
                    else
                    {
                        char[] letters = arg.Substring(1).ToArray();
                        foreach (char letter in letters)
                        {
                            if (letter == '=')
                            {
                                break;
                            }
                            if (letter == '?' || letter == 'h')
                            {
                                Help <T>(false);
                                return(null);
                            }
                            presence.Add(letter.ToString());

                            string value = "true";
                            if (arg.Contains('='))
                            {
                                value = arg.Substring(arg.IndexOf('=') + 1);
                            }
                            values[letter.ToString()] = value;
                        }
                    }
                }
                else
                {
                    positionals.Add(arg);
                }
            }

            FieldInfo[] fields = iface.GetFields();
            foreach (FieldInfo field in fields)
            {
                if (field.Name == "Positionals")
                {
                    field.SetValue(instance, positionals.ToArray());
                    continue;
                }
                CLIFlagAttribute flagattr = field.GetCustomAttribute <CLIFlagAttribute>(true);
                if (flagattr == null)
                {
                    continue;
                }
                object value = flagattr.Default;
                if (flagattr.Positional > -1)
                {
                    if (positionals.Count > flagattr.Positional)
                    {
                        value = positionals[flagattr.Positional];
                    }
                }
                else
                {
                    if (!presence.Contains(flagattr.Flag))
                    {
                        AliasAttribute[] aliasattrs = field.GetCustomAttributes <AliasAttribute>(true).ToArray();
                        if (aliasattrs.Length > 0)
                        {
                            foreach (AliasAttribute aliasattr in aliasattrs)
                            {
                                if (presence.Contains(aliasattr.Alias))
                                {
                                    value = values[aliasattr.Alias];
                                }
                            }
                        }
                    }
                    else
                    {
                        value = values[flagattr.Flag];
                    }
                }
                if (value != null)
                {
                    if (flagattr.Valid != null)
                    {
                        if (!flagattr.Valid.Contains(value.ToString()))
                        {
                            Console.Error.WriteLine($"Value {value} is invalid for flag {flagattr.Flag}, valid values are {string.Join(", ", flagattr.Valid)}");
                            FullHelp <T>(extraHelp);
                            return(null);
                        }
                    }
                    if (flagattr.Parser != null && (value as string) != null && flagattr.Parser.Length == 2)
                    {
                        Type       parserclass = Type.GetType(flagattr.Parser[0]);
                        MethodInfo method      = parserclass?.GetMethod(flagattr.Parser[1]);
                        if (method != null)
                        {
                            ParameterInfo[] @params = method.GetParameters();
                            if (@params.Length == 1 && @params[0].ParameterType.Name == "String" && method.ReturnType.Name == "Object")
                            {
                                value = method.Invoke(null, new object[] { (string)value });
                            }
                        }
                    }
                    field.SetValue(instance, value);
                }
                else if (flagattr.Required)
                {
                    Console.Error.WriteLine($"Flag {flagattr.Flag} is required");
                    FullHelp <T>(extraHelp);
                    return(null);
                }
            }
            return(instance);
        }
Example #4
0
        public static T Parse <T>(Action extraHelp, string[] args) where T : ICLIFlags
        {
            if (args.Length == 0)
            {
                FullHelp <T>(extraHelp);
                return(null);
            }

            Type iface = typeof(T);

            T instance = Activator.CreateInstance(iface) as T;

            if (instance == null)
            {
                return(null);
            }

            HashSet <string>            presence    = new HashSet <string>();
            List <string>               positionals = new List <string>();
            Dictionary <string, string> values      = new Dictionary <string, string>();
            Dictionary <string, Dictionary <string, string> > dictionaryValues = new Dictionary <string, Dictionary <string, string> >();
            Dictionary <string, List <string> > arrayValues = new Dictionary <string, List <string> >();

            FieldInfo[] fields = iface.GetFields();
            foreach (FieldInfo field in fields)
            {
                if (field.Name == "Positionals")
                {
                    continue;
                }
                CLIFlagAttribute flagattr = field.GetCustomAttribute <CLIFlagAttribute>(true);
                if (flagattr == null)
                {
                    continue;
                }
                Type t = field.FieldType;
                if (t.IsGenericType && t.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary <,>)))
                {
                    AliasAttribute[] aliasattrs = field.GetCustomAttributes <AliasAttribute>(true).ToArray();
                    if (aliasattrs.Length > 0)
                    {
                        foreach (AliasAttribute aliasattr in aliasattrs)
                        {
                            dictionaryValues.Add(aliasattr.Alias, new Dictionary <string, string>());
                        }
                    }
                    dictionaryValues.Add(flagattr.Flag, new Dictionary <string, string>());
                }
                if (t.IsGenericType && t.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>)))
                {
                    AliasAttribute[] aliasattrs = field.GetCustomAttributes <AliasAttribute>(true).ToArray();
                    if (aliasattrs.Length > 0)
                    {
                        foreach (AliasAttribute aliasattr in aliasattrs)
                        {
                            arrayValues.Add(aliasattr.Alias, new List <string>());
                        }
                    }
                    arrayValues.Add(flagattr.Flag, new List <string>());
                }
            }

            for (int i = 0; i < args.Length; ++i)
            {
                string arg = args[i];
                if (arg[0] == '-')
                {
                    if (arg[1] == '-')
                    {
                        string name = arg.Substring(2);
                        if (name.ToLower() == "help")
                        {
                            FullHelp <T>(extraHelp);
                            return(null);
                        }
                        string value = "true";
                        if (name.Contains('='))
                        {
                            value = name.Substring(name.IndexOf('=') + 1);
                            name  = name.Substring(0, name.IndexOf('='));
                        }
                        presence.Add(name);
                        if (dictionaryValues.ContainsKey(name))
                        {
                            string key = args[++i];
                            if (key.Contains('='))
                            {
                                value = key.Substring(key.IndexOf('=') + 1);
                                key   = key.Substring(0, key.IndexOf('='));
                            }
                            dictionaryValues[name][key] = value;
                        }
                        else if (arrayValues.ContainsKey(name))
                        {
                            arrayValues[name].Add(args[++i]);
                        }
                        else
                        {
                            values[name] = value;
                        }
                    }
                    else
                    {
                        char[] letters = arg.Substring(1).ToArray();
                        foreach (char letter in letters)
                        {
                            if (letter == '=')
                            {
                                break;
                            }
                            if (letter == '?' || letter == 'h')
                            {
                                Help <T>(false);
                                return(null);
                            }
                            presence.Add(letter.ToString());

                            string value = "true";
                            if (arg.Contains('='))
                            {
                                value = arg.Substring(arg.IndexOf('=') + 1);
                            }
                            string name = letter.ToString();
                            if (dictionaryValues.ContainsKey(name))
                            {
                                string key = args[++i];
                                if (key.Contains('='))
                                {
                                    value = key.Substring(key.IndexOf('=') + 1);
                                    key   = key.Substring(0, key.IndexOf('='));
                                }
                                dictionaryValues[name][key] = value;
                            }
                            else if (arrayValues.ContainsKey(name))
                            {
                                arrayValues[name].Add(args[++i]);
                            }
                            else
                            {
                                values[name] = value;
                            }
                        }
                    }
                }
                else
                {
                    positionals.Add(arg);
                }
            }

            foreach (FieldInfo field in fields)
            {
                if (field.Name == "Positionals")
                {
                    field.SetValue(instance, positionals.ToArray());
                    continue;
                }
                CLIFlagAttribute flagattr = field.GetCustomAttribute <CLIFlagAttribute>(true);
                if (flagattr == null)
                {
                    continue;
                }
                FieldKind kind = FieldKind.Default;
                Type      t    = field.FieldType;
                if (t.IsGenericType && t.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary <,>)))
                {
                    kind = FieldKind.Dictionary;
                }
                else if (t.IsGenericType && t.GetGenericTypeDefinition().IsAssignableFrom(typeof(List <>)))
                {
                    kind = FieldKind.Array;
                }
                object value         = flagattr.Default;
                object key           = string.Empty;
                bool   insertedValue = false;
                if (flagattr.Positional > -1)
                {
                    if (positionals.Count > flagattr.Positional)
                    {
                        value = positionals[flagattr.Positional];
                    }
                }
                else
                {
                    if (!presence.Contains(flagattr.Flag))
                    {
                        AliasAttribute[] aliasattrs = field.GetCustomAttributes <AliasAttribute>(true).ToArray();
                        if (aliasattrs.Length > 0)
                        {
                            foreach (AliasAttribute aliasattr in aliasattrs)
                            {
                                if (presence.Contains(aliasattr.Alias))
                                {
                                    insertedValue = true;
                                    if (kind == FieldKind.Default)
                                    {
                                        value = values[aliasattr.Alias];
                                    }
                                    else if (kind == FieldKind.Dictionary)
                                    {
                                        value = dictionaryValues[aliasattr.Alias];
                                    }
                                    else if (kind == FieldKind.Array)
                                    {
                                        value = arrayValues[aliasattr.Alias];
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        insertedValue = true;
                        if (kind == FieldKind.Default)
                        {
                            value = values[flagattr.Flag];
                        }
                        else if (kind == FieldKind.Dictionary)
                        {
                            value = dictionaryValues[flagattr.Flag];
                        }
                        else if (kind == FieldKind.Array)
                        {
                            value = arrayValues[flagattr.Flag];
                        }
                    }
                }
                if (value != null)
                {
                    if (flagattr.Valid != null)
                    {
                        if (!flagattr.Valid.Contains(value.ToString()))
                        {
                            Console.Error.WriteLine($"Value {value} is invalid for flag {flagattr.Flag}, valid values are {string.Join(", ", flagattr.Valid)}");
                            FullHelp <T>(extraHelp);
                            return(null);
                        }
                    }
                    if (flagattr.Parser != null && insertedValue && flagattr.Parser.Length == 2)
                    {
                        Type       parserclass = Type.GetType(flagattr.Parser[0]);
                        MethodInfo method      = parserclass?.GetMethod(flagattr.Parser[1]);
                        if (method != null)
                        {
                            ParameterInfo[] @params = method.GetParameters();
                            if (kind == FieldKind.Default)
                            {
                                if (@params.Length == 1 && @params[0].ParameterType.Name == "String" && method.ReturnType.Name == "Object")
                                {
                                    value = method.Invoke(null, new object[] { (string)value });
                                }
                            }
                            else if (kind == FieldKind.Dictionary)
                            {
                                if (@params.Length == 1 && @params[0].ParameterType.Name == "Dictionary`2" && method.ReturnType.Name == "Object")
                                {
                                    value = method.Invoke(null, new object[] { (Dictionary <string, string>)value });
                                }
                            }
                            else if (kind == FieldKind.Array)
                            {
                                if (@params.Length == 1 && @params[0].ParameterType.Name == "List`1" && method.ReturnType.Name == "Object")
                                {
                                    value = method.Invoke(null, new object[] { (List <string>)value });
                                }
                            }
                        }
                    }
                    field.SetValue(instance, value);
                }
                else if (flagattr.Required)
                {
                    Console.Error.WriteLine($"Flag {flagattr.Flag} is required");
                    FullHelp <T>(extraHelp);
                    return(null);
                }
                else if (field.FieldType.IsClass && field.FieldType.GetConstructor(Type.EmptyTypes) != null)
                {
                    field.SetValue(instance, Activator.CreateInstance(field.FieldType));
                }
            }
            return(instance);
        }