/// <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); } }
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; }