diff --git a/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutput.cs b/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutput.cs index 9d8d4187f..7e29c4270 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutput.cs +++ b/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutput.cs @@ -6,6 +6,7 @@ using Luthetus.TextEditor.RazorLib.Lexes.Models; using Luthetus.TextEditor.RazorLib.TextEditors.Displays; using Luthetus.TextEditor.RazorLib.TextEditors.Models; +using System.Collections.Generic; namespace Luthetus.Ide.RazorLib.Events.Models; @@ -24,6 +25,7 @@ public class OnOutput : ITextEditorTask private readonly TerminalCommandBoundary _terminalCommandBoundary; public OnOutput( + int outputOffset, string output, List outputTextSpanList, ResourceUri resourceUri, @@ -31,6 +33,7 @@ public OnOutput( TerminalCommandBoundary terminalCommandBoundary, Key viewModelKey) { + OutputOffset = outputOffset; Output = output; _outputTextSpanList = outputTextSpanList; ResourceUri = resourceUri; @@ -45,6 +48,7 @@ public OnOutput( public Key QueueKey { get; } = ContinuousBackgroundTaskWorker.GetQueueKey(); public string Name { get; } = nameof(OnOutput); public Task? WorkProgress { get; } + public int OutputOffset { get; } public string Output { get; } public ResourceUri ResourceUri { get; } public ITextEditorService TextEditorService { get; } @@ -101,25 +105,33 @@ await editContext.TextEditorService.ModelApi.ApplyDecorationRangeFactory( { if (oldEvent is OnOutput oldEventOnOutput) { - var outputList = new List + var localOutputList = new List { oldEventOnOutput.Output, Output }; + var localOutputTextSpanAndOffsetTupleList = new List<(int OutputOffset, List OutputTextSpan)> + { + (oldEventOnOutput.OutputOffset, oldEventOnOutput._outputTextSpanList), + (OutputOffset, _outputTextSpanList) + }; + return new OnOutputBatch( - outputList, - _outputTextSpanList, + oldEventOnOutput.OutputOffset, + localOutputList, + localOutputTextSpanAndOffsetTupleList, ResourceUri, TextEditorService, _terminalCommandBoundary, ViewModelKey); } - if (oldEvent is OnOutputBatch oldEventOnWheelBatch) + if (oldEvent is OnOutputBatch oldOnOutputBatch) { - oldEventOnWheelBatch.OutputList.Add(Output); - return oldEventOnWheelBatch; + oldOnOutputBatch.OutputList.Add(Output); + oldOnOutputBatch.OutputTextSpanAndOffsetTupleList.Add((OutputOffset, _outputTextSpanList)); + return oldOnOutputBatch; } return null; diff --git a/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutputBatch.cs b/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutputBatch.cs index 5fe1bbcbb..bc0aa201f 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutputBatch.cs +++ b/Source/Lib/Ide/Ide.RazorLib/Events/Models/OnOutputBatch.cs @@ -5,6 +5,7 @@ using Luthetus.TextEditor.RazorLib; using Luthetus.TextEditor.RazorLib.TextEditors.Displays; using Luthetus.TextEditor.RazorLib.TextEditors.Models; +using System; namespace Luthetus.Ide.RazorLib.Events.Models; @@ -19,28 +20,31 @@ public class OnOutputBatch : ITextEditorTask private readonly TerminalCommandBoundary _terminalCommandBoundary; public OnOutputBatch( + int batchOutputOffset, List outputList, - List outputTextSpanList, + List<(int OutputOffset, List OutputTextSpan)> outputTextSpanAndOffsetTupleList, ResourceUri resourceUri, ITextEditorService textEditorService, TerminalCommandBoundary terminalCommandBoundary, Key viewModelKey) { + BatchOutputOffset = batchOutputOffset; OutputList = outputList; - _outputTextSpanList = outputTextSpanList; + OutputTextSpanAndOffsetTupleList = outputTextSpanAndOffsetTupleList; ResourceUri = resourceUri; TextEditorService = textEditorService; _terminalCommandBoundary = terminalCommandBoundary; ViewModelKey = viewModelKey; } - private List _outputTextSpanList; public Key BackgroundTaskKey { get; } = Key.NewKey(); public Key QueueKey { get; } = ContinuousBackgroundTaskWorker.GetQueueKey(); public string Name { get; } = nameof(OnOutput); public Task? WorkProgress { get; } + public int BatchOutputOffset { get; } public List OutputList { get; } + public List<(int OutputOffset, List OutputTextSpanList)> OutputTextSpanAndOffsetTupleList { get; } public ResourceUri ResourceUri { get; } public ITextEditorService TextEditorService { get; } public Key ViewModelKey { get; } @@ -49,9 +53,21 @@ public OnOutputBatch( public Task InvokeWithEditContext(IEditContext editContext) { + // Flatten 'OutputTextSpanAndOffsetTupleList' + var outputTextSpanList = new List(); + foreach (var tuple in OutputTextSpanAndOffsetTupleList) + { + outputTextSpanList.AddRange(tuple.OutputTextSpanList.Select(x => x with + { + StartingIndexInclusive = x.StartingIndexInclusive + tuple.OutputOffset - BatchOutputOffset, + EndingIndexExclusive = x.EndingIndexExclusive + tuple.OutputOffset - BatchOutputOffset, + })); + } + var onOutput = new OnOutput( + BatchOutputOffset, string.Join(string.Empty, OutputList), - _outputTextSpanList, + outputTextSpanList, ResourceUri, TextEditorService, _terminalCommandBoundary, diff --git a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/Terminal.cs b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/Terminal.cs index 858d15c6f..e6c268cce 100644 --- a/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/Terminal.cs +++ b/Source/Lib/Ide/Ide.RazorLib/Terminals/Models/Terminal.cs @@ -148,6 +148,8 @@ public Task EnqueueCommandAsync(TerminalCommand terminalCommand) var terminalCommandBoundary = new TerminalCommandBoundary(); + var outputOffset = 0; + await command.Observe(_commandCancellationTokenSource.Token) .ForEachAsync(cmdEvent => { @@ -182,12 +184,15 @@ await command.Observe(_commandCancellationTokenSource.Token) outputTextSpanList = terminalCommand.OutputParser.ParseLine(output); _textEditorService.Post(new OnOutput( + outputOffset, output, outputTextSpanList, ResourceUri, _textEditorService, terminalCommandBoundary, TextEditorViewModelKey)); + + outputOffset += output.Length; } DispatchNewStateKey();