tgcli/tgcli.Tests/MessagePaging.cs
2023-01-23 17:51:10 +01:00

60 lines
3 KiB
C#

namespace tgcli.Tests;
public class MessagePaging {
[Theory]
[InlineData(0)]
[InlineData(76)]
[InlineData(77)]
[InlineData(147)]
[InlineData(148)]
[InlineData(218)]
[InlineData(219)]
[InlineData(289)]
public void Test1(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.GetViewIntoMessageBuffer(testMessage, offset, testBufferWidth),
Util.GetViewIntoMessageBuffer(testMessage, offset, testBufferWidth));
}
private static class ReferenceMethods {
internal static (string messageBuffer, int relativeCursorPosition)
GetViewIntoMessageBuffer(string message, int absoluteCursorPosition, int bufferWidth) {
const int wraparoundOffsetPre = 2; // number of "untouchable" characters moving the cursor onto will cause a wrap on the right screen edge
const int wraparoundOffsetPost = 5; // number of "untouchable" characters moving the cursor onto will cause a wrap on the left screen edge
const int wraparoundOffsetPreW = wraparoundOffsetPre + 1; // offset + 1 (character on the edge), for easier calculations
const int wraparoundOffsetPostW = wraparoundOffsetPost + 1; // offset + 1 (character on the edge), for easier calculations
if (absoluteCursorPosition > message.Length)
throw new ArgumentOutOfRangeException();
if (message.Length < bufferWidth)
return (message, absoluteCursorPosition);
if (absoluteCursorPosition < bufferWidth - wraparoundOffsetPre - 1)
return (Util.TruncateString(message, bufferWidth, $"{Util.Ansi.Inverse}>{Util.Ansi.InverseOff}"), absoluteCursorPosition);
// 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 - wraparoundOffsetPreW - wraparoundOffsetPost)..];
var finalCursorPos = absoluteCursorPosition - bufferWidth + wraparoundOffsetPreW + wraparoundOffsetPostW;
// 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 - wraparoundOffsetPreW) {
finalMessage = finalMessage[(bufferWidth - wraparoundOffsetPreW - wraparoundOffsetPostW)..];
finalCursorPos = finalCursorPos - bufferWidth + wraparoundOffsetPreW + wraparoundOffsetPostW;
}
finalMessage = Util.TruncateString(finalMessage, bufferWidth - 1, $"{Util.Ansi.Inverse}>{Util.Ansi.InverseOff}");
return ($"{Util.Ansi.Inverse}<{Util.Ansi.InverseOff}" + finalMessage, finalCursorPos);
}
}
}