1
0
Files
AnchorCli/InputProcessor.cs

126 lines
5.0 KiB
C#

using Spectre.Console;
namespace AnchorCli
{
internal class InputProcessor
{
private static void DisplayText(int left, string buffer, int index = -1, string placeholder = "", int viewportOffset = 0)
{
Console.CursorLeft = left;
if (buffer.Length == 0 && index == 0)
{
AnsiConsole.Markup($"[grey dim]{placeholder}{new string(' ', Console.WindowWidth - 1 - left - placeholder.Length)}[/]");
return;
}
var visibleWidth = Console.WindowWidth - left - 1;
var displayStart = Math.Min(viewportOffset, Math.Max(0, buffer.Length - 1));
var displayEnd = Math.Min(displayStart + visibleWidth, buffer.Length);
var displayBuffer = string.Concat(buffer.AsSpan(displayStart, displayEnd - displayStart), " ");
for (var i = 0; i < displayBuffer.Length; i++)
{
var actualIndex = displayStart + i;
if (index != -1 && actualIndex == index)
{
Console.ForegroundColor = ConsoleColor.Black;
Console.BackgroundColor = ConsoleColor.White;
}
Console.Write(displayBuffer[i]);
if (index != -1 && actualIndex == index)
Console.ResetColor();
}
// Fill remaining space with spaces
var remainingSpaces = visibleWidth - displayBuffer.Length;
if (remainingSpaces > 0)
Console.Write(new string(' ', remainingSpaces));
}
public static string ReadLine(string placeholder = "")
{
Console.CursorVisible = false;
var buffer = string.Empty;
var index = 0;
var viewportOffset = 0;
var left = Console.CursorLeft;
DisplayText(left, buffer, index, placeholder, viewportOffset);
while (true)
{
var inputKey = Console.ReadKey(intercept: true);
switch (inputKey)
{
case { Key: ConsoleKey.Enter } when buffer.Length > 0:
DisplayText(left, buffer);
Console.WriteLine();
return buffer;
case { Key: ConsoleKey.Backspace } when index > 0:
index--;
buffer = buffer.Remove(index, 1);
break;
case { Key: ConsoleKey.Delete } when index < buffer.Length:
buffer = buffer.Remove(index, 1);
break;
case { Key: ConsoleKey.LeftArrow, Modifiers: ConsoleModifiers.Control }:
while (index > 0 && buffer[index - 1] == ' ')
index--;
while (index > 0 && buffer[index - 1] != ' ')
index--;
break;
case { Key: ConsoleKey.RightArrow, Modifiers: ConsoleModifiers.Control }:
while (index < buffer.Length && buffer[index] == ' ')
index++;
while (index < buffer.Length && buffer[index] != ' ')
index++;
break;
case { Key: ConsoleKey.LeftArrow } when index > 0:
index--;
break;
case { Key: ConsoleKey.RightArrow } when index < buffer.Length:
index++;
break;
case { Key: ConsoleKey.W, Modifiers: ConsoleModifiers.Control } when index > 0:
var deleteStart = index;
while (deleteStart > 0 && buffer[deleteStart - 1] == ' ')
deleteStart--;
while (deleteStart > 0 && buffer[deleteStart - 1] != ' ')
deleteStart--;
var charsToDelete = index - deleteStart;
buffer = buffer.Remove(deleteStart, charsToDelete);
index = deleteStart;
break;
default:
var keyChar = inputKey.KeyChar;
if (!(char.IsLetterOrDigit(keyChar) || char.IsWhiteSpace(keyChar) || char.IsPunctuation(keyChar) || char.IsSymbol(keyChar)))
break;
buffer = buffer.Insert(index, inputKey.KeyChar.ToString());
index++;
break;
}
// Adjust viewport for scrolling
var visibleWidth = Console.WindowWidth - left - 1;
if (index < viewportOffset)
viewportOffset = index;
else if (index >= viewportOffset + visibleWidth)
viewportOffset = index - visibleWidth + 1;
DisplayText(left, buffer, index, placeholder, viewportOffset);
}
}
}
}