Esempio n. 1
0
        public static void HandleAutoformat(ITextView textView, IEditorShell editorShell, char typedChar)
        {
            if (!REditorSettings.AutoFormat)
            {
                return;
            }

            if (!REditorSettings.FormatScope && typedChar == '}')
            {
                return;
            }

            SnapshotPoint?rPoint = GetCaretPointInBuffer(textView);

            if (!rPoint.HasValue)
            {
                return;
            }

            var document = REditorDocument.FromTextBuffer(textView.TextBuffer);
            var ast      = document.EditorTree.AstRoot;

            // Make sure we are not formatting damaging the projected range in R Markdown
            // which looks like ```{r. 'r' should not separate from {.
            var host = ContainedLanguageHost.GetHost(textView, document.TextBuffer, editorShell);

            if (host != null && !host.CanFormatLine(textView, document.TextBuffer, document.TextBuffer.CurrentSnapshot.GetLineNumberFromPosition(rPoint.Value)))
            {
                return;
            }

            // We don't want to auto-format inside strings
            if (ast.IsPositionInsideString(rPoint.Value.Position))
            {
                return;
            }

            ITextBuffer subjectBuffer = rPoint.Value.Snapshot.TextBuffer;

            if (typedChar.IsLineBreak())
            {
                // Special case for hitting caret after } and before 'else'. We do want to format
                // the construct as '} else {' but if user types Enter after } and we auto-format
                // it will look as if the editor just eats the Enter. Instead, we will not be
                // autoformatting in this specific case. User can always format either the document
                // or select the block and reformat it.
                if (!IsBetweenCurlyAndElse(subjectBuffer, rPoint.Value.Position))
                {
                    var scopeStatement = GetFormatScope(textView, subjectBuffer, ast);
                    // Do not format large scope blocks for performance reasons
                    if (scopeStatement != null && scopeStatement.Length < 200)
                    {
                        FormatOperations.FormatNode(textView, subjectBuffer, editorShell, scopeStatement);
                    }
                    else if (CanFormatLine(textView, subjectBuffer, -1))
                    {
                        FormatOperations.FormatViewLine(textView, subjectBuffer, -1, editorShell);
                    }
                }
            }
            else if (typedChar == ';')
            {
                // Verify we are at the end of the string and not in a middle
                // of another string or inside a statement.
                ITextSnapshotLine line = subjectBuffer.CurrentSnapshot.GetLineFromPosition(rPoint.Value.Position);
                int    positionInLine  = rPoint.Value.Position - line.Start;
                string lineText        = line.GetText();
                if (positionInLine >= lineText.TrimEnd().Length)
                {
                    FormatOperations.FormatViewLine(textView, subjectBuffer, 0, editorShell);
                }
            }
            else if (typedChar == '}')
            {
                FormatOperations.FormatCurrentStatement(textView, subjectBuffer, editorShell, limitAtCaret: true, caretOffset: -1);
            }
        }
Esempio n. 2
0
        public static void HandleAutoformat(ITextView textView, char typedChar)
        {
            if (!REditorSettings.AutoFormat || IgnoreOnce)
            {
                IgnoreOnce = false;
                return;
            }

            SnapshotPoint?rPoint = GetCaretPointInBuffer(textView);

            if (!rPoint.HasValue)
            {
                return;
            }

            var document = REditorDocument.FromTextBuffer(textView.TextBuffer);
            var et       = document.EditorTree;
            var ast      = et.GetCurrentRootOrPreviousIfNotReady();

            // We don't want to auto-format inside strings
            if (ast.IsPositionInsideString(rPoint.Value.Position))
            {
                return;
            }

            ITextBuffer subjectBuffer = rPoint.Value.Snapshot.TextBuffer;

            if (typedChar.IsLineBreak())
            {
                // Special case for hitting caret after } and before 'else'. We do want to format
                // the construct as '} else {' but if user types Enter after } and we auto-format
                // it will look as if the editor just eats the Enter. Instead, we will not be
                // autoformatting in this specific case. User can always format either the document
                // or select the block and reformat it.
                if (!IsBetweenCurlyAndElse(subjectBuffer, rPoint.Value.Position))
                {
                    var scopeStatement = GetFormatScope(textView, subjectBuffer, ast, -1);
                    // Do not format large scope blocks for performance reasons
                    if (scopeStatement != null && scopeStatement.Length < 200)
                    {
                        FormatOperations.FormatNode(textView, subjectBuffer, scopeStatement);
                    }
                    else
                    {
                        FormatOperations.FormatLine(textView, subjectBuffer, -1);
                    }
                }
            }
            else if (typedChar == ';')
            {
                // Verify we are at the end of the string and not in a middle
                // of another string or inside a statement.
                ITextSnapshotLine line = subjectBuffer.CurrentSnapshot.GetLineFromPosition(rPoint.Value.Position);
                int    positionInLine  = rPoint.Value.Position - line.Start;
                string lineText        = line.GetText();
                if (positionInLine >= lineText.TrimEnd().Length)
                {
                    FormatOperations.FormatLine(textView, subjectBuffer, 0);
                }
            }
            else if (typedChar == '}')
            {
                FormatOperations.FormatCurrentStatement(textView, subjectBuffer);
            }
        }
Esempio n. 3
0
        public void HandleTyping(char typedChar, int position, IEditorBuffer editorBuffer = null, IIncrementalWhitespaceChangeHandler changeHandler = null)
        {
            if (!Settings.AutoFormat || (!Settings.FormatScope && typedChar == '}'))
            {
                return;
            }

            EditorBuffer = editorBuffer ?? EditorBuffer;
            var document = EditorBuffer.GetEditorDocument <IREditorDocument>();
            // AST may or may not be ready. Upto the caller to decide if it is worth waiting.
            var ast = document.EditorTree.AstRoot;

            // Make sure we are not formatting damaging the projected range in R Markdown
            // which looks like ```{r. 'r' should not separate from {.
            if (!CanFormatContainedLanguageLine(position, typedChar))
            {
                return;
            }

            // We don't want to auto-format inside strings
            if (ast.IsPositionInsideString(position))
            {
                return;
            }

            var fo = new FormatOperations(Services, EditorView, EditorBuffer, _changeHandler);

            if (typedChar.IsLineBreak())
            {
                // Special case for hitting caret after } and before 'else'. We do want to format
                // the construct as '} else {' but if user types Enter after } and we auto-format
                // it will look as if the editor just eats the Enter. Instead, we will not be
                // autoformatting in this specific case. User can always format either the document
                // or select the block and reformat it.
                if (!IsBetweenCurlyAndElse(position))
                {
                    var scopeStatement = GetFormatScope(position, ast);
                    // Do not format large scope blocks for performance reasons
                    if (scopeStatement != null && scopeStatement.Length < 200)
                    {
                        fo.FormatNode(scopeStatement);
                    }
                    else if (CanFormatLine(position, -1))
                    {
                        fo.FormatViewLine(-1);
                    }
                }
            }
            else if (typedChar == ';')
            {
                // Verify we are at the end of the string and not in a middle
                // of another string or inside a statement.
                var line           = EditorBuffer.CurrentSnapshot.GetLineFromPosition(position);
                var positionInLine = position - line.Start;
                var lineText       = line.GetText();
                if (positionInLine >= lineText.TrimEnd().Length)
                {
                    fo.FormatViewLine(0);
                }
            }
            else if (typedChar == '}')
            {
                fo.FormatCurrentStatement(limitAtCaret: true, caretOffset: -1);
            }
        }
Esempio n. 4
0
        public static void HandleAutoformat(ITextView textView, char typedChar)
        {
            if (!REditorSettings.AutoFormat || IgnoreOnce)
            {
                IgnoreOnce = false;
                return;
            }

            IEditorTree   tree;
            SnapshotPoint?rPoint = GetCaretPointInBuffer(textView, out tree);

            if (!rPoint.HasValue)
            {
                return;
            }

            // We don't want to auto-format inside strings
            if (tree.AstRoot.IsPositionInsideString(rPoint.Value.Position))
            {
                return;
            }

            ITextBuffer subjectBuffer = rPoint.Value.Snapshot.TextBuffer;

            if (typedChar.IsLineBreak())
            {
                // Special case for hitting caret after } and before 'else'. We do want to format
                // the construct as '} else {' but if user types Enter after } and we auto-format
                // it will look as if the editor just eats the Enter. Instead, we will not be
                // autoformatting in this specific case. User can always format either the document
                // or select the block and reformat it.
                if (!IsBetweenCurlyAndElse(subjectBuffer, rPoint.Value.Position))
                {
                    bool formatScope = ShouldFormatScope(textView, subjectBuffer, -1);
                    if (formatScope)
                    {
                        FormatOperations.FormatCurrentNode <IStatement>(textView, subjectBuffer);
                    }
                    else
                    {
                        FormatOperations.FormatLine(textView, subjectBuffer, tree.AstRoot, -1);
                    }
                }
            }
            else if (typedChar == ';')
            {
                // Verify we are at the end of the string and not in a middle
                // of another string or inside a statement.
                ITextSnapshotLine line = subjectBuffer.CurrentSnapshot.GetLineFromPosition(rPoint.Value.Position);
                int    positionInLine  = rPoint.Value.Position - line.Start;
                string lineText        = line.GetText();
                if (positionInLine >= lineText.TrimEnd().Length)
                {
                    FormatOperations.FormatLine(textView, subjectBuffer, tree.AstRoot, 0);
                }
            }
            else if (typedChar == '}')
            {
                FormatOperations.FormatNode <IStatement>(textView, subjectBuffer, Math.Max(rPoint.Value - 1, 0));
            }
        }