TextRegexProvider.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. using System.Text.RegularExpressions;
  2. namespace Terminal.Gui.Views;
  3. /// <summary>Regex Provider for TextValidateField.</summary>
  4. public class TextRegexProvider : ITextValidateProvider
  5. {
  6. private List<Rune> _pattern = null!;
  7. private Regex _regex = null!;
  8. private List<Rune> _text = null!;
  9. /// <summary>Empty Constructor.</summary>
  10. public TextRegexProvider (string pattern) { Pattern = pattern; }
  11. /// <summary>Regex pattern property.</summary>
  12. public string Pattern
  13. {
  14. get => StringExtensions.ToString (_pattern);
  15. set
  16. {
  17. _pattern = value.ToRuneList ();
  18. CompileMask ();
  19. SetupText ();
  20. }
  21. }
  22. /// <summary>When true, validates with the regex pattern on each input, preventing the input if it's not valid.</summary>
  23. public bool ValidateOnInput { get; set; } = true;
  24. /// <inheritdoc/>
  25. public event EventHandler<EventArgs<string>> TextChanged = null!;
  26. /// <inheritdoc/>
  27. public string Text
  28. {
  29. get => StringExtensions.ToString (_text);
  30. set
  31. {
  32. _text = (value != string.Empty ? value.ToRuneList () : null)!;
  33. SetupText ();
  34. }
  35. }
  36. /// <inheritdoc/>
  37. public string DisplayText => Text;
  38. /// <inheritdoc/>
  39. public bool IsValid => Validate (_text);
  40. /// <inheritdoc/>
  41. public bool Fixed => false;
  42. /// <inheritdoc/>
  43. public int Cursor (int pos)
  44. {
  45. if (pos < 0)
  46. {
  47. return CursorStart ();
  48. }
  49. if (pos >= _text.Count)
  50. {
  51. return CursorEnd ();
  52. }
  53. return pos;
  54. }
  55. /// <inheritdoc/>
  56. public int CursorStart () { return 0; }
  57. /// <inheritdoc/>
  58. public int CursorEnd () { return _text.Count; }
  59. /// <inheritdoc/>
  60. public int CursorLeft (int pos)
  61. {
  62. if (pos > 0)
  63. {
  64. return pos - 1;
  65. }
  66. return pos;
  67. }
  68. /// <inheritdoc/>
  69. public int CursorRight (int pos)
  70. {
  71. if (pos < _text.Count)
  72. {
  73. return pos + 1;
  74. }
  75. return pos;
  76. }
  77. /// <inheritdoc/>
  78. public bool Delete (int pos)
  79. {
  80. if (_text.Count > 0 && pos < _text.Count)
  81. {
  82. string oldValue = Text;
  83. _text.RemoveAt (pos);
  84. OnTextChanged (new (in oldValue));
  85. }
  86. return true;
  87. }
  88. /// <inheritdoc/>
  89. public bool InsertAt (char ch, int pos)
  90. {
  91. List<Rune> aux = _text.ToList ();
  92. aux.Insert (pos, (Rune)ch);
  93. if (Validate (aux) || ValidateOnInput == false)
  94. {
  95. string oldValue = Text;
  96. _text.Insert (pos, (Rune)ch);
  97. OnTextChanged (new (in oldValue));
  98. return true;
  99. }
  100. return false;
  101. }
  102. /// <inheritdoc/>
  103. public void OnTextChanged (EventArgs<string> args) { TextChanged?.Invoke (this, args); }
  104. /// <summary>Compiles the regex pattern for validation./></summary>
  105. private void CompileMask () { _regex = new (StringExtensions.ToString (_pattern), RegexOptions.Compiled); }
  106. private void SetupText ()
  107. {
  108. if (_text is { } && IsValid)
  109. {
  110. return;
  111. }
  112. _text = new ();
  113. }
  114. private bool Validate (List<Rune> text)
  115. {
  116. Match match = _regex.Match (StringExtensions.ToString (text));
  117. return match.Success;
  118. }
  119. }