private static void IndentCaretInNewScope(ITextView textView, IScope scope, SnapshotPoint caretBufferPoint, RFormatOptions options) { if (scope == null || scope.OpenCurlyBrace == null) { return; } ITextSnapshot rSnapshot = caretBufferPoint.Snapshot; ITextBuffer rTextBuffer = rSnapshot.TextBuffer; int rCaretPosition = caretBufferPoint.Position; var caretLine = rSnapshot.GetLineFromPosition(rCaretPosition); int innerIndentSize = SmartIndenter.InnerIndentSizeFromNode(rTextBuffer, scope, options); int openBraceLineNumber = rSnapshot.GetLineNumberFromPosition(scope.OpenCurlyBrace.Start); var braceLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber); var indentLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1); string lineBreakText = braceLine.GetLineBreakText(); rTextBuffer.Insert(indentLine.Start, lineBreakText); // Fetch the line again since snapshot has changed when line break was inserted indentLine = rTextBuffer.CurrentSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1); // Map new caret position back to the view var positionInView = textView.MapUpToView(indentLine.Start); if (positionInView.HasValue) { var viewIndentLine = textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(positionInView.Value); textView.Caret.MoveTo(new VirtualSnapshotPoint(viewIndentLine.Start, innerIndentSize)); } }
private static void IndentCaretInNewScope(ITextView textView, ITextBuffer textBuffer, IScope scope, RFormatOptions options) { ITextSnapshot snapshot = textBuffer.CurrentSnapshot; SnapshotPoint?positionInBuffer = textView.MapDownToBuffer(textView.Caret.Position.BufferPosition, textBuffer); if (!positionInBuffer.HasValue || scope == null || scope.OpenCurlyBrace == null) { return; } int position = positionInBuffer.Value.Position; ITextSnapshotLine caretLine = snapshot.GetLineFromPosition(position); int innerIndentSize = SmartIndenter.InnerIndentSizeFromNode(textBuffer, scope, options); int openBraceLineNumber = snapshot.GetLineNumberFromPosition(scope.OpenCurlyBrace.Start); ITextSnapshotLine braceLine = snapshot.GetLineFromLineNumber(openBraceLineNumber); ITextSnapshotLine indentLine = snapshot.GetLineFromLineNumber(openBraceLineNumber + 1); string lineBreakText = braceLine.GetLineBreakText(); textBuffer.Insert(indentLine.Start, lineBreakText); positionInBuffer = textView.MapUpToBuffer(indentLine.Start.Position, textView.TextBuffer); if (!positionInBuffer.HasValue) { return; } indentLine = textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(positionInBuffer.Value); textView.Caret.MoveTo(new VirtualSnapshotPoint(indentLine, innerIndentSize)); }
/// <summary> /// Appends indentation to each line so formatted text appears properly /// indented inside the host document (script block in HTML page). /// </summary> private void IndentLines(IEditorBuffer textBuffer, ITextRange range, AstRoot ast, int originalIndentSizeInSpaces) { var snapshot = textBuffer.CurrentSnapshot; var firstLine = snapshot.GetLineFromPosition(range.Start); var lastLine = snapshot.GetLineFromPosition(range.End); var document = textBuffer.GetEditorDocument <IREditorDocument>(); for (var i = firstLine.LineNumber; i <= lastLine.LineNumber; i++) { // Snapshot is updated after each insertion so do not cache var line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(i); var indent = SmartIndenter.GetSmartIndent(line, _settings, ast, originalIndentSizeInSpaces, formatting: true); if (indent > 0 && line.Length > 0 && line.Start >= range.Start) { // Check current indentation and correct for the difference int currentIndentSize = IndentBuilder.TextIndentInSpaces(line.GetText(), _settings.TabSize); indent = Math.Max(0, indent - currentIndentSize); if (indent > 0) { var indentString = IndentBuilder.GetIndentString(indent, _settings.IndentType, _settings.TabSize); textBuffer.Insert(line.Start, indentString); if (document == null) { // Typically this is a test scenario only. In the real editor // instance document is available and automatically updates AST // when whitespace inserted, not no manual update is necessary. ast.ReflectTextChange(line.Start, 0, indentString.Length, textBuffer.CurrentSnapshot); } } } } }
/// <summary> /// Appends indentation to each line so formatted text appears properly /// indented inside the host document (script block in HTML page). /// </summary> private static void IndentLines(ITextView textView, ITextBuffer textBuffer, ITextRange range, AstRoot ast, RFormatOptions options, int originalIndentSizeInSpaces) { ITextSnapshot snapshot = textBuffer.CurrentSnapshot; ITextSnapshotLine firstLine = snapshot.GetLineFromPosition(range.Start); ITextSnapshotLine lastLine = snapshot.GetLineFromPosition(range.End); IREditorDocument document = REditorDocument.TryFromTextBuffer(textBuffer); for (int i = firstLine.LineNumber; i <= lastLine.LineNumber; i++) { // Snapshot is updated after each insertion so do not cache ITextSnapshotLine line = textBuffer.CurrentSnapshot.GetLineFromLineNumber(i); int indent = SmartIndenter.GetSmartIndent(line, ast, originalIndentSizeInSpaces); if (indent > 0 && line.Length > 0 && line.Start >= range.Start) { // Check current indentation and correct for the difference int currentIndentSize = line.Length - line.GetText().TrimStart().Length; indent = Math.Max(0, indent - currentIndentSize); if (indent > 0) { string indentString = IndentBuilder.GetIndentString(indent, options.IndentType, options.TabSize); textBuffer.Insert(line.Start, indentString); if (document == null) { // Typically this is a test scenario only. In the real editor // instance document is available and automatically updates AST // when whitespace inserted, not no manual update is necessary. ast.ReflectTextChange(line.Start, 0, indentString.Length); } } } } }
private static void IndentCaretInNewScope(IEditorView editorView, IScope scope, ISnapshotPoint caretBufferPoint, RFormatOptions options) { if (scope?.OpenCurlyBrace == null) { return; } var rSnapshot = caretBufferPoint.Snapshot; var rTextBuffer = rSnapshot.EditorBuffer; var innerIndentSize = SmartIndenter.InnerIndentSizeFromNode(rTextBuffer, scope, options); var openBraceLineNumber = rSnapshot.GetLineNumberFromPosition(scope.OpenCurlyBrace.Start); var braceLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber); var indentLine = rSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1); var lineBreakText = braceLine.LineBreak; rTextBuffer.Insert(indentLine.Start, lineBreakText); // Fetch the line again since snapshot has changed when line break was inserted indentLine = rTextBuffer.CurrentSnapshot.GetLineFromLineNumber(openBraceLineNumber + 1); // Map new caret position back to the view var positionInView = editorView.MapToView(rTextBuffer.CurrentSnapshot, indentLine.Start); if (positionInView != null) { var viewIndentLine = editorView.EditorBuffer.CurrentSnapshot.GetLineFromPosition(positionInView.Position); editorView.Caret.MoveTo(viewIndentLine.Start, innerIndentSize); } }
public static int GetBaseIndentFromNode(ITextBuffer textBuffer, AstRoot ast, int position) { ITextSnapshot snapshot = textBuffer.CurrentSnapshot; IAstNode node = GetIndentDefiningNode(ast, position); ITextSnapshotLine baseLine = snapshot.GetLineFromPosition(node.Start); return(SmartIndenter.GetSmartIndent(baseLine, ast)); }
public void SmartIndentTest05() { AstRoot ast; ITextView textView = TextViewTest.MakeTextView(" x <- 1\r\n", 0, out ast); using (var document = new EditorDocumentMock(new EditorTreeMock(textView.TextBuffer, ast))) { ISmartIndentProvider provider = _exportProvider.GetExportedValue <ISmartIndentProvider>("ContentTypes", RContentTypeDefinition.ContentType); SmartIndenter indenter = (SmartIndenter)provider.CreateSmartIndent(textView); int?indent = indenter.GetDesiredIndentation(textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(1), IndentStyle.Block); indent.Should().HaveValue().And.Be(2); } }
/// <summary> /// Appends indentation to each line so formatted text appears properly /// indented inside the host document (script block in HTML page). /// </summary> private static string IndentLines(ITextBuffer textBuffer, int rangeStartPosition, AstRoot ast, string formattedText, RFormatOptions options, int scopeStatementPosition, bool respectUserIndent = true) { ITextSnapshotLine firstLine = textBuffer.CurrentSnapshot.GetLineFromPosition(rangeStartPosition); string firstLineText = firstLine.GetText(); int baseIndentInSpaces; if (scopeStatementPosition >= 0) { // If parent statement position is provided, use it to determine indentation ITextSnapshotLine statementLine = textBuffer.CurrentSnapshot.GetLineFromPosition(scopeStatementPosition); baseIndentInSpaces = SmartIndenter.GetSmartIndent(statementLine, ast); } else if (respectUserIndent && RespectUserIndent(textBuffer, ast, rangeStartPosition)) { // Determine indent from fist line in multiline constructs // such as when function argument list spans multiple lines baseIndentInSpaces = IndentBuilder.TextIndentInSpaces(firstLineText, options.TabSize); } else { baseIndentInSpaces = SmartIndenter.GetSmartIndent(firstLine, ast); } // There are three major cases with range formatting: // 1. Formatting of a scope when } closes. // 2. Formatting of a single line on Enter or ; // 3. Formatting of a user-selected range. // // Indentation in (1) is relatively easy since complete scope is known. // (2) Is the most difficult is to figure out proper indent of a single }. // Normally we get statementPosition of the statement that define the scope // (3) Theoretically may end up with odd indents but users rarely intentionally // select strange ranges string indentString = IndentBuilder.GetIndentString(baseIndentInSpaces, options.IndentType, options.TabSize); var sb = new StringBuilder(); IList <string> lines = TextHelper.SplitTextIntoLines(formattedText); for (int i = 0; i < lines.Count; i++) { string lineText = lines[i]; if (i == 0 && lineText.Trim() == "{") { if (options.BracesOnNewLine && !LineBreakBeforePosition(textBuffer, rangeStartPosition)) { sb.Append("\r\n"); } if (scopeStatementPosition < 0 || options.BracesOnNewLine) { sb.Append(indentString); } sb.Append('{'); if (i < lines.Count - 1) { sb.Append("\r\n"); } continue; } if (i == lines.Count - 1 && lineText.Trim() == "}") { sb.Append(indentString); sb.Append('}'); break; } // Leave empty lines alone if (!string.IsNullOrWhiteSpace(lineText)) { sb.Append(indentString); } sb.Append(lineText); if (i < lines.Count - 1) { sb.Append("\r\n"); } } return(sb.ToString()); }