string GetIndentationString(int offset, DocumentLocation loc) { stateTracker.Update(Math.Min(data.Length, offset)); DocumentLine line = data.Document.GetLine(loc.Line); if (line == null) { return(""); } // Get context to the end of the line w/o changing the main engine's state var ctx = stateTracker.Clone(); ctx.Update(line.Offset + line.Length); // int pos = line.Offset; string curIndent = line.GetIndentation(data.Document); int nlwsp = curIndent.Length; // int o = offset > pos + nlwsp ? offset - (pos + nlwsp) : 0; if (!stateTracker.LineBeganInsideMultiLineComment || (nlwsp < line.LengthIncludingDelimiter && data.Document.GetCharAt(line.Offset + nlwsp) == '*')) { return(ctx.ThisLineIndent); } return(curIndent); }
/// <inheritdoc /> string ITextPasteHandler.FormatPlainText(int offset, string text, byte[] copyData) { if (copyData != null && copyData.Length == 1) { var strategy = TextPasteUtils.Strategies[(PasteStrategy)copyData[0]]; text = strategy.Decode(text); } engine.Update(offset); if (engine.IsInsideStringLiteral) { int idx = text.IndexOf('"'); if (idx > 0) { var o = offset; while (o < engine.Document.TextLength) { char ch = engine.Document.GetCharAt(o); engine.Push(ch); if (NewLine.IsNewLine(ch)) { break; } o++; if (!engine.IsInsideStringLiteral) { return(TextPasteUtils.StringLiteralStrategy.Encode(text)); } } return(TextPasteUtils.StringLiteralStrategy.Encode(text.Substring(0, idx)) + text.Substring(idx)); } return(TextPasteUtils.StringLiteralStrategy.Encode(text)); } else if (engine.IsInsideVerbatimString) { int idx = text.IndexOf('"'); if (idx > 0) { var o = offset; while (o < engine.Document.TextLength) { char ch = engine.Document.GetCharAt(o); engine.Push(ch); o++; if (!engine.IsInsideVerbatimString) { return(TextPasteUtils.VerbatimStringStrategy.Encode(text)); } } return(TextPasteUtils.VerbatimStringStrategy.Encode(text.Substring(0, idx)) + text.Substring(idx)); } return(TextPasteUtils.VerbatimStringStrategy.Encode(text)); } var line = engine.Document.GetLineByOffset(offset); var pasteAtLineStart = line.Offset == offset; var indentedText = new StringBuilder(); var curLine = new StringBuilder(); var clonedEngine = engine.Clone(); bool isNewLine = false, gotNewLine = false; for (int i = 0; i < text.Length; i++) { var ch = text[i]; if (clonedEngine.IsInsideVerbatimString || clonedEngine.IsInsideMultiLineComment) { clonedEngine.Push(ch); curLine.Append(ch); continue; } var delimiterLength = NewLine.GetDelimiterLength(ch, i + 1 < text.Length ? text[i + 1] : ' '); if (delimiterLength > 0) { isNewLine = true; if (gotNewLine || pasteAtLineStart) { if (curLine.Length > 0 || formattingOptions.EmptyLineFormatting == EmptyLineFormatting.Indent) { indentedText.Append(clonedEngine.ThisLineIndent); } } indentedText.Append(curLine); indentedText.Append(textEditorOptions.EolMarker); curLine.Length = 0; gotNewLine = true; i += delimiterLength - 1; // textEditorOptions.EolMarker[0] is the newLineChar used by the indentation engine. clonedEngine.Push(textEditorOptions.EolMarker[0]); } else { if (isNewLine) { if (ch == '\t' || ch == ' ') { clonedEngine.Push(ch); continue; } isNewLine = false; } curLine.Append(ch); clonedEngine.Push(ch); } if (clonedEngine.IsInsideVerbatimString || clonedEngine.IsInsideMultiLineComment && !(clonedEngine.LineBeganInsideVerbatimString || clonedEngine.LineBeganInsideMultiLineComment)) { if (gotNewLine) { if (curLine.Length > 0 || formattingOptions.EmptyLineFormatting == EmptyLineFormatting.Indent) { indentedText.Append(clonedEngine.ThisLineIndent); } } pasteAtLineStart = false; indentedText.Append(curLine); curLine.Length = 0; gotNewLine = false; continue; } } if (gotNewLine && (!pasteAtLineStart || curLine.Length > 0)) { indentedText.Append(clonedEngine.ThisLineIndent); } if (curLine.Length > 0) { indentedText.Append(curLine); } return(indentedText.ToString()); }
/// <inheritdoc /> string ITextPasteHandler.FormatPlainText(SourceText sourceText, int offset, string text, byte [] copyData) { if (copyData != null && copyData.Length == 1) { var strategy = TextPasteUtils.Strategies [(PasteStrategy)copyData [0]]; text = strategy.Decode(text); } engine.Update(sourceText, offset); if (engine.IsInsideStringLiteral) { int idx = text.IndexOf('"'); if (idx > 0) { var o = offset; while (o < sourceText.Length) { char ch = sourceText [o]; engine.Push(ch); if (NewLine.IsNewLine(ch)) { break; } o++; if (!engine.IsInsideStringLiteral) { return(TextPasteUtils.StringLiteralStrategy.Encode(text)); } } return(TextPasteUtils.StringLiteralStrategy.Encode(text.Substring(0, idx)) + text.Substring(idx)); } return(TextPasteUtils.StringLiteralStrategy.Encode(text)); } else if (engine.IsInsideVerbatimString) { int idx = text.IndexOf('"'); if (idx > 0) { var o = offset; while (o < sourceText.Length) { char ch = sourceText [o]; engine.Push(ch); o++; if (!engine.IsInsideVerbatimString) { return(TextPasteUtils.VerbatimStringStrategy.Encode(text)); } } return(TextPasteUtils.VerbatimStringStrategy.Encode(text.Substring(0, idx)) + text.Substring(idx)); } return(TextPasteUtils.VerbatimStringStrategy.Encode(text)); } // on the fly formatting is done in post formatting, if turned off just correct indenting. if (!InUnitTestMode && DefaultSourceEditorOptions.Instance.OnTheFlyFormatting) { return(text); } var line = sourceText.Lines.GetLineFromPosition(offset); var pasteAtLineStart = line.Start == offset; var indentedText = StringBuilderCache.Allocate(); var curLine = StringBuilderCache.Allocate(); var clonedEngine = engine.Clone(); bool isNewLine = false, gotNewLine = false; for (int i = 0; i < text.Length; i++) { var ch = text [i]; if (clonedEngine.IsInsideVerbatimString || clonedEngine.IsInsideMultiLineComment || clonedEngine.IsInsidePreprocessorComment) { clonedEngine.Push(ch); curLine.Append(ch); continue; } var delimiterLength = NewLine.GetDelimiterLength(ch, i + 1 < text.Length ? text [i + 1] : ' '); if (delimiterLength > 0) { isNewLine = true; if (gotNewLine || pasteAtLineStart) { if (curLine.Length > 0 /*|| formattingOptions.EmptyLineFormatting == EmptyLineFormatting.Indent*/) { indentedText.Append(clonedEngine.ThisLineIndent); } } indentedText.Append(curLine); var newLine = options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); indentedText.Append(newLine); curLine.Length = 0; gotNewLine = true; i += delimiterLength - 1; // textEditorOptions.EolMarker[0] is the newLineChar used by the indentation engine. clonedEngine.Push(newLine [0]); } else { if (isNewLine) { if (ch == '\t' || ch == ' ') { clonedEngine.Push(ch); continue; } isNewLine = false; } curLine.Append(ch); clonedEngine.Push(ch); } if (clonedEngine.IsInsideVerbatimString || clonedEngine.IsInsideMultiLineComment && !(clonedEngine.LineBeganInsideVerbatimString || clonedEngine.LineBeganInsideMultiLineComment)) { if (gotNewLine) { if (curLine.Length > 0 /*|| formattingOptions.EmptyLineFormatting == EmptyLineFormatting.Indent*/) { indentedText.Append(clonedEngine.ThisLineIndent); } } pasteAtLineStart = false; indentedText.Append(curLine); curLine.Length = 0; gotNewLine = false; continue; } } if (gotNewLine && (!pasteAtLineStart || curLine.Length > 0)) { indentedText.Append(clonedEngine.ThisLineIndent); } if (curLine.Length > 0) { indentedText.Append(curLine); } StringBuilderCache.Free(curLine); return(StringBuilderCache.ReturnAndFree(indentedText)); }
void HandleTextPaste(int insertionOffset, string text, int insertedChars) { if (document.Editor.Options.IndentStyle == IndentStyle.None || document.Editor.Options.IndentStyle == IndentStyle.Auto) { return; } // Just correct the start line of the paste operation - the text is already indented. var curLine = Editor.GetLineByOffset(insertionOffset); var curLineOffset = curLine.Offset; stateTracker.Update(curLineOffset); if (!stateTracker.IsInsideOrdinaryCommentOrString) { // The Indent engine doesn't really handle pre processor directives very well. if (IsPreprocessorDirective(curLine)) { Editor.Replace(curLineOffset, curLine.Length, stateTracker.NextLineIndent + Editor.GetTextAt(curLine).TrimStart()); } else { int pos = curLineOffset; string curIndent = curLine.GetIndentation(textEditorData.Document); int nlwsp = curIndent.Length; if (!stateTracker.LineBeganInsideMultiLineComment || (nlwsp < curLine.LengthIncludingDelimiter && textEditorData.Document.GetCharAt(curLineOffset + nlwsp) == '*')) { // Possibly replace the indent stateTracker.Update(curLineOffset + curLine.Length); string newIndent = stateTracker.ThisLineIndent; if (newIndent != curIndent) { if (CompletionWindowManager.IsVisible) { if (pos < CompletionWindowManager.CodeCompletionContext.TriggerOffset) { CompletionWindowManager.CodeCompletionContext.TriggerOffset -= nlwsp; } } textEditorData.Replace(pos, nlwsp, newIndent); textEditorData.Document.CommitLineUpdate(textEditorData.Caret.Line); } } } } textEditorData.FixVirtualIndentation(); }