tgcli/tgcli.Tests/PagedMessageInput.cs
2023-01-23 18:20:07 +01:00

58 lines
3 KiB
C#

namespace tgcli.Tests;
public class PagedMessageInput {
[Theory]
[InlineData(0)]
[InlineData(76)]
[InlineData(77)]
[InlineData(147)]
[InlineData(148)]
[InlineData(218)]
[InlineData(219)]
[InlineData(289)]
public void TestGetPagedMessageInput(int offset) {
const string testMessage =
"this is a test string please ignore 1, this is a test string please ignore 2, this is a test string please ignore 3, this is a test string please ignore 4, this is a test string please ignore 5, this is a test string please ignore 6, this is a test string please ignore 7, this is a test str.";
const int testBufferWidth = 80;
Assert.Equal(ReferenceMethods.GetPagedMessageInputLine(testMessage, offset, testBufferWidth), Util.GetPagedMessageInputLine(testMessage, offset, testBufferWidth));
}
private static class ReferenceMethods {
internal static (string messageBuffer, int relCursorPos) GetPagedMessageInputLine(string message, int absCursorPos, int bufferWidth) {
const int wrapOffsetPre = 2; // number of "untouchable" characters moving the cursor onto will cause a wrap on the right screen edge
const int wrapOffsetPost = 5; // number of "untouchable" characters moving the cursor onto will cause a wrap on the left screen edge
const int wrapOffsetPreI = wrapOffsetPre + 1; // offset + 1 (character on the edge), for easier calculations
const int wrapOffsetPostI = wrapOffsetPost + 1; // offset + 1 (character on the edge), for easier calculations
if (absCursorPos > message.Length)
throw new ArgumentOutOfRangeException(nameof(absCursorPos), "Cursor position exceeds message length");
if (message.Length < bufferWidth)
return (message, absCursorPos);
if (absCursorPos < bufferWidth - wrapOffsetPre - 1)
return (Util.TruncateString(message, bufferWidth, $"{Util.Ansi.Inverse}>{Util.Ansi.InverseOff}"), absCursorPos);
// now we can be sure the message needs at least one wrap
// first wrap
// get rid of the content shown on the zeroth wrap, which is buf width minus wraparoundPreW (respects > character on screen edge)
var finalMessage = message[(bufferWidth - wrapOffsetPreI - wrapOffsetPost)..];
var finalCursorPos = absCursorPos - bufferWidth + wrapOffsetPreI + wrapOffsetPostI;
// successive wraps
// repeat above steps (but counting the new < character) until the string fits into the buffer
// it fits into the buffer when cursorPos >= bufferwidth minus wraparound (this time respecting > character absent on first wrap)
while (finalCursorPos >= bufferWidth - wrapOffsetPreI) {
finalMessage = finalMessage[(bufferWidth - wrapOffsetPreI - wrapOffsetPostI)..];
finalCursorPos = finalCursorPos - bufferWidth + wrapOffsetPreI + wrapOffsetPostI;
}
finalMessage = Util.TruncateString(finalMessage, bufferWidth - 1, $"{Util.Ansi.Inverse}>{Util.Ansi.InverseOff}");
return ($"{Util.Ansi.Inverse}<{Util.Ansi.InverseOff}" + finalMessage, finalCursorPos);
}
}
}