Example #1
0
        public override bool Execute(List <string> args)
        {
            if (args.Count < 2)
            {
                return(false);
            }

            var fieldName    = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext   = Stack.Context;
            var previousOwner     = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName    = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List <string> {
                    blockName
                }))
                {
                    while (Stack.Context != previousContext)
                    {
                        Stack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner     = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext)
                    {
                        Stack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field      = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);

            if (field == null)
            {
                Console.WriteLine("ERROR: {0} does not contain a field named \"{1}\".", Structure.Types[0].Name, fieldName);
                while (Stack.Context != previousContext)
                {
                    Stack.Pop();
                }
                Owner     = previousOwner;
                Structure = previousStructure;
                return(false);
            }

            var fieldType  = field.FieldType;
            var fieldValue = ParseArgs(field.FieldType, args.Skip(1).ToList());

            if (fieldValue != null && fieldValue.Equals(false))
            {
                while (Stack.Context != previousContext)
                {
                    Stack.Pop();
                }
                Owner     = previousOwner;
                Structure = previousStructure;
                return(false);
            }

            field.SetValue(Owner, fieldValue);

            var typeString =
                fieldType.IsGenericType ?
                $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var valueString =
                fieldType == typeof(StringId) ?
                Info.StringIds.GetString((StringId)fieldValue) :
                fieldType.GetInterface(typeof(IList).Name) != null ?
                (((IList)fieldValue).Count != 0 ?
                 $"{{...}}[{((IList)fieldValue).Count}]" :
                 "null") :
                fieldValue == null ?
                "null" :
                fieldValue.ToString();

            Console.WriteLine("{0}: {1} = {2}", field.Name, typeString, valueString);

            while (Stack.Context != previousContext)
            {
                Stack.Pop();
            }
            Owner     = previousOwner;
            Structure = previousStructure;

            return(true);
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 3)
                return false;

            var fieldName = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext = Stack.Context;
            var previousOwner = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List<string> { blockName }))
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);
            var fieldType = field.FieldType;

            if ((field == null) ||
                (!fieldType.IsGenericType) ||
                (fieldType.GetInterface("IList") == null))
            {
                Console.WriteLine("ERROR: {0} does not contain a tag block named \"{1}\".", Structure.Types[0].Name, args[0]);
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            var blockValue = field.GetValue(Owner) as IList;

            if (blockValue == null)
            {
                blockValue = Activator.CreateInstance(field.FieldType) as IList;
                field.SetValue(Owner, blockValue);
            }

            var elementType = field.FieldType.GenericTypeArguments[0];

            var index = blockValue.Count - 1;
            var count = 1;

            var genericIndex = false;
            var genericCount = false;

            if (args.Count == 1)
            {
                count = 1;
            }
            else
            {
                if (args.Count >= 2)
                {
                    if (args[1] == "*")
                    {
                        genericIndex = true;
                        index = blockValue.Count - 1;
                    }
                    else if (!int.TryParse(args[1], out index) || index < 0 || index >= blockValue.Count)
                    {
                        Console.WriteLine($"Invalid index specified: {args[1]}");
                        return false;
                    }
                }

                if (args.Count == 3)
                {
                    if (args[2] == "*")
                    {
                        genericCount = true;
                        count = blockValue.Count - index;
                    }
                    else if (!int.TryParse(args[2], out count) || count < 1)
                    {
                        Console.WriteLine($"Invalid number specified: {args[2]}");
                        return false;
                    }
                }
            }

            if (genericIndex && genericCount)
            {
                index = 0;
                count = blockValue.Count;
            }
            else if (genericIndex)
            {
                index -= count;

                if (index < 0)
                    index = 0;
            }

            if (index + count > blockValue.Count)
            {
                Console.WriteLine($"ERROR: Too many block elements specified to be removed: {count}. Maximum at index {index} can be {blockValue.Count - index}");
                return false;
            }

            for (var i = 0; i < count; i++)
                blockValue.RemoveAt(index);

            field.SetValue(Owner, blockValue);

            var typeString =
                fieldType.IsGenericType ?
                    $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var itemString = count < 2 ? "element" : "elements";

            var valueString =
                ((IList)blockValue).Count != 0 ?
                    $"{{...}}[{((IList)blockValue).Count}]" :
                "null";

            Console.WriteLine($"Successfully removed {count} {itemString} from {field.Name} at index {index}: {typeString}");
            Console.WriteLine(valueString);

            while (Stack.Context != previousContext) Stack.Pop();
            Owner = previousOwner;
            Structure = previousStructure;

            return true;
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 2)
                return false;

            var fieldName = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext = Stack.Context;
            var previousOwner = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List<string> { blockName }))
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);

            if (field == null)
            {
                Console.WriteLine("ERROR: {0} does not contain a field named \"{1}\".", Structure.Types[0].Name, fieldName);
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            var fieldType = field.FieldType;
            var fieldValue = ParseArgs(field.FieldType, args.Skip(1).ToList());

            if (fieldValue != null && fieldValue.Equals(false))
            {
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            field.SetValue(Owner, fieldValue);

            var typeString =
                fieldType.IsGenericType ?
                    $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var valueString =
                fieldType == typeof(StringId) ?
                    Info.StringIds.GetString((StringId)fieldValue) :
                fieldType.GetInterface(typeof(IList).Name) != null ?
                    (((IList)fieldValue).Count != 0 ?
                        $"{{...}}[{((IList)fieldValue).Count}]" :
                    "null") :
                fieldValue == null ?
                    "null" :
                fieldValue.ToString();

            Console.WriteLine("{0}: {1} = {2}", field.Name, typeString, valueString);

            while (Stack.Context != previousContext) Stack.Pop();
            Owner = previousOwner;
            Structure = previousStructure;

            return true;
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 2)
                return false;

            var blockName = args[0];
            var ownerType = Owner.GetType();

            var enumerator = new TagFieldEnumerator(Structure);

            var deferredNames = new List<string>();
            var deferredArgs = new List<string>();

            if (blockName.Contains("."))
            {
                deferredNames.AddRange(blockName.Split('.'));
                blockName = deferredNames[0];
                deferredNames = deferredNames.Skip(1).ToList();
                deferredArgs.AddRange(args.Skip(1));
                args = new List<string> { blockName };
            }

            if (blockName.Contains("]"))
            {
                var openBracketIndex = blockName.IndexOf('[');
                var closeBracketIndex = blockName.IndexOf(']');
                var name = blockName.Substring(0, openBracketIndex);
                var index = blockName.Substring(openBracketIndex + 1, (closeBracketIndex - openBracketIndex) - 1);

                blockName = name;
                args = new List<string> { name, index };
            }

            var blockNameLow = blockName.ToLower();
            var field = enumerator.Find(f => f.Name == blockName || f.Name.ToLower() == blockNameLow);

            if (field == null)
            {
                Console.WriteLine("{0} does not contain a block named \"{1}\"", ownerType.Name, blockName);
                return false;
            }

            var contextName = "";
            object blockValue = null;

            var structureAttribute = field.FieldType.CustomAttributes.ToList().Find(a => a.AttributeType == typeof(TagStructureAttribute));

            if (structureAttribute != null)
            {
                if (args.Count != 1)
                    return false;

                blockValue = field.GetValue(Owner);
                contextName = $"{blockName}";
            }
            else
            {
                if (args.Count != 2)
                    return false;

                IList fieldValue = null;

                if (field.FieldType.GetInterface("IList") == null || (fieldValue = (IList)field.GetValue(Owner)) == null)
                {
                    Console.WriteLine("{0} does not contain a block named \"{1}\"", ownerType.Name, blockName);
                    return false;
                }

                int blockIndex = 0;

                if (args[1] == "*")
                    blockIndex = fieldValue.Count - 1;
                else if (!int.TryParse(args[1], out blockIndex))
                {
                    Console.WriteLine("Invalid index requested from block {0}: {1}", blockName, blockIndex);
                    return false;
                }

                if (blockIndex >= fieldValue.Count || blockIndex < 0)
                {
                    Console.WriteLine("Invalid index requested from block {0}: {1}", blockName, blockIndex);
                    return false;
                }

                blockValue = fieldValue[blockIndex];
                contextName = $"{blockName}[{blockIndex}]";
            }

            var blockStructure = new TagStructureInfo(blockValue.GetType());

            var blockContext = new CommandContext(Stack.Context, contextName);
            blockContext.AddCommand(new ListFieldsCommand(Info, blockStructure, blockValue));
            blockContext.AddCommand(new SetFieldCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new EditBlockCommand(Stack, Info, Tag, blockValue));
            blockContext.AddCommand(new AddToBlockCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new RemoveFromBlockCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new CopyElementsCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new PasteElementsCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new ExitToCommand(Stack));
            Stack.Push(blockContext);

            if (deferredNames.Count != 0)
            {
                var name = deferredNames[0];
                deferredNames = deferredNames.Skip(1).ToList();

                foreach (var deferredName in deferredNames)
                    name += '.' + deferredName;

                args = new List<string> { name };
                args.AddRange(deferredArgs);

                var command = new EditBlockCommand(Stack, Info, Tag, blockValue);
                return command.Execute(args);
            }

            return true;
        }
        public override bool Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 2)
            {
                return(false);
            }

            var blockName = args[0];
            var ownerType = Owner.GetType();

            var enumerator = new TagFieldEnumerator(Structure);

            var deferredNames = new List <string>();
            var deferredArgs  = new List <string>();

            if (blockName.Contains("."))
            {
                deferredNames.AddRange(blockName.Split('.'));
                blockName     = deferredNames[0];
                deferredNames = deferredNames.Skip(1).ToList();
                deferredArgs.AddRange(args.Skip(1));
                args = new List <string> {
                    blockName
                };
            }

            if (blockName.Contains("]"))
            {
                var openBracketIndex  = blockName.IndexOf('[');
                var closeBracketIndex = blockName.IndexOf(']');
                var name  = blockName.Substring(0, openBracketIndex);
                var index = blockName.Substring(openBracketIndex + 1, (closeBracketIndex - openBracketIndex) - 1);

                blockName = name;
                args      = new List <string> {
                    name, index
                };
            }

            var blockNameLow = blockName.ToLower();
            var field        = enumerator.Find(f => f.Name == blockName || f.Name.ToLower() == blockNameLow);

            if (field == null)
            {
                Console.WriteLine("{0} does not contain a block named \"{1}\"", ownerType.Name, blockName);
                return(false);
            }

            var    contextName = "";
            object blockValue  = null;

            var structureAttribute = field.FieldType.CustomAttributes.ToList().Find(a => a.AttributeType == typeof(TagStructureAttribute));

            if (structureAttribute != null)
            {
                if (args.Count != 1)
                {
                    return(false);
                }

                blockValue  = field.GetValue(Owner);
                contextName = $"{blockName}";
            }
            else
            {
                if (args.Count != 2)
                {
                    return(false);
                }

                IList fieldValue = null;

                if (field.FieldType.GetInterface("IList") == null || (fieldValue = (IList)field.GetValue(Owner)) == null)
                {
                    Console.WriteLine("{0} does not contain a block named \"{1}\"", ownerType.Name, blockName);
                    return(false);
                }

                int blockIndex = 0;

                if (args[1] == "*")
                {
                    blockIndex = fieldValue.Count - 1;
                }
                else if (!int.TryParse(args[1], out blockIndex))
                {
                    Console.WriteLine("Invalid index requested from block {0}: {1}", blockName, blockIndex);
                    return(false);
                }

                if (blockIndex >= fieldValue.Count || blockIndex < 0)
                {
                    Console.WriteLine("Invalid index requested from block {0}: {1}", blockName, blockIndex);
                    return(false);
                }

                blockValue  = fieldValue[blockIndex];
                contextName = $"{blockName}[{blockIndex}]";
            }

            var blockStructure = new TagStructureInfo(blockValue.GetType());

            var blockContext = new CommandContext(Stack.Context, contextName);

            blockContext.AddCommand(new ListFieldsCommand(Info, blockStructure, blockValue));
            blockContext.AddCommand(new SetFieldCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new EditBlockCommand(Stack, Info, Tag, blockValue));
            blockContext.AddCommand(new AddToBlockCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new RemoveFromBlockCommand(Stack, Info, Tag, blockStructure, blockValue));
            blockContext.AddCommand(new ExitToCommand(Stack));
            Stack.Push(blockContext);

            if (deferredNames.Count != 0)
            {
                var name = deferredNames[0];
                deferredNames = deferredNames.Skip(1).ToList();

                foreach (var deferredName in deferredNames)
                {
                    name += '.' + deferredName;
                }

                args = new List <string> {
                    name
                };
                args.AddRange(deferredArgs);

                var command = new EditBlockCommand(Stack, Info, Tag, blockValue);
                return(command.Execute(args));
            }

            return(true);
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 3)
                return false;

            var fieldName = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext = Stack.Context;
            var previousOwner = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List<string> { blockName }))
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);
            var fieldType = field.FieldType;

            if ((field == null) ||
                (!fieldType.IsGenericType) ||
                (fieldType.GetInterface("IList") == null))
            {
                Console.WriteLine("ERROR: {0} does not contain a tag block named \"{1}\".", Structure.Types[0].Name, args[0]);
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            var blockValue = field.GetValue(Owner) as IList;

            if (blockValue == null)
            {
                blockValue = Activator.CreateInstance(field.FieldType) as IList;
                field.SetValue(Owner, blockValue);
            }

            var elementType = field.FieldType.GenericTypeArguments[0];

            var index = blockValue.Count - 1;
            var count = 1;

            var genericIndex = false;
            var genericCount = false;

            if (args.Count == 1)
            {
                count = 1;
            }
            else
            {
                if (args.Count >= 2)
                {
                    if (args[1] == "*")
                    {
                        genericIndex = true;
                        index = blockValue.Count - 1;
                    }
                    else if (!int.TryParse(args[1], out index) || index < 0 || index >= blockValue.Count)
                    {
                        Console.WriteLine($"Invalid index specified: {args[1]}");
                        return false;
                    }
                }

                if (args.Count == 3)
                {
                    if (args[2] == "*")
                    {
                        genericCount = true;
                        count = blockValue.Count - index;
                    }
                    else if (!int.TryParse(args[2], out count) || count < 1)
                    {
                        Console.WriteLine($"Invalid number specified: {args[2]}");
                        return false;
                    }
                }
            }

            if (genericIndex && genericCount)
            {
                index = 0;
                count = blockValue.Count;
            }
            else if (genericIndex)
            {
                index -= count;

                if (index < 0)
                    index = 0;
            }

            if (index + count > blockValue.Count)
            {
                Console.WriteLine($"ERROR: Too many block elements specified to be removed: {count}. Maximum at index {index} can be {blockValue.Count - index}");
                return false;
            }

            for (var i = 0; i < count; i++)
                blockValue.RemoveAt(index);

            field.SetValue(Owner, blockValue);

            var typeString =
                fieldType.IsGenericType ?
                    $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var itemString = count < 2 ? "element" : "elements";

            var valueString =
                ((IList)blockValue).Count != 0 ?
                    $"{{...}}[{((IList)blockValue).Count}]" :
                "null";

            Console.WriteLine($"Successfully removed {count} {itemString} from {field.Name} at index {index}: {typeString}");
            Console.WriteLine(valueString);

            while (Stack.Context != previousContext) Stack.Pop();
            Owner = previousOwner;
            Structure = previousStructure;

            return true;
        }
        public override bool Execute(List <string> args)
        {
            if (args.Count < 1 || args.Count > 3)
            {
                return(false);
            }

            var fieldName    = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext   = Stack.Context;
            var previousOwner     = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName    = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List <string> {
                    blockName
                }))
                {
                    while (Stack.Context != previousContext)
                    {
                        Stack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner     = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext)
                    {
                        Stack.Pop();
                    }
                    Owner     = previousOwner;
                    Structure = previousStructure;
                    return(false);
                }
            }

            var count = 1;

            if ((args.Count > 1 && !int.TryParse(args[1], out count)) || count < 1)
            {
                Console.WriteLine($"Invalid amount specified: {args[1]}");
                return(false);
            }

            var index = -1;

            if (args.Count > 2)
            {
                if (args[2] != "*" && (!int.TryParse(args[2], out index) || index < 0))
                {
                    Console.WriteLine($"Invalid index specified: {args[2]}");
                    return(false);
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field      = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);
            var fieldType  = field.FieldType;

            if ((field == null) ||
                (!fieldType.IsGenericType) ||
                (fieldType.GetInterface("IList") == null))
            {
                Console.WriteLine("ERROR: {0} does not contain a tag block named \"{1}\".", Structure.Types[0].Name, args[0]);
                while (Stack.Context != previousContext)
                {
                    Stack.Pop();
                }
                Owner     = previousOwner;
                Structure = previousStructure;
                return(false);
            }

            var blockValue = field.GetValue(Owner) as IList;

            if (blockValue == null)
            {
                blockValue = Activator.CreateInstance(field.FieldType) as IList;
                field.SetValue(Owner, blockValue);
            }

            if (index > blockValue.Count)
            {
                Console.WriteLine($"Invalid index specified: {args[2]}");
                return(false);
            }

            var elementType = field.FieldType.GenericTypeArguments[0];

            for (var i = 0; i < count; i++)
            {
                var element = CreateElement(elementType);

                if (index == -1)
                {
                    blockValue.Add(element);
                }
                else
                {
                    blockValue.Insert(index + i, element);
                }
            }

            field.SetValue(Owner, blockValue);

            var typeString =
                fieldType.IsGenericType ?
                $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var itemString = count < 2 ? "element" : "elements";

            var valueString =
                ((IList)blockValue).Count != 0 ?
                $"{{...}}[{((IList)blockValue).Count}]" :
                "null";

            Console.WriteLine($"Successfully added {count} {itemString} to {field.Name}: {typeString}");
            Console.WriteLine(valueString);

            while (Stack.Context != previousContext)
            {
                Stack.Pop();
            }
            Owner     = previousOwner;
            Structure = previousStructure;

            return(true);
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 2)
                return false;

            if (CopyElementsCommand.Elements == null)
            {
                Console.WriteLine("No elements are available in the clipboard.");
                return false;
            }

            var fieldName = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext = Stack.Context;
            var previousOwner = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List<string> { blockName }))
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }
            }

            var index = -1;

            if (args.Count > 1)
            {
                if (args[1] != "*" && (!int.TryParse(args[1], out index) || index < 0))
                {
                    Console.WriteLine($"Invalid index specified: {args[1]}");
                    return false;
                }
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);
            var fieldType = field.FieldType;

            if ((field == null) ||
                (!fieldType.IsGenericType) ||
                (fieldType.GetInterface("IList") == null))
            {
                Console.WriteLine("ERROR: {0} does not contain a tag block named \"{1}\".", Structure.Types[0].Name, args[0]);
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            var elementType = field.FieldType.GenericTypeArguments[0];

            if (elementType != CopyElementsCommand.ElementType)
            {
                Console.WriteLine("Invalid block element type!");
                return false;
            }

            var blockValue = field.GetValue(Owner) as IList;

            if (blockValue == null)
            {
                blockValue = Activator.CreateInstance(field.FieldType) as IList;
                field.SetValue(Owner, blockValue);
            }

            if (index > blockValue.Count)
            {
                Console.WriteLine($"Invalid index specified: {args[2]}");
                return false;
            }

            for (var i = 0; i < CopyElementsCommand.Elements.Count; i++)
            {
                var element = CopyElementsCommand.Elements[i];

                if (index == -1)
                    blockValue.Add(element);
                else
                    blockValue.Insert(index + i, element);
            }

            field.SetValue(Owner, blockValue);

            var typeString =
                fieldType.IsGenericType ?
                    $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var itemString = CopyElementsCommand.Elements.Count < 2 ? "element" : "elements";

            var valueString =
                ((IList)blockValue).Count != 0 ?
                    $"{{...}}[{((IList)blockValue).Count}]" :
                "null";

            Console.WriteLine($"Successfully pasted {CopyElementsCommand.Elements.Count} {itemString} to {field.Name}: {typeString}");
            Console.WriteLine(valueString);

            while (Stack.Context != previousContext) Stack.Pop();
            Owner = previousOwner;
            Structure = previousStructure;

            return true;
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count < 1 || args.Count > 2)
                return false;

            var fieldName = args[0];
            var fieldNameLow = fieldName.ToLower();

            var previousContext = Stack.Context;
            var previousOwner = Owner;
            var previousStructure = Structure;

            if (fieldName.Contains("."))
            {
                var lastIndex = fieldName.LastIndexOf('.');
                var blockName = fieldName.Substring(0, lastIndex);
                fieldName = fieldName.Substring(lastIndex + 1, (fieldName.Length - lastIndex) - 1);
                fieldNameLow = fieldName.ToLower();

                var command = new EditBlockCommand(Stack, Info, Tag, Owner);

                if (!command.Execute(new List<string> { blockName }))
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }

                command = (Stack.Context.GetCommand("Edit") as EditBlockCommand);

                Owner = command.Owner;
                Structure = command.Structure;

                if (Owner == null)
                {
                    while (Stack.Context != previousContext) Stack.Pop();
                    Owner = previousOwner;
                    Structure = previousStructure;
                    return false;
                }
            }

            var count = 1;

            if ((args.Count == 2 && !int.TryParse(args[1], out count)) || count < 1)
            {
                Console.WriteLine($"Invalid number specified: {args[1]}");
                return false;
            }

            var enumerator = new TagFieldEnumerator(Structure);
            var field = enumerator.Find(f => f.Name == fieldName || f.Name.ToLower() == fieldNameLow);
            var fieldType = field.FieldType;

            if ((field == null) ||
                (!fieldType.IsGenericType) ||
                (fieldType.GetInterface("IList") == null))
            {
                Console.WriteLine("ERROR: {0} does not contain a tag block named \"{1}\".", Structure.Types[0].Name, args[1]);
                while (Stack.Context != previousContext) Stack.Pop();
                Owner = previousOwner;
                Structure = previousStructure;
                return false;
            }

            var fieldValue = field.GetValue(Owner) as IList;

            if (fieldValue == null)
                field.SetValue(Owner, Activator.CreateInstance(field.FieldType));

            for (var i = 0; i < count; i++)
                fieldValue.Add(Activator.CreateInstance(field.FieldType.GenericTypeArguments[0]));

            field.SetValue(Owner, fieldValue);

            var typeString =
                fieldType.IsGenericType ?
                    $"{fieldType.Name}<{fieldType.GenericTypeArguments[0].Name}>" :
                fieldType.Name;

            var itemString = count < 2 ? "element" : "elements";

            var valueString =
                ((IList)fieldValue).Count != 0 ?
                    $"{{...}}[{((IList)fieldValue).Count}]" :
                "null";

            Console.WriteLine($"Successfully added {count} {itemString} to {field.Name}: {typeString}");
            Console.WriteLine(valueString);

            while (Stack.Context != previousContext) Stack.Pop();
            Owner = previousOwner;
            Structure = previousStructure;

            return true;
        }