| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace TodoList
- {
- public class Program
- {
- private static CommandLineIterator ParseCommand(Tuple<CommandAttribute, Type> Command, CommandLineIterator Iterator, Dictionary<String, Object> PipedArguments)
- {
- var commandObject = Activator.CreateInstance(Command.Item2) as ICommand;
- try
- {
- Iterator = Iterator.Advance(); // Skip the command name.
- // Set the piped arguments.
- foreach (var pipedArgument in PipedArguments)
- foreach (var member in commandObject.GetType().GetFields())
- if (member.Name == pipedArgument.Key && member.FieldType == pipedArgument.Value.GetType())
- member.SetValue(Command, pipedArgument.Value);
-
- var defaultList = new List<Tuple<DefaultSwitchAttribute, System.Reflection.FieldInfo>>();
- System.Reflection.FieldInfo unknownSwitch = null;
- var unknownSwitchCaught = false;
- foreach (var member in commandObject.GetType().GetFields())
- {
- var defaultAttribute = member.GetCustomAttributes(true).FirstOrDefault(a => a is DefaultSwitchAttribute) as DefaultSwitchAttribute;
- if (defaultAttribute != null)
- defaultList.Add(Tuple.Create(defaultAttribute, member));
- if (member.GetCustomAttributes(true).Any(a => a is UnknownSwitchAttribute))
- unknownSwitch = member;
- }
- defaultList = defaultList.OrderBy(t => t.Item1.Order).ToList();
- while (!Iterator.AtEnd() && !Iterator.Peek().StartsWith("+"))
- {
- if (Iterator.Peek().StartsWith("-"))
- {
- var memberName = Iterator.Peek().Substring(1);
- Iterator = Iterator.Advance();
- bool matchingMemberFound = false;
- foreach (var member in commandObject.GetType().GetFields())
- if (member.Name == memberName)
- {
- if (member.FieldType == typeof(bool))
- member.SetValue(commandObject, true);
- else if (member.FieldType == typeof(String) && member.GetCustomAttributes(true).Any(a => a is GreedyArgumentAttribute))
- {
- var v = "";
- while (!Iterator.AtEnd())
- {
- v += Iterator.Peek();
- Iterator = Iterator.Advance();
- if (!Iterator.AtEnd())
- v += " ";
- }
- member.SetValue(commandObject, v);
- }
- else
- {
- member.SetValue(commandObject, ConvertArgument(Iterator.Peek(), member.FieldType));
- Iterator = Iterator.Advance();
- }
- matchingMemberFound = true;
- }
- if (!matchingMemberFound)
- {
- if (unknownSwitch == null)
- throw new InvalidOperationException("Unknown switch " + memberName);
- else
- {
- if (unknownSwitchCaught)
- throw new InvalidOperationException("Caught multiple unknown switches. " + memberName);
- unknownSwitchCaught = true;
- unknownSwitch.SetValue(commandObject, ConvertArgument(memberName, unknownSwitch.FieldType));
- }
- }
- }
- else
- {
- if (defaultList.Count == 0)
- break;
- if (defaultList[0].Item2.FieldType == typeof(String) && defaultList[0].Item2.GetCustomAttributes(true).Any(a => a is GreedyArgumentAttribute))
- {
- var v = "";
- while (!Iterator.AtEnd())
- {
- v += Iterator.Peek();
- Iterator = Iterator.Advance();
- if (!Iterator.AtEnd())
- v += " ";
- }
- defaultList[0].Item2.SetValue(commandObject, v);
- }
- else
- {
- defaultList[0].Item2.SetValue(commandObject, ConvertArgument(Iterator.Peek(), defaultList[0].Item2.FieldType));
- Iterator = Iterator.Advance();
- }
- defaultList.RemoveAt(0);
- }
- }
- commandObject.Invoke(PipedArguments);
- return Iterator;
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine(e.StackTrace);
- Console.WriteLine("Try 'help -" + Command.Item1.Name + "'");
- if (!String.IsNullOrEmpty(Command.Item1.ErrorText))
- Console.WriteLine(Command.Item1.ErrorText);
- Environment.Exit(0);
- throw new Exception();
- }
- }
- private static Object ConvertArgument(String Argument, Type DestinationType)
- {
- if (DestinationType == typeof(String))
- return Argument;
- else if (DestinationType == typeof(UInt32))
- return Convert.ToUInt32(Argument, 16);
- else if (DestinationType.IsEnum)
- {
- var value = Enum.Parse(DestinationType, Argument.ToUpperInvariant());
- return Convert.ChangeType(value, DestinationType);
- }
- else
- return Convert.ChangeType(Argument, DestinationType);
- }
- public static void Main(string[] args)
- {
- try
- {
- var commands = new Dictionary<String, Tuple<CommandAttribute, Type>>();
- foreach (var type in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
- {
- var commandAttribute = type.GetCustomAttributes(true).FirstOrDefault(a => a is CommandAttribute) as CommandAttribute;
- if (commandAttribute != null)
- commands[commandAttribute.Name] = Tuple.Create(commandAttribute, type);
- }
- var pipedArguments = new Dictionary<String, Object>();
- var iterator = new CommandLineIterator(args, 0);
- while (!iterator.AtEnd())
- {
- var commandName = iterator.Peek().Replace("+", "");
- var command = commands.Values.FirstOrDefault(c => c.Item1.Name == commandName || c.Item1.Synonyms.Contains(commandName));
- if (command == null)
- throw new InvalidOperationException("Unknown command " + iterator.Peek());
- iterator = ParseCommand(command, iterator, pipedArguments);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine(e.StackTrace);
- }
- finally
- {
- Console.ResetColor();
- }
- }
- }
- }
|