diff --git a/src/InteractiveWindow/Editor/InteractiveWindow.cs b/src/InteractiveWindow/Editor/InteractiveWindow.cs
index 15837cb5d41203adaeaee2b52a3e4b184bdf838a..c17f2da83099936b9bc81b6b91f78e3128b7207d 100644
--- a/src/InteractiveWindow/Editor/InteractiveWindow.cs
+++ b/src/InteractiveWindow/Editor/InteractiveWindow.cs
@@ -34,6 +34,34 @@ namespace Microsoft.VisualStudio.InteractiveWindow
///
internal partial class InteractiveWindow : IInteractiveWindow, IInteractiveWindowOperations2
{
+ private enum ReplSpanKind
+ {
+ ///
+ /// Primary, secondary, or standard input prompt.
+ ///
+ Prompt,
+
+ ///
+ /// Line break inserted at end of output.
+ ///
+ LineBreak,
+
+ ///
+ /// The span represents output from the program (standard output).
+ ///
+ Output,
+
+ ///
+ /// The span represents code inputted after a prompt or secondary prompt.
+ ///
+ Language,
+
+ ///
+ /// The span represents the input for a standard input (non code input).
+ ///
+ StandardInput,
+ }
+
private bool _adornmentToMinimize;
private readonly IWpfTextView _textView;
@@ -61,10 +89,7 @@ internal partial class InteractiveWindow : IInteractiveWindow, IInteractiveWindo
private readonly ITextBuffer _outputBuffer;
private readonly IProjectionBuffer _projectionBuffer;
private readonly ITextBuffer _standardInputBuffer;
- private readonly ITextBuffer _promptBuffer;
- private readonly ITextBuffer _secondaryPromptBuffer;
- private readonly ITextBuffer _standardInputPromptBuffer;
- private readonly ITextBuffer _outputLineBreakBuffer;
+ private readonly IContentType _inertType;
private ITextBuffer _currentLanguageBuffer;
private string _historySearch;
@@ -463,12 +488,13 @@ void IInteractiveWindowOperations.SelectAll()
// Grab the span following the prompt (either language or standard input).
var projectionSpan = sourceSpans[promptIndex + 1];
var inputSnapshot = projectionSpan.Snapshot;
+ var kind = GetSpanKind(projectionSpan);
- Debug.Assert(GetSpanKind(inputSnapshot) == ReplSpanKind.Language || GetSpanKind(inputSnapshot) == ReplSpanKind.StandardInput);
+ Debug.Assert(kind == ReplSpanKind.Language || kind == ReplSpanKind.StandardInput);
// Language input block is a projection of the entire snapshot;
// std input block is a projection of a single span:
- SnapshotPoint inputBufferEnd = GetSpanKind(inputSnapshot) == ReplSpanKind.Language ?
+ SnapshotPoint inputBufferEnd = (kind == ReplSpanKind.Language) ?
new SnapshotPoint(inputSnapshot, inputSnapshot.Length) :
projectionSpan.End;
@@ -504,7 +530,7 @@ void IInteractiveWindowOperations.SelectAll()
int nextPromptIndex = -1;
for (int i = promptIndex + 1; i < sourceSpans.Count; i++)
{
- if (IsPrompt(sourceSpans[i].Snapshot))
+ if (IsPrompt(sourceSpans[i]))
{
nextPromptIndex = i;
break;
@@ -521,7 +547,7 @@ void IInteractiveWindowOperations.SelectAll()
}
var lastSpanBeforeNextPrompt = sourceSpans[nextPromptIndex - 1];
- Debug.Assert(GetSpanKind(lastSpanBeforeNextPrompt.Snapshot) == ReplSpanKind.Output);
+ Debug.Assert(GetSpanKind(lastSpanBeforeNextPrompt) == ReplSpanKind.Output);
// select all text in between the language buffer and the next prompt:
return new SnapshotSpan(
@@ -558,7 +584,7 @@ private void IndentCurrentLine(SnapshotPoint caretPosition)
var sourceSpans = GetSourceSpans(caretPosition.Snapshot);
var promptIndex = GetPromptIndexForPoint(sourceSpans, caretPosition);
var promptSpan = sourceSpans[promptIndex];
- Debug.Assert(IsPrompt(promptSpan.Snapshot));
+ Debug.Assert(IsPrompt(promptSpan));
int promptLength = promptSpan.Length;
Debug.Assert(promptLength == 2 || promptLength == 0); // Not required, just expected.
var adjustedIndentationValue = indentation.GetValueOrDefault() - promptLength;
@@ -790,19 +816,23 @@ private StringBuilder GetTextWithoutPrompts(StringBuilder builder, SnapshotSpan
{
continue;
}
- var sourceSnapshot = sourceSpan.Snapshot;
- var mappedSpans = _textView.BufferGraph.MapDownToBuffer(span, SpanTrackingMode.EdgeExclusive, sourceSnapshot.TextBuffer);
- if (mappedSpans.Count == 0)
- {
- break;
- }
- if (!IsPrompt(sourceSnapshot))
+ if (!IsPrompt(sourceSpan))
{
+ var sourceSnapshot = sourceSpan.Snapshot;
+ var mappedSpans = _textView.BufferGraph.MapDownToBuffer(span, SpanTrackingMode.EdgeExclusive, sourceSnapshot.TextBuffer);
+ bool added = false;
foreach (var mappedSpan in mappedSpans)
{
var intersection = sourceSpan.Span.Intersection(mappedSpan);
- Debug.Assert(intersection.HasValue);
- builder.Append(sourceSnapshot.GetText(intersection.Value));
+ if (intersection.HasValue)
+ {
+ builder.Append(sourceSnapshot.GetText(intersection.Value));
+ added = true;
+ }
+ }
+ if (!added)
+ {
+ break;
}
}
}
@@ -1288,36 +1318,13 @@ private void SetActiveCodeToHistory(History.Entry entry)
private void ClearInput()
{
- var sourceSpans = _projectionBuffer.CurrentSnapshot.GetSourceSpans();
- Debug.Assert(sourceSpans.Count > 0);
-
- // Finds the last primary prompt (standard input or code input).
- // Removes all spans following the primary prompt from the projection buffer.
- int i = sourceSpans.Count - 1;
- while (i >= 0)
+ if (_stdInputStart != null)
{
- var sourceSnapshot = sourceSpans[i].Snapshot;
- if (GetSpanKind(sourceSnapshot) == ReplSpanKind.Prompt || GetSpanKind(sourceSnapshot) == ReplSpanKind.StandardInputPrompt)
- {
- Debug.Assert(i != sourceSpans.Count - 1);
- break;
- }
-
- i--;
+ _standardInputBuffer.Delete(Span.FromBounds(_stdInputStart.Value, _standardInputBuffer.CurrentSnapshot.Length));
}
-
- if (i >= 0)
+ else
{
- var sourceSnapshot = sourceSpans[i].Snapshot;
- if (GetSpanKind(sourceSnapshot) != ReplSpanKind.StandardInputPrompt)
- {
- _currentLanguageBuffer.Delete(new Span(0, _currentLanguageBuffer.CurrentSnapshot.Length));
- }
- else
- {
- Debug.Assert(_stdInputStart != null);
- _standardInputBuffer.Delete(Span.FromBounds(_stdInputStart.Value, _standardInputBuffer.CurrentSnapshot.Length));
- }
+ _currentLanguageBuffer.Delete(new Span(0, _currentLanguageBuffer.CurrentSnapshot.Length));
}
}
@@ -1340,7 +1347,7 @@ TextReader IInteractiveWindow.ReadStandardInput()
{
var snapshot = _projectionBuffer.CurrentSnapshot;
var spanCount = snapshot.SpanCount;
- if (spanCount > 0 && IsLanguage(snapshot.GetSourceSpan(spanCount - 1).Snapshot))
+ if (spanCount > 0 && GetSpanKind(snapshot.GetSourceSpan(spanCount - 1)) == ReplSpanKind.Language)
{
// we need to remove our input prompt.
uiOnly.RemoveLastInputPrompt();
@@ -1420,9 +1427,9 @@ private void SubmitStandardInput()
_inputEvent.Set();
}
- #endregion
+#endregion
- #region Output
+#region Output
Span IInteractiveWindow.Write(string text)
{
@@ -1475,9 +1482,9 @@ private void OnAdornmentLoaded(object source, EventArgs e)
Caret.EnsureVisible();
}
- #endregion
+#endregion
- #region Execution
+#region Execution
private bool CanExecuteActiveCode()
{
@@ -1503,35 +1510,23 @@ private bool CanExecuteActiveCode()
return _evaluator.CanExecuteCode(input);
}
- #endregion
+#endregion
- #region Buffers, Spans and Prompts
- private ITrackingSpan CreateStandardInputPrompt()
+#region Buffers, Spans and Prompts
+ private object CreateStandardInputPrompt()
{
- return CreateTrackingSpan(_standardInputPromptBuffer, string.Empty);
+ return string.Empty;
}
- private ITrackingSpan CreatePrimaryPrompt()
+ private object CreatePrimaryPrompt()
{
- return CreateTrackingSpan(_promptBuffer, _evaluator.GetPrompt());
+ return _evaluator.GetPrompt();
}
- private ITrackingSpan CreateSecondaryPrompt()
+ private object CreateSecondaryPrompt()
{
// TODO (crwilcox) format prompt used to get a blank here but now gets "> " from get prompt.
- return CreateTrackingSpan(_secondaryPromptBuffer, _evaluator.GetPrompt());
- }
-
- private static ITrackingSpan CreateTrackingSpan(ITextBuffer buffer, string textToAppend)
- {
- using (var edit = buffer.CreateEdit())
- {
- var snapshot = edit.Snapshot;
- int offset = snapshot.Length;
- edit.Insert(offset, textToAppend);
- snapshot = edit.Apply();
- return new CustomTrackingSpan(snapshot, new Span(offset, snapshot.Length - offset), PointTrackingMode.Negative, PointTrackingMode.Negative);
- }
+ return _evaluator.GetPrompt();
}
///
@@ -1545,15 +1540,15 @@ private void MeasurePrompts(int startLine, int endLine, out int minPromptLength,
var sourceSpans = projectionSnapshot.GetSourceSpans();
var promptSpanIndex = GetProjectionSpanIndexFromEditableBufferPosition(projectionSnapshot, sourceSpans.Count, startLine) - 1;
var promptSpan = sourceSpans[promptSpanIndex];
- Debug.Assert(IsPrompt(promptSpan.Snapshot));
+ Debug.Assert(IsPrompt(promptSpan));
minPromptLength = maxPromptLength = promptSpan.Length;
}
- private ReplSpanKind GetSpanKind(ITextSnapshot snapshot)
+ private ReplSpanKind GetSpanKind(SnapshotSpan span)
{
- var textBuffer = snapshot.TextBuffer;
- if ((textBuffer == _outputBuffer) || (textBuffer == _outputLineBreakBuffer))
+ var textBuffer = span.Snapshot.TextBuffer;
+ if (textBuffer == _outputBuffer)
{
return ReplSpanKind.Output;
}
@@ -1561,30 +1556,18 @@ private ReplSpanKind GetSpanKind(ITextSnapshot snapshot)
{
return ReplSpanKind.StandardInput;
}
- if (textBuffer == _promptBuffer)
- {
- return ReplSpanKind.Prompt;
- }
- if (textBuffer == _secondaryPromptBuffer)
- {
- return ReplSpanKind.SecondaryPrompt;
- }
- if (textBuffer == _standardInputPromptBuffer)
+ if (textBuffer.ContentType == _inertType)
{
- return ReplSpanKind.StandardInputPrompt;
+ return (span.Length == _lineBreakString.Length) && string.Equals(span.GetText(), _lineBreakString) ?
+ ReplSpanKind.LineBreak :
+ ReplSpanKind.Prompt;
}
return ReplSpanKind.Language;
}
- private bool IsPrompt(ITextSnapshot snapshot)
- {
- var kind = GetSpanKind(snapshot);
- return (kind == ReplSpanKind.Prompt) || (kind == ReplSpanKind.SecondaryPrompt) || (kind == ReplSpanKind.StandardInputPrompt);
- }
-
- private bool IsLanguage(ITextSnapshot snapshot)
+ private bool IsPrompt(SnapshotSpan span)
{
- return GetSpanKind(snapshot) == ReplSpanKind.Language;
+ return GetSpanKind(span) == ReplSpanKind.Prompt;
}
private static ReadOnlyCollection GetSourceSpans(ITextSnapshot snapshot)
@@ -1600,7 +1583,7 @@ private int GetPromptIndexForPoint(ReadOnlyCollection sourceSpans,
index--;
}
// Find the nearest preceding prompt.
- while (!IsPrompt(sourceSpans[index].Snapshot))
+ while (!IsPrompt(sourceSpans[index]))
{
index--;
}
@@ -1708,9 +1691,9 @@ private struct SpanRangeEdit
{
public readonly int Start;
public readonly int End;
- public readonly ITrackingSpan[] Replacement;
+ public readonly object[] Replacement;
- public SpanRangeEdit(int start, int count, ITrackingSpan[] replacement)
+ public SpanRangeEdit(int start, int count, object[] replacement)
{
Start = start;
End = start + count;
@@ -1818,7 +1801,7 @@ private void ProjectionBufferChanged(object sender, TextContentChangedEventArgs
int i = 0;
int lineBreakCount = newSubjectEndLineNumber - newSubjectStartLine.LineNumber;
- var newSpans = new ITrackingSpan[lineBreakCount * SpansPerLineOfInput + 1];
+ var newSpans = new object[lineBreakCount * SpansPerLineOfInput + 1];
var subjectLine = newSubjectStartLine;
while (true)
@@ -1868,7 +1851,7 @@ private int GetProjectionSpanIndexFromEditableBufferPosition(IProjectionSnapshot
// and ending at the end of the projection buffer, each language buffer projection is on a separate line:
// [prompt)[language)...[prompt)[language)
int result = projectionSpansCount - (surfaceSnapshot.LineCount - surfaceLineNumber) * SpansPerLineOfInput + 1;
- Debug.Assert(GetSpanKind(surfaceSnapshot.GetSourceSpan(result).Snapshot) == ReplSpanKind.Language);
+ Debug.Assert(GetSpanKind(surfaceSnapshot.GetSourceSpan(result)) == ReplSpanKind.Language);
return result;
}
@@ -1911,9 +1894,14 @@ private void ReplaceProjectionSpans(ReadOnlyCollection oldProjecti
_projectionBuffer.ReplaceSpans(start, end - start, replacement, EditOptions.None, s_suppressPromptInjectionTag);
}
- private static ITrackingSpan CreateTrackingSpan(SnapshotSpan snapshotSpan)
+ private object CreateTrackingSpan(SnapshotSpan snapshotSpan)
{
- return new CustomTrackingSpan(snapshotSpan.Snapshot, snapshotSpan.Span, PointTrackingMode.Negative, PointTrackingMode.Negative);
+ var snapshot = snapshotSpan.Snapshot;
+ if (snapshot.ContentType == _inertType)
+ {
+ return snapshotSpan.GetText();
+ }
+ return new CustomTrackingSpan(snapshot, snapshotSpan.Span, PointTrackingMode.Negative, PointTrackingMode.Negative);
}
private ITrackingSpan CreateLanguageSpanForLine(ITextSnapshotLine languageLine)
@@ -1936,7 +1924,7 @@ private void AppendLineNoPromptInjection(ITextBuffer buffer)
}
}
- private void AppendProjectionSpans(ITrackingSpan span1, ITrackingSpan span2)
+ private void AppendProjectionSpans(object span1, object span2)
{
int index = _projectionBuffer.CurrentSnapshot.SpanCount;
_projectionBuffer.ReplaceSpans(index, 0, new[] { span1, span2 }, EditOptions.None, editTag: s_suppressPromptInjectionTag);
diff --git a/src/InteractiveWindow/Editor/InteractiveWindow.csproj b/src/InteractiveWindow/Editor/InteractiveWindow.csproj
index 3da91df0753fb7c6182bacf58b8b9f424b674233..6e743acffa89dc3075342e7a2db6d028be1b3842 100644
--- a/src/InteractiveWindow/Editor/InteractiveWindow.csproj
+++ b/src/InteractiveWindow/Editor/InteractiveWindow.csproj
@@ -108,7 +108,6 @@
-
diff --git a/src/InteractiveWindow/Editor/InteractiveWindow_UIThread.cs b/src/InteractiveWindow/Editor/InteractiveWindow_UIThread.cs
index c44f8db4c4c6dcb3d2fa5855692a3b5ed36cea0f..9a1c3402a05fc23e764f30b504549537575f5ec8 100644
--- a/src/InteractiveWindow/Editor/InteractiveWindow_UIThread.cs
+++ b/src/InteractiveWindow/Editor/InteractiveWindow_UIThread.cs
@@ -60,10 +60,7 @@ internal partial class InteractiveWindow
_outputBuffer = bufferFactory.CreateTextBuffer(replOutputContentType);
_standardInputBuffer = bufferFactory.CreateTextBuffer();
- _promptBuffer = bufferFactory.CreateTextBuffer();
- _secondaryPromptBuffer = bufferFactory.CreateTextBuffer();
- _standardInputPromptBuffer = bufferFactory.CreateTextBuffer();
- _outputLineBreakBuffer = bufferFactory.CreateTextBuffer();
+ _inertType = bufferFactory.InertContentType;
var projBuffer = projectionBufferFactory.CreateProjectionBuffer(
new EditResolver(this),
@@ -217,7 +214,7 @@ public Task ResetAsync(bool initialize)
{
var snapshot = _window._projectionBuffer.CurrentSnapshot;
var spanCount = snapshot.SpanCount;
- Debug.Assert(_window.IsLanguage(snapshot.GetSourceSpan(spanCount - 1).Snapshot));
+ Debug.Assert(_window.GetSpanKind(snapshot.GetSourceSpan(spanCount - 1)) == ReplSpanKind.Language);
StoreUncommittedInput();
RemoveProjectionSpans(spanCount - 2, 2);
_window._currentLanguageBuffer = null;
@@ -434,8 +431,8 @@ private void AppendInput(string text)
var snapshot = _window._projectionBuffer.CurrentSnapshot;
var spanCount = snapshot.SpanCount;
var inputSpan = snapshot.GetSourceSpan(spanCount - 1);
- Debug.Assert(_window.GetSpanKind(inputSpan.Snapshot) == ReplSpanKind.Language ||
- _window.GetSpanKind(inputSpan.Snapshot) == ReplSpanKind.StandardInput);
+ Debug.Assert(_window.GetSpanKind(inputSpan) == ReplSpanKind.Language ||
+ _window.GetSpanKind(inputSpan) == ReplSpanKind.StandardInput);
var buffer = inputSpan.Snapshot.TextBuffer;
var span = inputSpan.Span;
@@ -618,10 +615,9 @@ public void NewOutputBuffer()
{
// Stop growing the current output projection span.
var sourceSpan = _window._projectionBuffer.CurrentSnapshot.GetSourceSpan(_currentOutputProjectionSpan);
- var sourceSnapshot = sourceSpan.Snapshot;
- Debug.Assert(_window.GetSpanKind(sourceSnapshot) == ReplSpanKind.Output);
+ Debug.Assert(_window.GetSpanKind(sourceSpan) == ReplSpanKind.Output);
var nonGrowingSpan = new CustomTrackingSpan(
- sourceSnapshot,
+ sourceSpan.Snapshot,
sourceSpan.Span,
PointTrackingMode.Negative,
PointTrackingMode.Negative);
@@ -650,7 +646,7 @@ private int AppendProjectionSpan(ITrackingSpan span)
return index;
}
- private void InsertProjectionSpan(int index, ITrackingSpan span)
+ private void InsertProjectionSpan(int index, object span)
{
_window._projectionBuffer.ReplaceSpans(index, 0, new[] { span }, EditOptions.None, editTag: s_suppressPromptInjectionTag);
}
@@ -674,12 +670,11 @@ internal void AppendOutput(IEnumerable output, int outputLength)
{
Debug.Assert(output.Any());
- // we maintain this invariant so that projections don't split "\r\n" in half
- // (the editor isn't happy about it and our line counting also gets simpler):
+ // we maintain this invariant so that projections don't split "\r\n" in half:
Debug.Assert(!_window._outputBuffer.CurrentSnapshot.EndsWith('\r'));
var projectionSpans = _window._projectionBuffer.CurrentSnapshot.GetSourceSpans();
- Debug.Assert(_window.GetSpanKind(projectionSpans[_currentOutputProjectionSpan].Snapshot) == ReplSpanKind.Output);
+ Debug.Assert(_window.GetSpanKind(projectionSpans[_currentOutputProjectionSpan]) == ReplSpanKind.Output);
int lineBreakProjectionSpanIndex = _currentOutputProjectionSpan + 1;
@@ -688,26 +683,25 @@ internal void AppendOutput(IEnumerable output, int outputLength)
if (lineBreakProjectionSpanIndex < projectionSpans.Count)
{
var oldSpan = projectionSpans[lineBreakProjectionSpanIndex];
- hasLineBreakProjection = _window.GetSpanKind(oldSpan.Snapshot) == ReplSpanKind.Output && string.Equals(oldSpan.GetText(), _window._lineBreakString);
+ hasLineBreakProjection = _window.GetSpanKind(oldSpan) == ReplSpanKind.LineBreak;
}
Debug.Assert(output.Last().Last() != '\r');
bool endsWithLineBreak = output.Last().Last() == '\n';
- bool insertLineBreak = !endsWithLineBreak && !hasLineBreakProjection;
- bool removeLineBreak = endsWithLineBreak && hasLineBreakProjection;
-
// insert text to the subject buffer.
int oldBufferLength = _window._outputBuffer.CurrentSnapshot.Length;
InsertOutput(output, oldBufferLength);
- if (removeLineBreak)
+ if (endsWithLineBreak && hasLineBreakProjection)
{
+ // Remove line break.
RemoveProjectionSpans(lineBreakProjectionSpanIndex, 1);
}
- else if (insertLineBreak)
+ else if (!endsWithLineBreak && !hasLineBreakProjection)
{
- InsertProjectionSpan(lineBreakProjectionSpanIndex, CreateTrackingSpan(_window._outputLineBreakBuffer, _window._lineBreakString));
+ // Insert line break.
+ InsertProjectionSpan(lineBreakProjectionSpanIndex, _window._lineBreakString);
}
// caret didn't move since last time we moved it to track output:
@@ -826,13 +820,14 @@ private ITextBuffer GetLanguageBuffer(SnapshotPoint point)
// Grab the span following the prompt (either language or standard input).
var projectionSpan = sourceSpans[promptIndex + 1];
- var inputSnapshot = projectionSpan.Snapshot;
- if (_window.GetSpanKind(inputSnapshot) != ReplSpanKind.Language)
+ var kind = _window.GetSpanKind(projectionSpan);
+ if (kind != ReplSpanKind.Language)
{
- Debug.Assert(_window.GetSpanKind(inputSnapshot) == ReplSpanKind.StandardInput);
+ Debug.Assert(kind == ReplSpanKind.StandardInput);
return null;
}
+ var inputSnapshot = projectionSpan.Snapshot;
var inputBuffer = inputSnapshot.TextBuffer;
var projectedSpans = _window._textView.BufferGraph.MapUpToBuffer(
@@ -914,7 +909,7 @@ public int IndexOfLastStandardInputSpan(ReadOnlyCollection sourceS
{
for (int i = sourceSpans.Count - 1; i >= 0; i--)
{
- if (_window.GetSpanKind(sourceSpans[i].Snapshot) == ReplSpanKind.StandardInput)
+ if (_window.GetSpanKind(sourceSpans[i]) == ReplSpanKind.StandardInput)
{
return i;
}
@@ -927,7 +922,7 @@ public void RemoveLastInputPrompt()
{
var snapshot = _window._projectionBuffer.CurrentSnapshot;
var spanCount = snapshot.SpanCount;
- Debug.Assert(_window.IsPrompt(snapshot.GetSourceSpan(spanCount - SpansPerLineOfInput).Snapshot));
+ Debug.Assert(_window.IsPrompt(snapshot.GetSourceSpan(spanCount - SpansPerLineOfInput)));
// projection buffer update must be the last operation as it might trigger event that accesses prompt line mapping:
RemoveProjectionSpans(spanCount - SpansPerLineOfInput, SpansPerLineOfInput);
diff --git a/src/InteractiveWindow/Editor/ReplSpanKind.cs b/src/InteractiveWindow/Editor/ReplSpanKind.cs
deleted file mode 100644
index 4b5e15827c7e3ef22cb892b40986f33756f58618..0000000000000000000000000000000000000000
--- a/src/InteractiveWindow/Editor/ReplSpanKind.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-namespace Microsoft.VisualStudio.InteractiveWindow
-{
- internal enum ReplSpanKind
- {
- None,
-
- ///
- /// The span represents output from the program (standard output)
- ///
- Output,
-
- ///
- /// The span represents a prompt for input of code.
- ///
- Prompt,
-
- ///
- /// The span represents a secondary prompt for more code.
- ///
- SecondaryPrompt,
-
- ///
- /// The span represents code inputted after a prompt or secondary prompt.
- ///
- Language,
-
- ///
- /// The span represents the prompt for input for standard input (non code input)
- ///
- StandardInputPrompt,
-
- ///
- /// The span represents the input for a standard input (non code input)
- ///
- StandardInput,
- }
-}
diff --git a/src/InteractiveWindow/EditorTest/InteractiveWindowTests.cs b/src/InteractiveWindow/EditorTest/InteractiveWindowTests.cs
index 40ea7ab48b9ad41d21a9356841e4458579e7d0b0..9df3dd185c6749903f2e03a13631062edbb0c97f 100644
--- a/src/InteractiveWindow/EditorTest/InteractiveWindowTests.cs
+++ b/src/InteractiveWindow/EditorTest/InteractiveWindowTests.cs
@@ -573,8 +573,23 @@ public void ReformatBraces()
new TextChange(5, 1, " "),
new TextChange(7, 1, "\r\n"));
+ // Text from language buffer.
var actualText = snapshot.GetText();
Assert.Equal("{\r\n {\r\n }\r\n}", actualText);
+
+ // Text including prompts.
+ buffer = Window.TextView.TextBuffer;
+ snapshot = buffer.CurrentSnapshot;
+ actualText = snapshot.GetText();
+ Assert.Equal("> {\r\n> {\r\n> }\r\n> }", actualText);
+
+ // Prompts should be read-only.
+ var regions = buffer.GetReadOnlyExtents(new Span(0, snapshot.Length));
+ AssertEx.SetEqual(regions,
+ new Span(0, 2),
+ new Span(5, 2),
+ new Span(14, 2),
+ new Span(23, 2));
}
[Fact]
@@ -721,6 +736,25 @@ private void CopyNoSelectionAndVerify(int start, int end, string expectedText, s
}
}
+ [Fact]
+ public void CancelMultiLineInput()
+ {
+ ApplyChanges(
+ Window.CurrentLanguageBuffer,
+ new TextChange(0, 0, "{\r\n {\r\n }\r\n}"));
+
+ // Text including prompts.
+ var buffer = Window.TextView.TextBuffer;
+ var snapshot = buffer.CurrentSnapshot;
+ Assert.Equal("> {\r\n> {\r\n> }\r\n> }", snapshot.GetText());
+
+ Task.Run(() => Window.Operations.Cancel()).PumpingWait();
+
+ // Text after cancel.
+ snapshot = buffer.CurrentSnapshot;
+ Assert.Equal("> ", snapshot.GetText());
+ }
+
private void Submit(string submission, string output)
{
Task.Run(() => Window.SubmitAsync(new[] { submission })).PumpingWait();