SyntaxHighlighting.cs 5.1 KB

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