예제 #1
0
 /// <summary>
 /// This is called when the enter key is pressed or when navigating to an empty line.
 /// </summary>
 /// <param name="line"></param>
 /// <returns></returns>
 public int?GetDesiredIndentation(ITextSnapshotLine line)
 {
     if (VSGeneroPackage.Instance.LangPrefs.IndentMode == vsIndentStyle.vsIndentStyleSmart)
     {
         return(AutoIndent.GetLineIndentation(line, _textView));
     }
     else
     {
         return(null);
     }
 }
예제 #2
0
        void TextBuffer_Changed(object sender, TextContentChangedEventArgs e)
        {
            string filename = e.After.TextBuffer.GetFilePath();

            if (_textView != null &&
                _textView.Caret.Position.BufferPosition.Position >= 0 &&
                _textView.Caret.Position.BufferPosition.Position <= e.After.Length &&
                _ignoreNextChange != _textView.Caret.Position.BufferPosition.Position)
            {
                if (e.Changes.Count == 0 ||
                    e.Changes[0].Delta < 0 ||
                    string.IsNullOrWhiteSpace(e.Changes[0].NewText))
                {
                    return;
                }

                var line           = e.After.GetLineFromPosition(_textView.Caret.Position.BufferPosition.Position);
                var currLineTokens = _classifier.GetClassificationSpans(line);

                var lineStr = line.GetText();

                TokenKind alignWith        = TokenKind.EndOfFile;
                bool      indentAfterAlign = false;
                bool      useContains      = false;

                if (currLineTokens.Count > 0 && currLineTokens[0].ClassificationType.IsOfType(PredefinedClassificationTypeNames.Keyword))
                {
                    if (currLineTokens[0].Span.GetText().Equals("end", StringComparison.OrdinalIgnoreCase))
                    {
                        if (currLineTokens.Count > 1)
                        {
                            var tok = Tokens.GetToken(currLineTokens[1].Span.GetText());
                            if (tok != null && AutoIndent.BlockKeywords.ContainsKey(tok.Kind))
                            {
                                useContains = AutoIndent.BlockKeywordsContainsCheck.Contains(tok.Kind);
                                alignWith   = tok.Kind;
                            }
                        }
                    }
                    else
                    {
                        var tok = Tokens.GetToken(currLineTokens[0].Span.GetText());
                        if (tok != null && AutoIndent.SubBlockKeywords.ContainsKey(tok.Kind))
                        {
                            alignWith        = AutoIndent.SubBlockKeywords[tok.Kind].Item1;
                            indentAfterAlign = AutoIndent.SubBlockKeywords[tok.Kind].Item2;
                        }
                    }
                }

                if (alignWith != TokenKind.EndOfFile)
                {
                    var keyword = Tokens.TokenKinds[alignWith];
                    ITextSnapshotLine prevLine;
                    int    prevLineNo  = line.LineNumber - 1;
                    bool   found       = false;
                    string prevLineStr = null;
                    // find the line that corresponds
                    int inNestedBlockCount = 0;

                    IList <ClassificationSpan> lineTokens = null;

                    while (prevLineNo >= 0)
                    {
                        prevLine    = e.After.GetLineFromLineNumber(prevLineNo);
                        prevLineStr = prevLine.GetText();
                        lineTokens  = _classifier.GetClassificationSpans(prevLine);

                        if (lineTokens.Count > 0 && lineTokens[0].ClassificationType.IsOfType(PredefinedClassificationTypeNames.Keyword))
                        {
                            if (lineTokens[0].Span.GetText().Equals("end", StringComparison.OrdinalIgnoreCase) &&
                                lineTokens.Count > 1 &&
                                lineTokens[1].Span.GetText().Equals(keyword, StringComparison.OrdinalIgnoreCase))
                            {
                                inNestedBlockCount++;
                            }
                            else if ((!useContains && lineTokens[0].Span.GetText().Equals(keyword, StringComparison.OrdinalIgnoreCase)) ||
                                     (useContains && lineTokens.Any(x => x.Span.GetText().Equals(keyword, StringComparison.OrdinalIgnoreCase))))
                            {
                                if (inNestedBlockCount > 0)
                                {
                                    inNestedBlockCount--;
                                }
                                else
                                {
                                    found = true;
                                    break;
                                }
                            }
                            else if (!useContains &&
                                     keyword.Equals("function", StringComparison.OrdinalIgnoreCase) &&
                                     lineTokens.Count > 1 &&
                                     lineTokens[1].Span.GetText().Equals(keyword, StringComparison.OrdinalIgnoreCase))
                            {
                                found = true;
                                break;
                            }
                        }
                        prevLineNo--;
                    }

                    // get the line's indentation
                    if (found)
                    {
                        int indentSize         = _options.GetIndentSize();
                        int desiredIndentation = AutoIndent.GetIndentation(prevLineStr, indentSize);
                        if (indentAfterAlign)
                        {
                            desiredIndentation += indentSize;
                        }
                        int currIndentation = AutoIndent.GetIndentation(lineStr, indentSize);
                        if (desiredIndentation != currIndentation)
                        {
                            string replacement = null;
                            if (desiredIndentation < currIndentation)
                            {
                                replacement = lineStr.Substring(currIndentation - desiredIndentation);
                            }
                            else
                            {
                                StringBuilder sb = new StringBuilder();
                                for (int i = 0; i < (desiredIndentation - currIndentation); i++)
                                {
                                    sb.Append(' ');
                                }
                                sb.Append(lineStr);
                                replacement = sb.ToString();
                            }
                            _ignoreNextChange = _textView.Caret.Position.BufferPosition.Position;
                            ITextEdit edit = _textView.TextBuffer.CreateEdit();
                            edit.Replace(new Span(line.Start, line.Length), replacement);
                            edit.Apply();
                            return;
                        }
                    }
                }
            }
            _ignoreNextChange = -1;
        }