[MethodImpl(MethodImplOptions.NoInlining)] // Avoid loading InteractiveWindow unless necessary private void PasteInteractiveFormat(ITextView textView) { var editorOperations = _editorOperationsFactoryService.GetEditorOperations(textView); var data = RoslynClipboard.GetDataObject(); Debug.Assert(data != null); bool dataHasLineCutCopyTag = false; bool dataHasBoxCutCopyTag = false; dataHasLineCutCopyTag = data.GetDataPresent(ClipboardLineBasedCutCopyTag); dataHasBoxCutCopyTag = data.GetDataPresent(BoxSelectionCutCopyTag); Debug.Assert(!(dataHasLineCutCopyTag && dataHasBoxCutCopyTag)); string text; try { text = InteractiveClipboardFormat.Deserialize(RoslynClipboard.GetData(InteractiveClipboardFormat.Tag)); } catch (InvalidDataException) { text = "<bad clipboard data>"; } using (var transaction = _textUndoHistoryRegistry.GetHistory(textView.TextBuffer).CreateTransaction(EditorFeaturesResources.Paste)) { editorOperations.AddBeforeTextBufferChangePrimitive(); if (dataHasLineCutCopyTag && textView.Selection.IsEmpty) { editorOperations.MoveToStartOfLine(extendSelection: false); editorOperations.InsertText(text); } else if (dataHasBoxCutCopyTag) { // If the caret is on a blank line, treat this like a normal stream insertion if (textView.Selection.IsEmpty && !HasNonWhiteSpaceCharacter(textView.Caret.Position.BufferPosition.GetContainingLine())) { // trim the last newline before paste var trimmed = text.Remove(text.LastIndexOf(textView.Options.GetNewLineCharacter())); editorOperations.InsertText(trimmed); } else { VirtualSnapshotPoint unusedStart, unusedEnd; editorOperations.InsertTextAsBox(text, out unusedStart, out unusedEnd); } } else { editorOperations.InsertText(text); } editorOperations.AddAfterTextBufferChangePrimitive(); transaction.Complete(); } }
public void Deserialize_Errors() { Assert.Throws <ArgumentNullException>(() => InteractiveClipboardFormat.Deserialize(null)); Assert.Throws <InvalidDataException>(() => InteractiveClipboardFormat.Deserialize(1)); Assert.Throws <InvalidDataException>(() => InteractiveClipboardFormat.Deserialize("foo")); Assert.Throws <InvalidDataException>(() => InteractiveClipboardFormat.Deserialize(@" [ {""content"":""A"",""kind"":1}, {""content"":""B"",""kind"":1000000000000000000000}, {""content"":""C"",""kind"":1}, ]")); Assert.Throws <InvalidDataException>(() => InteractiveClipboardFormat.Deserialize(@" [ {""content"":""A"",""kind"":1}, {""content"":""B"",""kind"":""x""}, {""content"":""C"",""kind"":1}, ]")); }
public void Deserialize() { var serialized = BufferBlock.Serialize(new[] { new BufferBlock(ReplSpanKind.Input, "I"), new BufferBlock(ReplSpanKind.Output, "O"), new BufferBlock(ReplSpanKind.LineBreak, "LB"), new BufferBlock(ReplSpanKind.Prompt, "P"), new BufferBlock(ReplSpanKind.StandardInput, "SI"), }); Assert.Equal("IOLBSI", InteractiveClipboardFormat.Deserialize(serialized)); // missing kind interpreted as Prompt, which is ignored: Assert.Equal("AC", InteractiveClipboardFormat.Deserialize(@" [ {""content"":""A"",""kind"":1}, {""content"":""B"",""x"":1}, {""content"":""C"",""kind"":1}, ]")); // invalid kind ignored: Assert.Equal("AC", InteractiveClipboardFormat.Deserialize(@" [ {""content"":""A"",""kind"":1}, {""content"":""B"",""kind"":-1}, {""content"":""C"",""kind"":1}, ]")); // invalid kind ignored: Assert.Equal("AC", InteractiveClipboardFormat.Deserialize(@" [ {""content"":""A"",""kind"":1}, {""content"":""B"",""kind"":-1}, {""content"":""C"",""kind"":1}, ]")); }