Script for automating a large assortment of AME related actions
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

604 lines
28 KiB

using System;
using System.Collections;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using JetBrains.Annotations;
namespace Ameliorated.ConsoleUtils
{
/// <summary>
/// Represents a input prompt to be used with the Start method.
/// </summary>
public class ChoicePrompt : Prompt
{
public string Choices { get; set; } = "YN";
public bool BeepSound { get; set; } = true;
public bool CaseSensitive { get; set; } = false;
public bool AllowEscape { get; set; } = true;
public bool AnyKey { get; set; } = false;
public ConsoleColor? TextForeground { get; set; }
private bool _bindToOpenFrame;
[CanBeNull]
public new int? Start()
{
if (Choices.Length < 1 && !AnyKey) throw new ArgumentException("There must be at least 1 choice.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (TextForeground.HasValue)
ConsoleUtils.SetColor(TextForeground);
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (TextForeground.HasValue)
ConsoleUtils.ResetColor();
var cursorVisibility = Console.CursorVisible;
int? result;
while (true)
{
Console.CursorVisible = true;
ConsoleUtils.ClearInputBuffer();
var key = Console.ReadKey(true);
if (AnyKey)
{
Console.CursorVisible = cursorVisibility;
return key.KeyChar;
}
if (key.Key == ConsoleKey.Escape && AllowEscape)
{
Console.CursorVisible = cursorVisibility;
return null;
}
if (CaseSensitive)
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.Ordinal);
else
result = Choices.IndexOf(key.KeyChar.ToString(), StringComparison.OrdinalIgnoreCase);
if (result >= 0)
{
if (InputForeground.HasValue && InputBackground.HasValue) ConsoleUtils.SetColor(InputForeground.Value, InputBackground.Value);
else if (InputForeground.HasValue) ConsoleUtils.SetColor(InputForeground.Value);
else if (InputBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, InputBackground.Value);
if (!CaseSensitive) Console.Write(key.KeyChar.ToString().ToUpper());
else Console.Write(key.KeyChar.ToString());
if (InputForeground.HasValue || InputBackground.HasValue) ConsoleUtils.ResetColor();
break;
}
else if (BeepSound) Console.Beep();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
return result.Value;
}
}
public class InputPrompt : Prompt
{
[Optional] public ConsoleColor? BoxBackground { get; set; }
public bool MaskInput { get; set; } = false;
public bool AlignInput { get; set; } = true;
[Optional] public int? SplitWidth { get; set; }
private bool _bindToOpenFrame;
private int? _splitWidth;
[CanBeNull]
public new string Start()
{
if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (!MaxLength.HasValue)
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars();
int startLeft = Console.CursorLeft + Text.LastLine().Length;
_splitWidth = null;
if (AlignInput && !_bindToOpenFrame)
{
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = Console.WindowWidth - startLeft;
}
if (_bindToOpenFrame)
{
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth))
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
// TODO: BAD WORDING
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft);
if (!AlignInput)
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth;
}
if (SplitWidth.HasValue)
{
if (SplitWidth.Value + startLeft >= Console.WindowWidth)
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = SplitWidth.Value;
}
/*
int maxLines = Console.WindowHeight - Console.CursorTop;
if (_bindToOpenFrame)
{
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
if (maxLines < 2)
{
ConsoleTUI.OpenFrame.Clear();
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
}
}
*/
ConsoleUtils.ClearInputBuffer();
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (BoxBackground.HasValue && _splitWidth.HasValue)
{
if (AlignInput)
WriteBackground(_splitWidth.Value, BoxBackground.Value);
else
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value);
}
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value);
var cursorVisibility = Console.CursorVisible;
var input = new StringBuilder();
ConsoleKeyInfo key;
do
{
Console.CursorVisible = true;
key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Backspace)
{
if (input.Length <= 0) continue;
input.Remove(input.Length - 1, 1);
bool movedLines = false;
if (_bindToOpenFrame)
{
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor);
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
}
else if (AlignInput)
{
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value))
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1);
movedLines = true;
}
}
else
{
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft)
{
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor);
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1);
movedLines = true;
}
}
if (movedLines)
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write(" \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
else
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write("\b \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true;
continue;
}
if (Char.IsControl(key.KeyChar)) continue;
if (MaxLength.HasValue && MaxLength.Value <= input.Length)
{
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground);
Console.CursorVisible = false;
Console.Write("!");
Thread.Sleep(200);
ConsoleUtils.ClearInputBuffer();
ConsoleUtils.ResetColor();
ConsoleUtils.SetColor(null, BoxBackground);
Console.Write("\b \b");
ConsoleUtils.ResetColor();
continue;
}
input.Append(key.KeyChar);
ConsoleUtils.SetColor(InputForeground, InputBackground);
if (MaskInput) Console.Write("*");
else Console.Write(key.KeyChar);
ConsoleUtils.ResetColor();
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1)
continue;
if (_bindToOpenFrame)
{
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else if (AlignInput)
{
if (input.Length.IsDivisibleBy(_splitWidth.Value))
{
if (SplitWidth.HasValue)
Console.SetCursorPosition(startLeft, Console.CursorTop + 1);
else
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else
{
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft)
{
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value);
}
}
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape)));
if (input.Length == 0)
{
ConsoleUtils.SetColor(ConsoleColor.DarkGray);
Console.Write("None");
ConsoleUtils.ResetColor();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
if (key.Key == ConsoleKey.Escape && AllowEscape) return null;
return input.ToString();
}
}
public class SecureInputPrompt : Prompt
{
[Optional] public ConsoleColor? BoxBackground { get; set; }
public bool MaskInput { get; set; } = true;
public bool AlignInput { get; set; } = true;
[Optional] public int? SplitWidth { get; set; }
private bool _bindToOpenFrame;
private int? _splitWidth;
[CanBeNull]
public new SecureString Start()
{if (SplitWidth.HasValue && !AlignInput) throw new ArgumentException("Property SplitWidth must not be used without property AlignInput set to true.");
_bindToOpenFrame = ConsoleTUI.OpenFrame != null && BindToOpenFrame;
if (_bindToOpenFrame && ConsoleTUI.OpenFrame.AvailableLines() < 1)
ConsoleTUI.OpenFrame.Clear();
if (!MaxLength.HasValue)
MaxLength = AlignInput ? ConsoleTUI.OpenFrame.AvailableChars() - (Text.LastLine().Length * ConsoleTUI.OpenFrame.AvailableLines()) : ConsoleTUI.OpenFrame.AvailableChars();
int startLeft = Console.CursorLeft + Text.LastLine().Length;
_splitWidth = null;
if (AlignInput && !_bindToOpenFrame)
{
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = Console.WindowWidth - startLeft;
}
if (_bindToOpenFrame)
{
if (SplitWidth.HasValue && (SplitWidth.Value + startLeft + ConsoleTUI.OpenFrame.DisplayOffset >= Console.WindowWidth))
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
// TODO: BAD WORDING
if (Text.LastLine().Length > ConsoleTUI.OpenFrame.DisplayWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth - (startLeft);
if (!AlignInput)
_splitWidth = ConsoleTUI.OpenFrame.DisplayWidth;
}
if (SplitWidth.HasValue)
{
if (SplitWidth.Value + startLeft >= Console.WindowWidth)
throw new ArgumentException($"Property SplitWidth must be less than the available width.");
if (Text.LastLine().Length > Console.WindowWidth - 3) throw new ArgumentException("Last line of property Text must not be within 3 characters of the available width.");
_splitWidth = SplitWidth.Value;
}
/*
int maxLines = Console.WindowHeight - Console.CursorTop;
if (_bindToOpenFrame)
{
maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
if (maxLines < 2)
{
ConsoleTUI.OpenFrame.Clear();
if (_bindToOpenFrame) maxLines = ConsoleTUI.OpenFrame.DisplayHeight - (Console.CursorTop - 6) - Text.SplitByLine().Length;
}
}
*/
ConsoleUtils.ClearInputBuffer();
if (_bindToOpenFrame)
ConsoleTUI.OpenFrame.Write(Text);
else
Console.Write(Text);
if (BoxBackground.HasValue && _splitWidth.HasValue)
{
if (AlignInput)
WriteBackground(_splitWidth.Value, BoxBackground.Value);
else
WriteBackground(_splitWidth.Value - Text.LastLine().Length, BoxBackground.Value);
}
if (BoxBackground.HasValue && !_splitWidth.HasValue) WriteBackground(Console.WindowWidth - Console.CursorLeft, BoxBackground.Value);
var cursorVisibility = Console.CursorVisible;
var input = new SecureString();
ConsoleKeyInfo key;
do
{
Console.CursorVisible = true;
key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Backspace)
{
if (input.Length <= 0) continue;
input.RemoveAt(input.Length - 1);
bool movedLines = false;
if (_bindToOpenFrame)
{
if ((((input.Length + 1) - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(ConsoleTUI.OpenFrame.DisplayWidth) || input.Length + 1 == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value - (Console.CursorLeft - ConsoleTUI.OpenFrame.DisplayOffset), Console.BackgroundColor);
Console.SetCursorPosition((ConsoleTUI.OpenFrame.DisplayOffset) + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
else if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset + startLeft + _splitWidth.Value - 1, Console.CursorTop - 1);
movedLines = true;
}
}
else if (AlignInput)
{
if ((input.Length + 1).IsDivisibleBy(_splitWidth.Value))
{
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, Console.BackgroundColor);
Console.SetCursorPosition(startLeft + _splitWidth.Value, Console.CursorTop - 1);
movedLines = true;
}
}
else
{
if (((input.Length + 1) - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length + 1 == Console.WindowWidth - startLeft)
{
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth, Console.BackgroundColor);
Console.SetCursorPosition(Console.WindowWidth - 1, Console.CursorTop - 1);
movedLines = true;
}
}
if (movedLines)
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write(" \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
else
{
if (BoxBackground.HasValue) ConsoleUtils.SetColor(Console.ForegroundColor, BoxBackground.Value);
Console.Write("\b \b");
if (BoxBackground.HasValue) ConsoleUtils.ResetColor();
}
if (MaxLength.HasValue && MaxLength.Value - 1 == input.Length) Console.CursorVisible = true;
}
if (Char.IsControl(key.KeyChar)) continue;
if (MaxLength.HasValue && MaxLength.Value <= input.Length)
{
ConsoleUtils.SetColor(ConsoleColor.DarkRed, InputBackground);
Console.CursorVisible = false;
Console.Write("!");
Thread.Sleep(200);
ConsoleUtils.ClearInputBuffer();
ConsoleUtils.ResetColor();
ConsoleUtils.SetColor(null, BoxBackground);
Console.Write("\b \b");
ConsoleUtils.ResetColor();
continue;
}
input.AppendChar(key.KeyChar);
ConsoleUtils.SetColor(InputForeground, InputBackground);
if (MaskInput) Console.Write("*");
else Console.Write(key.KeyChar);
ConsoleUtils.ResetColor();
if (MaxLength.HasValue && MaxLength.Value <= input.Length + 1)
continue;
if (_bindToOpenFrame)
{
if (((input.Length - _splitWidth.Value + Text.LastLine().Length).IsDivisibleBy(_splitWidth.Value) || input.Length == _splitWidth.Value - Text.LastLine().Length) && !AlignInput)
{
Console.SetCursorPosition(ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
else if (input.Length.IsDivisibleBy(_splitWidth.Value) && AlignInput)
{
Console.SetCursorPosition(startLeft + ConsoleTUI.OpenFrame.DisplayOffset, Console.CursorTop + 1);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else if (AlignInput)
{
if (input.Length.IsDivisibleBy(_splitWidth.Value))
{
if (SplitWidth.HasValue)
Console.SetCursorPosition(startLeft, Console.CursorTop + 1);
else
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(_splitWidth.Value, BoxBackground.Value);
}
}
else
{
if ((input.Length - (Console.WindowWidth - startLeft)).IsDivisibleBy(Console.WindowWidth) || input.Length == Console.WindowWidth - startLeft)
{
// Console will have automatically moved the cursor down
Console.SetCursorPosition(startLeft - Text.LastLine().Length, Console.CursorTop);
if (BoxBackground.HasValue) WriteBackground(Console.WindowWidth - (startLeft - Text.LastLine().Length), BoxBackground.Value);
}
}
} while (key.Key != ConsoleKey.Enter && (!AllowEscape || (AllowEscape && key.Key != ConsoleKey.Escape)));
if (input.Length == 0)
{
ConsoleUtils.SetColor(ConsoleColor.Gray);
Console.Write("None");
ConsoleUtils.ResetColor();
}
Console.CursorVisible = cursorVisibility;
Console.WriteLine();
if (key.Key == ConsoleKey.Escape && AllowEscape) return null;
return input;
}
}
public abstract class Prompt
{
/// <summary>
/// Text to be displayed before the input.
/// </summary>
[Optional]
public string Text { get; set; } = "";
[Optional] public int? MaxLength { get; set; }
/// <summary>
/// (Optional)
/// </summary>
[Optional]
public ConsoleColor? InputForeground { get; set; } = null;
[Optional] public ConsoleColor? InputBackground { get; set; } = null;
public bool BindToOpenFrame { get; set; } = true;
public bool AllowEscape { get; set; } = true;
internal static void WriteBackground(int length, ConsoleColor color)
{
if (Console.CursorLeft + length > Console.WindowWidth) throw new Exception("Critical Error");
int leftStart = Console.CursorLeft;
int topStart = Console.CursorTop;
ConsoleUtils.SetColor(Console.ForegroundColor, color);
Console.Write(new string(' ', length));
ConsoleUtils.ResetColor();
Console.SetCursorPosition(leftStart, topStart);
}
}
}