/// <summary> /// Sets the value of the named flag. /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <exception cref="ArgumentException">Thrown when name does not exist as flag or when string value cannot be converted to desired type.</exception> public void Set(string name, string value) { var flagExists = Formal.TryGetValue(name, out var flag); if (!flagExists) { throw new ArgumentException("No such flag", nameof(name)); } if (!flag.TrySetValue(value, out var err)) { throw new ArgumentException($"Could not set value: {err}", nameof(value)); } if (Actual == null) { Actual = new Dictionary <string, IFlag>(); } if (Actual.ContainsKey(name)) { Actual[name] = flag; } else { Actual.Add(name, flag); } }
internal (bool, ParsingError) ParseOne() { if (Args.Length == 0) { return(false, null); } var s = Args[0]; if (s.Length < 2 || s[0] != '-') { return(false, null); } var numMinuses = 1; if (s[1] == '-') { numMinuses++; if (s.Length == 2) // "--" terminates the flags { Args = Args.Skip(1).ToArray(); return(false, null); } } var name = s.Substring(numMinuses); if (name.Length == 0 || name[0] == '-' || name[0] == '=') { return(false, FailF($"bad flag syntax: {0}", s)); } //it's a flag, does it have an argument? Args = Args.Skip(1).ToArray(); var hasValue = false; var value = ""; for (var i = 1; i < name.Length; i++) { if (name[i] == '=') { value = name.Substring(i + 1); hasValue = true; name = name.Substring(0, i); } } IFlag flag = null; var alreadyThere = Formal != null && Formal.TryGetValue(name, out flag); if (!alreadyThere) { if (name.Equals("help", StringComparison.CurrentCultureIgnoreCase) || name.Equals("h", StringComparison.CurrentCultureIgnoreCase)) { Usage(); return(false, ErrHelp); } return(false, FailF("flag provided but not defined: -{0}", name)); } if (flag?.TrackedType == typeof(bool)) //special case, doesn't need an arg { if (hasValue) { if (!flag.TrySetValue(value, out var err)) { if (value.Equals("0") && !flag.TrySetValue("false", out err)) //account for 0 and 1 values (inherint in Go, not in C#) { return(false, FailF("invalid boolean value \"{0}\" for -{1}: {2}", value, name, err)); } else if (value.Equals("1") && !flag.TrySetValue("true", out err)) { return(false, FailF("invalid boolean value \"{0}\" for -{1}: {2}", value, name, err)); } else { return(false, FailF("invalid boolean value \"{0}\" for -{1}: {2}", value, name, err)); } } } else { if (!flag.TrySetValue("true", out var err)) { return(false, FailF("invalid boolean flag {0}: {1}", name, err)); } } } else { //It must have a value, which might be the next argument. if (!hasValue && Args.Length > 0) { //value is the next arg hasValue = true; value = Args[0]; Args = Args.Skip(1).ToArray(); } if (!hasValue) { return(false, FailF("flag needs an argument: -{0}", name)); } if (!flag.TrySetValue(value, out var err)) { return(false, FailF("invalid value \"{0}\" for flag -{1}: {2}", value, name, err)); } } if (Actual == null) { Actual = new Dictionary <string, IFlag>(); } if (Actual.ContainsKey(name)) { Actual[name] = flag; } else { Actual.Add(name, flag); } return(true, null); }