Пример #1
0
        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));
            }
        }
Пример #2
0
        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));
        }
Пример #3
0
        /// <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);
                        }
                    }
                }
            }
        }
Пример #4
0
        /// <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);
                        }
                    }
                }
            }
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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));
        }
Пример #7
0
        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);
            }
        }
Пример #8
0
        /// <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());
        }