// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; namespace Flax.Build { /// /// The command line utilities. /// public class CommandLine { internal static List ConsoleCommands; /// /// The command line option data. /// public class Option { /// /// The name. /// public string Name; /// /// The value. /// public string Value; /// public override string ToString() { if (string.IsNullOrEmpty(Value)) return $"/{Name}"; return $"/{Name}={Value}"; } } /// /// Gets the program executable string. Post-processed to improve parsing performance. /// /// The command line. public static string Get() { string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1) { string commandLine = Environment.CommandLine.Remove(0, args[0].Length + 2); commandLine = commandLine.Trim(' '); return commandLine; } return string.Empty; } /// /// Gets the help information for the command line options for the given type. /// /// The type. /// The options help information. public static string GetHelp(Type type) { StringWriter result = new StringWriter(); result.WriteLine("Usage: Flax.Build.exe [options]"); result.WriteLine("Options:"); var options = GetMembers(type); foreach (var option in options) { result.Write(" -" + option.Key.Name); if (!string.IsNullOrEmpty(option.Key.ValueHint)) { result.Write("={0}", option.Key.ValueHint); } result.WriteLine(); if (!string.IsNullOrEmpty(option.Key.Description)) { result.WriteLine("\t{0}", option.Key.Description.Replace(Environment.NewLine, Environment.NewLine + "\t")); } result.WriteLine(); } return result.ToString(); } /// /// Gets the options for command line configuration for the given type. /// /// The type. /// The list of configurable options. public static Dictionary GetMembers(Type type) { if (type == null) throw new ArgumentNullException(); var result = new Dictionary(); var members = type.GetMembers(BindingFlags.Static | BindingFlags.Public); for (int i = 0; i < members.Length; i++) { var member = members[i]; var attribute = member.GetCustomAttribute(); if (attribute != null) { result.Add(attribute, member); } } return result; } /// /// Gets the options for command line configuration for the given object instance. /// /// The object instance. /// The list of configurable options. public static Dictionary GetMembers(object obj) { if (obj == null) throw new ArgumentNullException(); var result = new Dictionary(); var type = obj.GetType(); var members = type.GetMembers(BindingFlags.Instance | BindingFlags.Public); for (int i = 0; i < members.Length; i++) { var member = members[i]; var attribute = member.GetCustomAttribute(); if (attribute != null) { result.Add(attribute, member); } } return result; } private static int _cacheHash; private static readonly object _cacheLock = new object(); private static Option[] _cacheOptions; /// /// Determines whether the specified option has been specified in the environment command line. /// /// The option name. /// true if the specified option has been specified; otherwise, false. public static bool HasOption(string name) { return HasOption(name, Get()); } /// /// Determines whether the specified option has been specified in the environment command line. /// /// The option name. /// The command line. /// true if the specified option has been specified; otherwise, false. private static bool HasOption(string name, string commandLine) { return commandLine.Length > 0 && GetOptions(commandLine).Any(p => (string.Equals(p.Name, name, StringComparison.OrdinalIgnoreCase))); } /// /// Gets the options for the current environment command line. /// /// The options. public static Option[] GetOptions() { return GetOptions(Get()); } /// /// Gets the options for the given command line. /// /// The command line. /// The options. public static Option[] GetOptions(string commandLine) { int hash = commandLine.GetHashCode(); Option[] options; lock (_cacheLock) { if (hash != _cacheHash) { _cacheHash = hash; _cacheOptions = Parse(commandLine); } options = _cacheOptions; } return options; } /// /// Gets the options for the given configuration (key=value pairs). /// /// The configuration (key=value pairs). /// The options. public static Option[] GetOptions(Dictionary configuration) { var options = new Option[configuration.Count]; int i = 0; foreach (var e in configuration) { options[i++] = new Option { Name = e.Key, Value = e.Value, }; } return options; } /// /// Parses the specified command line. /// /// The command line. /// The options. public static Option[] Parse(string commandLine) { var options = new List