fix missing carriage returns on unix
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Buffers;
|
||||||
using GDExtensionBindgen;
|
using GDExtensionBindgen;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
@@ -20,9 +21,21 @@ public partial class SharpIdeTerminal : Control
|
|||||||
|
|
||||||
public async Task WriteAsync(byte[] text)
|
public async Task WriteAsync(byte[] text)
|
||||||
{
|
{
|
||||||
await this.InvokeAsync(() => _terminal.Write(text));
|
var (processedArray, length, wasRented) = ProcessLineEndings(text);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await this.InvokeAsync(() => _terminal.Write(processedArray.AsSpan(0, length)));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (wasRented)
|
||||||
|
{
|
||||||
|
ArrayPool<byte>.Shared.Return(processedArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_previousArrayEndedInCr = text.Length > 0 && text[^1] == (byte)'\r';
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequiresGodotUiThread]
|
[RequiresGodotUiThread]
|
||||||
public void ClearTerminal()
|
public void ClearTerminal()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using System.Buffers;
|
||||||
|
|
||||||
|
namespace SharpIDE.Godot.Features.TerminalBase;
|
||||||
|
|
||||||
|
public partial class SharpIdeTerminal
|
||||||
|
{
|
||||||
|
private bool _previousArrayEndedInCr = false;
|
||||||
|
|
||||||
|
// Unfortunately, although the terminal emulator handles escape sequences etc, it does not handle interpreting \n as \r\n - that is handled by the PTY, which we currently don't use
|
||||||
|
// So we need to replace lone \n with \r\n ourselves
|
||||||
|
// TODO: Probably run processes with PTY instead, so that this is not needed, and so we can capture user input and Ctrl+C etc
|
||||||
|
// 🤖
|
||||||
|
private (byte[] array, int length, bool wasRented) ProcessLineEndings(byte[] input)
|
||||||
|
{
|
||||||
|
if (input.Length == 0) return (input, 0, false);
|
||||||
|
|
||||||
|
// Count how many \n need to be replaced (those not preceded by \r)
|
||||||
|
var replacementCount = 0;
|
||||||
|
var previousWasCr = _previousArrayEndedInCr;
|
||||||
|
|
||||||
|
for (var i = 0; i < input.Length; i++)
|
||||||
|
{
|
||||||
|
if (input[i] == (byte)'\n')
|
||||||
|
{
|
||||||
|
// Check if it's preceded by \r
|
||||||
|
var precededByCr = (i > 0 && input[i - 1] == (byte)'\r') || (i == 0 && previousWasCr);
|
||||||
|
if (!precededByCr)
|
||||||
|
{
|
||||||
|
replacementCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousWasCr = input[i] == (byte)'\r';
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no replacements needed, return original array
|
||||||
|
if (replacementCount == 0) return (input, input.Length, false);
|
||||||
|
|
||||||
|
// Rent array from pool with space for additional \r characters
|
||||||
|
var requiredSize = input.Length + replacementCount;
|
||||||
|
var result = ArrayPool<byte>.Shared.Rent(requiredSize);
|
||||||
|
var writeIndex = 0;
|
||||||
|
previousWasCr = _previousArrayEndedInCr;
|
||||||
|
|
||||||
|
for (var i = 0; i < input.Length; i++)
|
||||||
|
{
|
||||||
|
if (input[i] == (byte)'\n')
|
||||||
|
{
|
||||||
|
// Check if it's preceded by \r
|
||||||
|
var precededByCr = (i > 0 && input[i - 1] == (byte)'\r') || (i == 0 && previousWasCr);
|
||||||
|
if (!precededByCr)
|
||||||
|
{
|
||||||
|
result[writeIndex++] = (byte)'\r';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result[writeIndex++] = input[i];
|
||||||
|
previousWasCr = input[i] == (byte)'\r';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (result, writeIndex, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user