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
77 if(this.OptionBundle.ParsingMode == Mono.GetOptions.OptionsParsingMode.Windows)
88 optionHelp += (this.ShortForm != ' ') ? shortPrefix+this.ShortForm+" " : " ";
89 optionHelp += (this.LongForm != string.Empty && this.LongForm != null) ? longPrefix+this.LongForm : "";
92 if (this.LongForm != string.Empty && this.LongForm != null)
94 optionHelp += ParamName;
96 optionHelp = optionHelp.PadRight(32) + " ";
97 optionHelp += this.ShortDescription;
98 if (this.AlternateForm != string.Empty && this.AlternateForm != null)
99 optionHelp += " [/"+this.AlternateForm + "]";
103 private static System.Type TypeOfMember(MemberInfo memberInfo)
105 if ((memberInfo.MemberType == MemberTypes.Field && memberInfo is FieldInfo))
106 return ((FieldInfo)memberInfo).FieldType;
108 if ((memberInfo.MemberType == MemberTypes.Property && memberInfo is PropertyInfo))
109 return ((PropertyInfo)memberInfo).PropertyType;
111 if ((memberInfo.MemberType == MemberTypes.Method && memberInfo is MethodInfo))
113 if (((MethodInfo)memberInfo).ReturnType.FullName != typeof(WhatToDoNext).FullName)
114 throw new NotSupportedException("Option method must return '" + typeof(WhatToDoNext).FullName + "'");
116 ParameterInfo[] parameters = ((MethodInfo)memberInfo).GetParameters();
117 if ((parameters == null) || (parameters.Length == 0))
120 return parameters[0].ParameterType;
123 throw new NotSupportedException("'" + memberInfo.MemberType + "' memberType is not supported");
126 public OptionDetails(MemberInfo memberInfo, OptionAttribute option, Options optionBundle)
128 this.ShortForm = option.ShortForm;
129 this.LongForm = (option.LongForm == string.Empty)? memberInfo.Name:option.LongForm;
130 this.AlternateForm = option.AlternateForm;
131 this.ShortDescription = option.ShortDescription;
133 this.OptionBundle = optionBundle;
134 this.MemberInfo = memberInfo;
135 this.NeedsParameter = false;
138 this.ParameterType = TypeOfMember(memberInfo);
140 if (this.ParameterType != null)
142 if (this.ParameterType.FullName != "System.Boolean")
144 if (this.LongForm.IndexOf(':') >= 0)
145 throw new InvalidOperationException("Options with an embedded colon (':') in their visible name must be boolean!!! [" +
146 this.MemberInfo.ToString() + " isn't]");
148 this.NeedsParameter = true;
150 if (option.MaxOccurs != 1)
152 if (this.ParameterType.IsArray)
154 this.Values = new ArrayList();
155 this.MaxOccurs = option.MaxOccurs;
159 if (this.MemberInfo is MethodInfo || this.MemberInfo is PropertyInfo)
160 this.MaxOccurs = option.MaxOccurs;
162 throw new InvalidOperationException("MaxOccurs set to non default value (" + option.MaxOccurs + ") for a [" +
163 this.MemberInfo.ToString() + "] option");
169 if (option.MaxOccurs != 1)
171 if (this.MemberInfo is MethodInfo || this.MemberInfo is PropertyInfo)
172 this.MaxOccurs = option.MaxOccurs;
174 throw new InvalidOperationException("MaxOccurs set to non default value (" + option.MaxOccurs + ") for a [" +
175 this.MemberInfo.ToString() + "] option");
183 get { return ((this.ShortForm != ' ') ? this.ShortForm + "" : "") + this.LongForm; }
186 int IComparable.CompareTo(object other)
188 return Key.CompareTo(((OptionDetails)other).Key);
191 public void TransferValues()
195 if (MemberInfo is FieldInfo)
197 ((FieldInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()));
201 if (MemberInfo is PropertyInfo)
203 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, Values.ToArray(ParameterType.GetElementType()), null);
207 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { Values.ToArray(ParameterType.GetElementType()) }) == WhatToDoNext.AbandonProgram)
208 System.Environment.Exit(1);
212 private void Occurred(int howMany)
216 if (MaxOccurs > 0 && Occurs > MaxOccurs)
217 throw new IndexOutOfRangeException("Option " + ShortForm + " can be used at most " + MaxOccurs + " times");
227 Console.WriteLine("<" + this.LongForm + "> set to [true]");
229 if (MemberInfo is FieldInfo)
231 ((FieldInfo)MemberInfo).SetValue(OptionBundle, true);
234 if (MemberInfo is PropertyInfo)
236 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, true, null);
239 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, null) == WhatToDoNext.AbandonProgram)
240 System.Environment.Exit(1);
246 private void DoIt(string parameterValue)
248 if (parameterValue == null)
251 string[] parameterValues = parameterValue.Split(',');
253 Occurred(parameterValues.Length);
255 foreach (string parameter in parameterValues)
258 object convertedParameter = null;
261 Console.WriteLine("<" + this.LongForm + "> set to [" + parameter + "]");
263 if (Values != null && parameter != null)
265 convertedParameter = Convert.ChangeType(parameter, ParameterType.GetElementType());
266 Values.Add(convertedParameter);
270 if (parameter != null)
271 convertedParameter = Convert.ChangeType(parameter, ParameterType);
273 if (MemberInfo is FieldInfo)
275 ((FieldInfo)MemberInfo).SetValue(OptionBundle, convertedParameter);
279 if (MemberInfo is PropertyInfo)
281 ((PropertyInfo)MemberInfo).SetValue(OptionBundle, convertedParameter, null);
285 if ((WhatToDoNext)((MethodInfo)MemberInfo).Invoke(OptionBundle, new object[] { convertedParameter }) == WhatToDoNext.AbandonProgram)
286 System.Environment.Exit(1);
290 private bool StartsLikeAnOption(string arg)
292 return (arg != null && arg[0] == '-');
295 private bool IsThisOption(string arg)
297 if (StartsLikeAnOption(arg))
299 arg = arg.TrimStart('-');
300 return (arg == "" + ShortForm || arg == LongForm || arg == AlternateForm);
305 public OptionProcessingResult ProcessArgument(string arg, string nextArg)
307 if (IsThisOption(arg))
312 return OptionProcessingResult.OptionAlone;
316 if (StartsLikeAnOption(nextArg))
319 return OptionProcessingResult.OptionAlone;
324 return OptionProcessingResult.OptionConsumedParameter;
329 if (IsThisOption(arg + ":" + nextArg))
332 return OptionProcessingResult.OptionConsumedParameter;
335 return OptionProcessingResult.NotThisOption;