4 // Author: Rafael Teixeira (rafaelteixeirabr@hotmail.com)
6 // (C) 2002 Rafael Teixeira
10 using System.Collections;
12 using System.Reflection;
14 namespace Mono.GetOptions
16 public enum WhatToDoNext
22 internal enum OptionProcessingResult
26 OptionConsumedParameter
29 internal class OptionDetails : IComparable
31 public char ShortForm;
32 public string LongForm;
33 public string AlternateForm;
34 public string ShortDescription;
35 public bool NeedsParameter;
36 public int MaxOccurs; // negative means there is no limit
38 public Options OptionBundle;
39 public MemberInfo MemberInfo;
40 public ArrayList Values;
41 public System.Type ParameterType;
42 public string paramName = null;
43 public string ParamName
47 if (paramName == null)
49 int whereBegins = ShortDescription.IndexOf("{");
54 int whereEnds = ShortDescription.IndexOf("}");
55 if (whereEnds < whereBegins)
56 whereEnds = ShortDescription.Length+1;
58 paramName = ShortDescription.Substring(whereBegins + 1, whereEnds - whereBegins - 1);
60 ShortDescription.Substring(0, whereBegins) +
62 ShortDescription.Substring(whereEnds + 1);
69 public static bool Verbose = false;
71 public override string ToString()
74 // TODO: Yet not that good
76 optionHelp += (this.ShortForm != ' ') ? "-"+this.ShortForm+" " : " ";
77 optionHelp += (this.LongForm != string.Empty && this.LongForm != null) ? "--"+this.LongForm : "";
80 if (this.LongForm != string.Empty && this.LongForm != null)
82 optionHelp += ParamName;
84 optionHelp = optionHelp.PadRight(32) + " ";
85 optionHelp += this.ShortDescription;
86 if (this.AlternateForm != string.Empty && this.AlternateForm != null)
87 optionHelp += " [/"+this.AlternateForm + "]";
91 private static System.Type TypeOfMember(MemberInfo memberInfo)
93 if ((memberInfo.MemberType == MemberTypes.Field && memberInfo is FieldInfo))
94 return ((FieldInfo)memberInfo).FieldType;
96 if ((memberInfo.MemberType == MemberTypes.Property && memberInfo is PropertyInfo))
97 return ((PropertyInfo)memberInfo).PropertyType;
99 if ((memberInfo.MemberType == MemberTypes.Method && memberInfo is MethodInfo))
101 if (((MethodInfo)memberInfo).ReturnType.FullName != typeof(WhatToDoNext).FullName)
102 throw new NotSupportedException("Option method must return '" + typeof(WhatToDoNext).FullName + "'");
104 ParameterInfo[] parameters = ((MethodInfo)memberInfo).GetParameters();
105 if ((parameters == null) || (parameters.Length == 0))
108 return parameters[0].ParameterType;
111 throw new NotSupportedException("'" + memberInfo.MemberType + "' memberType is not supported");
114 public OptionDetails(MemberInfo memberInfo, OptionAttribute option, Options optionBundle)
116 this.ShortForm = option.ShortForm;
117 this.LongForm = (option.LongForm == string.Empty)? memberInfo.Name:option.LongForm;
118 this.AlternateForm = option.AlternateForm;
119 this.ShortDescription = option.ShortDescription;
121 this.OptionBundle = optionBundle;
122 this.MemberInfo = memberInfo;
123 this.NeedsParameter = false;
126 this.ParameterType = TypeOfMember(memberInfo);
128 if (this.ParameterType != null && this.ParameterType.FullName != "System.Boolean")
130 if (this.LongForm.IndexOf(':') >= 0)
131 throw new InvalidOperationException("Options with an embedded colon (':') in their visible name must be boolean!!! [" + this.MemberInfo.ToString() + " isn't]");
133 this.NeedsParameter = true;
135 if (option.MaxOccurs != 1)
137 if (this.ParameterType.IsArray)
139 this.Values = new ArrayList();
140 this.MaxOccurs = option.MaxOccurs;
144 if (this.MemberInfo is MethodInfo || this.MemberInfo is PropertyInfo)
145 this.MaxOccurs = option.MaxOccurs;
147 throw new InvalidOperationException("MaxOccurs set to non default value (" + option.MaxOccurs + ") for a [" + this.MemberInfo.ToString() + "] option");
155 get { return ((this.ShortForm != ' ') ? this.ShortForm + "" : "") + this.LongForm; }
158 int IComparable.CompareTo(object other)
160 return Key.CompareTo(((OptionDetails)other).Key);
163 public void TransferValues()
167 if (MemberInfo is FieldInfo)
169 ((FieldInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()));
173 if (MemberInfo is PropertyInfo)
175 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()), null);
179 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { Values.ToArray(ParameterType.GetElementType()) }) == WhatToDoNext.AbandonProgram)
180 System.Environment.Exit(1);
184 private void Occurred(int howMany)
188 if (MaxOccurs > 0 && Occurs > MaxOccurs)
189 throw new IndexOutOfRangeException("Option " + ShortForm + " can be used at most " + MaxOccurs + " times");
199 Console.WriteLine("<" + this.LongForm + "> set to [true]");
201 if (MemberInfo is FieldInfo)
203 ((FieldInfo)MemberInfo).SetValue(OptionBundle, true);
206 if (MemberInfo is PropertyInfo)
208 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, true, null);
211 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, null) == WhatToDoNext.AbandonProgram)
212 System.Environment.Exit(1);
218 private void DoIt(string parameterValue)
220 if (parameterValue == null)
223 string[] parameterValues = parameterValue.Split(',');
225 Occurred(parameterValues.Length);
227 foreach (string parameter in parameterValues)
230 object convertedParameter = null;
233 Console.WriteLine("<" + this.LongForm + "> set to [" + parameter + "]");
235 if (Values != null && parameter != null)
237 convertedParameter = Convert.ChangeType(parameter, ParameterType.GetElementType());
238 Values.Add(convertedParameter);
242 if (parameter != null)
243 convertedParameter = Convert.ChangeType(parameter, ParameterType);
245 if (MemberInfo is FieldInfo)
247 ((FieldInfo)MemberInfo).SetValue(OptionBundle, convertedParameter);
251 if (MemberInfo is PropertyInfo)
253 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, convertedParameter, null);
257 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { convertedParameter }) == WhatToDoNext.AbandonProgram)
258 System.Environment.Exit(1);
262 private bool StartsLikeAnOption(string arg)
264 return (arg != null && arg[0] == '-');
267 private bool IsThisOption(string arg)
269 if (StartsLikeAnOption(arg))
271 arg = arg.TrimStart('-');
272 return (arg == "" + ShortForm || arg == LongForm || arg == AlternateForm);
277 public OptionProcessingResult ProcessArgument(string arg, string nextArg)
279 if (IsThisOption(arg))
284 return OptionProcessingResult.OptionAlone;
288 if (StartsLikeAnOption(nextArg))
291 return OptionProcessingResult.OptionAlone;
296 return OptionProcessingResult.OptionConsumedParameter;
301 if (IsThisOption(arg + ":" + nextArg))
304 return OptionProcessingResult.OptionConsumedParameter;
307 return OptionProcessingResult.NotThisOption;