/// <param name="kind">The type of template tag we are processing</param>
        /// <param name="templateText">The text of the template tag which we are offering a completion in</param>
        /// <param name="templateStart">The offset in the buffer where the template starts</param>
        /// <param name="triggerPoint">The point in the buffer where the completion was triggered</param>
        internal CompletionSet GetCompletionSet(CompletionOptions options, VsProjectAnalyzer analyzer, TemplateTokenKind kind, string templateText, int templateStart, SnapshotPoint triggerPoint, out ITrackingSpan applicableSpan)
        {
            int position = triggerPoint.Position - templateStart;
            IEnumerable <CompletionInfo> tags;
            IDjangoCompletionContext     context;

            applicableSpan = GetWordSpan(templateText, templateStart, triggerPoint);

            switch (kind)
            {
            case TemplateTokenKind.Block:
                var block = DjangoBlock.Parse(templateText);
                if (block != null)
                {
                    if (position <= block.ParseInfo.Start + block.ParseInfo.Command.Length)
                    {
                        // we are completing before the command
                        // TODO: Return a new set of tags?  Do nothing?  Do this based upon ctrl-space?
                        tags = FilterBlocks(CompletionInfo.ToCompletionInfo(analyzer.GetTags(), StandardGlyphGroup.GlyphKeyword), triggerPoint);
                    }
                    else
                    {
                        // we are in the arguments, let the block handle the completions
                        context = new ProjectBlockCompletionContext(analyzer, _buffer);
                        tags    = block.GetCompletions(context, position);
                    }
                }
                else
                {
                    // no tag entered yet, provide the known list of tags.
                    tags = FilterBlocks(CompletionInfo.ToCompletionInfo(analyzer.GetTags(), StandardGlyphGroup.GlyphKeyword), triggerPoint);
                }
                break;

            case TemplateTokenKind.Variable:
                var variable = DjangoVariable.Parse(templateText);
                context = new ProjectBlockCompletionContext(analyzer, _buffer);
                if (variable != null)
                {
                    tags = variable.GetCompletions(context, position);
                }
                else
                {
                    // show variable names
                    tags = CompletionInfo.ToCompletionInfo(context.Variables, StandardGlyphGroup.GlyphGroupVariable);
                }

                break;

            default:
                throw new InvalidOperationException();
            }

            var completions = tags
                              .OrderBy(tag => tag.DisplayText, StringComparer.OrdinalIgnoreCase)
                              .Select(tag => new DynamicallyVisibleCompletion(
                                          tag.DisplayText,
                                          tag.InsertionText,
                                          StripDocumentation(tag.Documentation),
                                          _glyphService.GetGlyph(tag.Glyph, StandardGlyphItem.GlyphItemPublic),
                                          "tag"));

            return(new FuzzyCompletionSet(
                       "PythonDjangoTags",
                       "Django Tags",
                       applicableSpan,
                       completions,
                       options,
                       CompletionComparer.UnderscoresLast));
        }
Esempio n. 2
0
        public static DjangoForBlock Parse(BlockParseInfo parseInfo)
        {
            var words   = parseInfo.Args.Split(' ');
            int inStart = -1;

            int inOffset = 0, inIndex = -1;
            var definitions = new List <Tuple <string, int> >();

            for (int i = 0; i < words.Length; i++)
            {
                var word = words[i];
                if (word == "in")
                {
                    inStart = inOffset + parseInfo.Start + parseInfo.Command.Length;
                    inIndex = i;
                    break;
                }
                else if (words[i].IndexOfAny(NewLines) != -1)
                {
                    // unterminated tag
                    break;
                }

                if (!String.IsNullOrEmpty(word))
                {
                    definitions.Add(new Tuple <string, int>(word, inOffset + parseInfo.Start + parseInfo.Command.Length));
                }
                inOffset += words[i].Length + 1;
            }

            // parse the arguments...
            int            reversedStart = -1;
            DjangoVariable variable      = null;
            int            argsEnd       = -1;

            if (inIndex != -1)
            {
                string filterText = "";
                argsEnd = inStart + "in".Length + 1;
                for (int i = inIndex + 1; i < words.Length; i++)
                {
                    int    nlStart = words[i].IndexOfAny(NewLines);
                    string trimmed = words[i];
                    if (nlStart != -1)
                    {
                        trimmed = words[i].Substring(0, nlStart);
                    }

                    if (i != inIndex + 1 && trimmed == words[i])   // if we trimmed we don't have an extra space
                    {
                        filterText += " ";
                        argsEnd    += 1;
                    }

                    if (trimmed == "reversed")
                    {
                        reversedStart = argsEnd;
                        break;
                    }

                    filterText += trimmed;
                    argsEnd    += trimmed.Length;
                    if (trimmed != words[i])
                    {
                        // unterminated tag
                        break;
                    }
                }

                var trimmedFilter = filterText.TrimStart(' ');

                variable = DjangoVariable.Parse(trimmedFilter,
                                                inStart + "in".Length + 1 + filterText.Length - trimmedFilter.Length);
            }

            return(new DjangoForBlock(parseInfo, inStart, variable, argsEnd, reversedStart, definitions.ToArray()));
        }