SyntaxHighlighting.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. 
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using System.Threading.Tasks;
  9. using Terminal.Gui;
  10. using static UICatalog.Scenario;
  11. using Attribute = Terminal.Gui.Attribute;
  12. namespace UICatalog.Scenarios {
  13. [ScenarioMetadata (Name: "Syntax Highlighting", Description: "Text editor with keyword highlighting")]
  14. [ScenarioCategory ("Controls")]
  15. class SyntaxHighlighting : Scenario {
  16. public override void Setup ()
  17. {
  18. Win.Title = this.GetName ();
  19. Win.Y = 1; // menu
  20. Win.Height = Dim.Fill (1); // status bar
  21. Top.LayoutSubviews ();
  22. var menu = new MenuBar (new MenuBarItem [] {
  23. new MenuBarItem ("_File", new MenuItem [] {
  24. new MenuItem ("_Quit", "", () => Quit()),
  25. })
  26. });
  27. Top.Add (menu);
  28. var textView = new SqlTextView () {
  29. X = 0,
  30. Y = 0,
  31. Width = Dim.Fill (),
  32. Height = Dim.Fill (1),
  33. };
  34. textView.Init();
  35. textView.Text = "SELECT TOP 100 * \nfrom\n MyDb.dbo.Biochemistry;";
  36. Win.Add (textView);
  37. var statusBar = new StatusBar (new StatusItem [] {
  38. new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
  39. });
  40. Top.Add (statusBar);
  41. }
  42. private void Quit ()
  43. {
  44. Application.RequestStop ();
  45. }
  46. private class SqlTextView : TextView{
  47. private HashSet<string> keywords = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
  48. private Attribute blue;
  49. private Attribute white;
  50. private Attribute magenta;
  51. public void Init()
  52. {
  53. keywords.Add("select");
  54. keywords.Add("distinct");
  55. keywords.Add("top");
  56. keywords.Add("from");
  57. keywords.Add ("create");
  58. keywords.Add ("primary");
  59. keywords.Add ("key");
  60. keywords.Add ("insert");
  61. keywords.Add ("alter");
  62. keywords.Add ("add");
  63. keywords.Add ("update");
  64. keywords.Add ("set");
  65. keywords.Add ("delete");
  66. keywords.Add ("truncate");
  67. keywords.Add ("as");
  68. keywords.Add ("order");
  69. keywords.Add ("by");
  70. keywords.Add ("asc");
  71. keywords.Add ("desc");
  72. keywords.Add ("between");
  73. keywords.Add ("where");
  74. keywords.Add ("and");
  75. keywords.Add ("or");
  76. keywords.Add ("not");
  77. keywords.Add ("limit");
  78. keywords.Add ("null");
  79. keywords.Add ("is");
  80. keywords.Add ("drop");
  81. keywords.Add ("database");
  82. keywords.Add ("column");
  83. keywords.Add ("table");
  84. keywords.Add ("having");
  85. keywords.Add ("in");
  86. keywords.Add ("join");
  87. keywords.Add ("on");
  88. keywords.Add ("union");
  89. keywords.Add ("exists");
  90. magenta = Driver.MakeAttribute (Color.Magenta, Color.Black);
  91. blue = Driver.MakeAttribute (Color.Cyan, Color.Black);
  92. white = Driver.MakeAttribute (Color.White, Color.Black);
  93. }
  94. protected override void ColorNormal ()
  95. {
  96. Driver.SetAttribute (white);
  97. }
  98. protected override void ColorNormal (List<System.Rune> line, int idx)
  99. {
  100. if(IsInStringLiteral(line,idx)) {
  101. Driver.SetAttribute (magenta);
  102. }
  103. else
  104. if(IsKeyword(line,idx))
  105. {
  106. Driver.SetAttribute (blue);
  107. }
  108. else{
  109. Driver.SetAttribute (white);
  110. }
  111. }
  112. private bool IsInStringLiteral (List<System.Rune> line, int idx)
  113. {
  114. string strLine = new string (line.Select (r => (char)r).ToArray ());
  115. foreach(Match m in Regex.Matches(strLine, "'[^']*'")) {
  116. if(idx >= m.Index && idx < m.Index+m.Length) {
  117. return true;
  118. }
  119. }
  120. return false;
  121. }
  122. private bool IsKeyword(List<System.Rune> line, int idx)
  123. {
  124. var word = IdxToWord(line,idx);
  125. if(string.IsNullOrWhiteSpace(word)){
  126. return false;
  127. }
  128. return keywords.Contains(word,StringComparer.CurrentCultureIgnoreCase);
  129. }
  130. private string IdxToWord(List<System.Rune> line, int idx)
  131. {
  132. var words = Regex.Split(
  133. new string(line.Select(r=>(char)r).ToArray()),
  134. "\\b");
  135. int count = 0;
  136. string current = null;
  137. foreach(var word in words)
  138. {
  139. current = word;
  140. count+= word.Length;
  141. if(count > idx){
  142. break;
  143. }
  144. }
  145. return current?.Trim();
  146. }
  147. }
  148. }
  149. }