/// <summary>
        /// http://blog.280z28.org/archives/2010/01/92/
        /// </summary>
        /// <param name="spans"></param>
        /// <returns></returns>
        public IEnumerable <ITagSpan <Ps1KeywordTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            var colorizedTokens = new List <ITagSpan <Ps1KeywordTokenTag> >();

            try {
                foreach (SnapshotSpan curSpan in spans)
                {
                    ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine();
                    int    lineStartPosition         = containingLine.Start.Position;
                    string line               = containingLine.GetText();
                    string allText            = containingLine.Snapshot.GetText();
                    Tokens tokens             = new Tokens(line, lineStartPosition, "-$", "-$", supportSignleQuoteString: true);
                    string Value              = null;
                    bool   InsertCurrentToken = false;
                    bool   parsingPSNameSpace = false;        // sample: [System.NET.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
                    var    comments           = new JSON.SyntaxValidator.CommentParser().Parse(allText, "<#", "#>");

                    if (comments.IsPositionInComment(lineStartPosition) && comments.IsPositionInComment(lineStartPosition))
                    {
                        var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, line.Length));
                        lineStartPosition += line.Length;
                        if (tokenSpan.IntersectsWith(curSpan))
                        {
                            colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(tokens.Current.Value, tokens.Index, TagType.COMMENT)));
                        }
                        return(colorizedTokens);
                    }

                    while (tokens.Index < tokens.Count)
                    {
                        // -- Double and single quote string
                        if (tokens.Current.Type.In(TokenType.STRING, TokenType.SINGLE_QUOTE_STRING))
                        {
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, tokens.Current.Value.Length));
                            lineStartPosition += tokens.Current.Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(tokens.Current.Value, tokens.Index, TagType.STRING)));
                            }
                        }

                        // Id with - and $

                        else if (tokens.Current.IsID())
                        {
                            TagType tagType = TagType.OTHER;

                            if (_Ps1ColorEngine.Keywords.Contains(tokens.Current.Value, StringComparer.OrdinalIgnoreCase))
                            {
                                tagType = TagType.KEYWORD;
                            }
                            else if (_Ps1ColorEngine.Commands.Contains(tokens.Current.Value, StringComparer.OrdinalIgnoreCase))
                            {
                                tagType = TagType.COMMAND;
                            }
                            else if (tokens.Current.Value.StartsWith("-"))
                            {
                                tagType = TagType.PARAMETER;
                            }
                            else if (tokens.Current.Value.StartsWith("$"))
                            {
                                tagType = TagType.VARIABLE;
                            }
                            else if ((tokens.Previous.Value == ":") && (tokens.PreviousPrevious.Value == ":"))
                            {
                                tagType = TagType.KEYWORD;
                            }
                            else if (tokens.PreviousPrevious.Value == "function")
                            {
                                tagType = TagType.COMMAND;
                            }
                            else if (tokens.Previous.Value == "[" || tokens.PreviousPrevious.Value == "[")
                            {
                                if (this.IsCurrentTokenAPowerShellStaticNameSpaceReference(tokens))
                                {
                                    tagType            = TagType.KEYWORD;
                                    parsingPSNameSpace = true;
                                }
                            }
                            else if (parsingPSNameSpace)   // Is an Id part of a namespace

                            {
                                tagType = TagType.KEYWORD;
                                if (tokens.Previous.Value == "]")
                                {
                                    parsingPSNameSpace = false; // Found end of namespace declaration
                                }
                            }

                            Value = tokens.Current.Value;
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, Value.Length));
                            lineStartPosition += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(Value, tokens.Index, tagType)));
                            }
                        }
                        else if (tokens.Current.Value == "#")
                        {
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, line.Length));
                            lineStartPosition += line.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(tokens.Current.Value, tokens.Index, TagType.COMMENT)));
                            }
                            break;
                        }
                        else if (tokens.Current.Value.In("{", "}", "|", "[", "]", "`", "(", ")"))
                        {
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, tokens.Current.Value.Length));
                            lineStartPosition += tokens.Current.Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(tokens.Current.Value, tokens.Index, TagType.PUNCTUATION)));
                            }
                        }
                        else
                        {
                            InsertCurrentToken = true;
                        }
                        if (InsertCurrentToken)
                        {
                            InsertCurrentToken = false;  // Tokenize anything
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(lineStartPosition, tokens.Current.Length));
                            lineStartPosition += tokens.Current.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <Ps1KeywordTokenTag>(tokenSpan, new Ps1KeywordTokenTag(tokens.Current.Value, tokens.Index, TagType.OTHER)));
                            }
                        }
                        tokens.Index++;
                    }
                }
            }
            catch (System.Exception ex)
            {
                this.Out(ex.ToString());
                #if DEBUG
                Util.Utility.MsgBox(": (", ex);
                #endif
            }
            return(colorizedTokens);
        }
        public IEnumerable <ITagSpan <JsonKeywordTokenTag> > GetTags(NormalizedSnapshotSpanCollection spans)
        {
            var colorizedTokens = new List <ITagSpan <JsonKeywordTokenTag> >();

            try
            {
                foreach (SnapshotSpan curSpan in spans)
                {
                    ITextSnapshotLine containingLine = curSpan.Start.GetContainingLine();
                    int    curLocStart        = containingLine.Start.Position;
                    int    curLocEnd          = containingLine.End.Position;
                    string line               = containingLine.GetText();
                    string allText            = containingLine.Snapshot.GetText();
                    Tokens Tokens             = new Tokens(line, curLocStart, "$", "$");
                    string Value              = null;
                    bool   insertCurrentToken = false;
                    var    comments           = new JSON.SyntaxValidator.CommentParser().Parse(allText);

                    #if DEBUG
                    //this.Out("\nColorCoding:[{0},{1}]{2}".format(curLocStart, curLocEnd, line));
                    this.Out("CC Parse:" + line);
                    #endif

                    if (comments.IsPositionInComment(curLocStart) && comments.IsPositionInComment(curLocEnd))
                    {
                        var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, line.Length));
                        curLocStart += line.Length;
                        if (tokenSpan.IntersectsWith(curSpan))
                        {
                            colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, TagType.COMMENT)));
                        }
                        return(colorizedTokens);
                    }

                    while (Tokens.Index < Tokens.Count)
                    {
                        if (comments.IsPositionInComment(Tokens.Current.Position))
                        {
                            Value = Tokens.Current.Value;
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, TagType.COMMENT)));
                            }
                        }
                        else if (Tokens.Current.Type == TokenType.OTHER) //&& Tokens.Current.Value == " "
                        {
                            insertCurrentToken = true;
                        }
                        else if (Tokens.Current.IsSlashComment() && Tokens.Next.IsSlashComment())
                        {
                            // The position of the token is wrong, if the // is in the middle of the string, we have to go back
                            // 2 + 1 for start at 0. if it is at the begining of the line the postion is 0
                            var slashSlashPos = Tokens.Current.AbsolutePosition;
                            if (slashSlashPos < 0)
                            {
                                slashSlashPos = 0;
                            }
                            Value = line.Substring(slashSlashPos);

                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Value, Tokens.Index, TagType.COMMENT)));
                            }
                            break;
                        }
                        // []{}:,
                        else if (Tokens.Current.IsJsonPunctuation())
                        {
                            Value = Tokens.Current.Value;
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Value, Tokens.Index, TagType.PUNCTUATION)));
                            }
                        }
                        else if (Tokens.Current.Type == TokenType.STRING)
                        {
                            TagType tagType = TagType.STRING;
                            Tokens.PushIndex();
                            if (Tokens.NextIgnoreOther.IsOp(":"))
                            {
                                tagType = TagType.ID;
                            }
                            Tokens.PopIndex();

                            if (JSON.SyntaxValidator.Tokenizer.IsJsonDate(Tokens.Current.Value))
                            {
                                tagType = TagType.DATE;
                            }

                            Value = Tokens.Current.Value;//.Replace(@"""", @"\""");
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, tagType)));
                            }
                        }
                        else if (Tokens.Current.Type == TokenType.INTEGER)
                        {
                            Value = Tokens.Current.Value;
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, TagType.NUMBER)));
                            }
                        }
                        else if (Tokens.Current.Type == TokenType.ID)
                        {
                            Value = Tokens.Current.Value;
                            var tagType = ((Value == "true") || (Value == "false")) ? TagType.BOOLEAN : TagType.ID;

                            if (Value == "null")
                            {
                                tagType = TagType.NULL;
                            }

                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Value.Length));
                            curLocStart += Value.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, tagType)));
                            }
                        }
                        //// Comment as //   or /* */ for now second syntax must be on one line
                        //else if ((Tokens.Current.IsOp("/") && Tokens.Next.IsOp("*")))
                        //{
                        //    var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, line.Length));
                        //    curLocStart += line.Length;
                        //    if (tokenSpan.IntersectsWith(curSpan))
                        //        colorizedTokens.Add(new TagSpan<JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index, TagType.COMMENT)));
                        //    break;
                        //}
                        else
                        {
                            insertCurrentToken = true;
                        }

                        if (insertCurrentToken)
                        {
                            insertCurrentToken = false; // Tokenize anything
                            var tokenSpan = new SnapshotSpan(curSpan.Snapshot, new Span(curLocStart, Tokens.Current.Length));
                            curLocStart += Tokens.Current.Length;
                            if (tokenSpan.IntersectsWith(curSpan))
                            {
                                colorizedTokens.Add(new TagSpan <JsonKeywordTokenTag>(tokenSpan, new JsonKeywordTokenTag(Tokens.Current.Value, Tokens.Index)));
                            }
                        }
                        Tokens.Index++;
                    }
                }
            }
            catch (System.Exception ex)
            {
                this.Out(ex.ToString());
                #if DEBUG
                //System.Diagnostics.Debugger.Break();
                #endif
            }
            return(colorizedTokens);
        }