2
0
Эх сурвалжийг харах

Merge pull request #1336 from tznind/color-text-view

Expose TextView color methods as protected virtual (allows custom colors)
Charlie Kindel 4 жил өмнө
parent
commit
2f813bfaf1

+ 35 - 6
Terminal.Gui/Views/TextView.cs

@@ -1333,17 +1333,46 @@ namespace Terminal.Gui {
 			}
 		}
 
-		void ColorNormal ()
+		/// <summary>
+		/// Sets the driver to the default color for the control where no text is being rendered.  Defaults to <see cref="ColorScheme.Normal"/>.
+		/// </summary>
+		protected virtual void ColorNormal ()
+		{
+			Driver.SetAttribute (ColorScheme.Normal);
+		}
+
+		/// <summary>
+		/// Sets the <see cref="View.Driver"/> to an appropriate color for rendering the given <paramref name="idx"/> of the
+		/// current <paramref name="line"/>.  Override to provide custom coloring by calling <see cref="ConsoleDriver.SetAttribute(Attribute)"/>
+		/// Defaults to <see cref="ColorScheme.Normal"/>.
+		/// </summary>
+		/// <param name="line"></param>
+		/// <param name="idx"></param>
+		protected virtual void ColorNormal (List<Rune> line, int idx)
 		{
 			Driver.SetAttribute (ColorScheme.Normal);
 		}
 
-		void ColorSelection ()
+		/// <summary>
+		/// Sets the <see cref="View.Driver"/> to an appropriate color for rendering the given <paramref name="idx"/> of the
+		/// current <paramref name="line"/>.  Override to provide custom coloring by calling <see cref="ConsoleDriver.SetAttribute(Attribute)"/>
+		/// Defaults to <see cref="ColorScheme.Focus"/>.
+		/// </summary>
+		/// <param name="line"></param>
+		/// <param name="idx"></param>
+		protected virtual void ColorSelection (List<Rune> line, int idx)
 		{
 			Driver.SetAttribute (ColorScheme.Focus);
 		}
 
-		void ColorUsed ()
+		/// <summary>
+		/// Sets the <see cref="View.Driver"/> to an appropriate color for rendering the given <paramref name="idx"/> of the
+		/// current <paramref name="line"/>.  Override to provide custom coloring by calling <see cref="ConsoleDriver.SetAttribute(Attribute)"/>
+		/// Defaults to <see cref="ColorScheme.HotFocus"/>.
+		/// </summary>
+		/// <param name="line"></param>
+		/// <param name="idx"></param>
+		protected virtual void ColorUsed (List<Rune> line, int idx)
 		{
 			Driver.SetAttribute (ColorScheme.HotFocus);
 		}
@@ -1667,12 +1696,12 @@ namespace Terminal.Gui {
 					var rune = idxCol >= lineRuneCount ? ' ' : line [idxCol];
 					var cols = Rune.ColumnWidth (rune);
 					if (idxCol < line.Count && selecting && PointInSelection (idxCol, idxRow)) {
-						ColorSelection ();
+						ColorSelection (line, idxCol);
 					} else if (idxCol == currentColumn && idxRow == currentRow && !selecting && !Used
 						&& HasFocus && idxCol < lineRuneCount) {
-						ColorUsed ();
+						ColorUsed (line, idxCol);
 					} else {
-						ColorNormal ();
+						ColorNormal (line,idxCol);
 					}
 
 					if (rune == '\t' && TabWidth > 0) {

+ 180 - 0
UICatalog/Scenarios/SyntaxHighlighting.cs

@@ -0,0 +1,180 @@
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Terminal.Gui;
+using static UICatalog.Scenario;
+using Attribute = Terminal.Gui.Attribute;
+
+namespace UICatalog.Scenarios {
+	[ScenarioMetadata (Name: "Syntax Highlighting", Description: "Text editor with keyword highlighting")]
+	[ScenarioCategory ("Controls")]
+	class SyntaxHighlighting : Scenario {
+
+			public override void Setup ()
+			{
+				Win.Title = this.GetName ();
+				Win.Y = 1; // menu
+				Win.Height = Dim.Fill (1); // status bar
+				Top.LayoutSubviews ();
+
+				var menu = new MenuBar (new MenuBarItem [] {
+				new MenuBarItem ("_File", new MenuItem [] {
+					new MenuItem ("_Quit", "", () => Quit()),
+				})
+				});
+				Top.Add (menu);
+
+				var textView = new SqlTextView () {
+					X = 0,
+					Y = 0,
+					Width = Dim.Fill (),
+					Height = Dim.Fill (1),
+				};
+
+				textView.Init();
+
+				textView.Text = "SELECT TOP 100 * \nfrom\n MyDb.dbo.Biochemistry;";
+				
+				Win.Add (textView);
+
+				var statusBar = new StatusBar (new StatusItem [] {
+				new StatusItem(Key.CtrlMask | Key.Q, "~^Q~ Quit", () => Quit()),
+
+			});
+
+
+				Top.Add (statusBar);
+			}
+
+
+			private void Quit ()
+			{
+				Application.RequestStop ();
+			}
+
+		private class SqlTextView : TextView{
+
+			private HashSet<string> keywords = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
+			private Attribute blue;
+			private Attribute white;
+			private Attribute magenta;
+
+
+			public void Init()
+			{
+				keywords.Add("select");
+				keywords.Add("distinct");
+				keywords.Add("top");
+				keywords.Add("from");
+				keywords.Add ("create");
+				keywords.Add ("primary");
+				keywords.Add ("key");
+				keywords.Add ("insert");
+				keywords.Add ("alter");
+				keywords.Add ("add");
+				keywords.Add ("update");
+				keywords.Add ("set");
+				keywords.Add ("delete");
+				keywords.Add ("truncate");
+				keywords.Add ("as");
+				keywords.Add ("order");
+				keywords.Add ("by");
+				keywords.Add ("asc");
+				keywords.Add ("desc");
+				keywords.Add ("between");
+				keywords.Add ("where");
+				keywords.Add ("and");
+				keywords.Add ("or");
+				keywords.Add ("not");
+				keywords.Add ("limit");
+				keywords.Add ("null");
+				keywords.Add ("is");
+				keywords.Add ("drop");
+				keywords.Add ("database");
+				keywords.Add ("column");
+				keywords.Add ("table");
+				keywords.Add ("having");
+				keywords.Add ("in");
+				keywords.Add ("join");
+				keywords.Add ("on");
+				keywords.Add ("union");
+				keywords.Add ("exists");
+
+				magenta = Driver.MakeAttribute (Color.Magenta, Color.Black);
+				blue = Driver.MakeAttribute (Color.Cyan, Color.Black);
+				white = Driver.MakeAttribute (Color.White, Color.Black);
+			}
+
+			protected override void ColorNormal ()
+			{
+				Driver.SetAttribute (white);
+			}
+
+			protected override void ColorNormal (List<System.Rune> line, int idx)
+			{
+				if(IsInStringLiteral(line,idx)) {
+					Driver.SetAttribute (magenta);
+				}
+				else
+				if(IsKeyword(line,idx))
+				{
+					Driver.SetAttribute (blue);
+				}
+				else{
+					Driver.SetAttribute (white);
+				}
+			}
+
+			private bool IsInStringLiteral (List<System.Rune> line, int idx)
+			{
+				string strLine = new string (line.Select (r => (char)r).ToArray ());
+				
+				foreach(Match m in Regex.Matches(strLine, "'[^']*'")) {
+					if(idx >= m.Index && idx < m.Index+m.Length) {
+						return true;
+					}
+				}
+
+				return false;
+			}
+
+			private bool IsKeyword(List<System.Rune> line, int idx)
+			{
+				var word = IdxToWord(line,idx);
+				
+				if(string.IsNullOrWhiteSpace(word)){
+					return false;
+				}
+
+				return keywords.Contains(word,StringComparer.CurrentCultureIgnoreCase);
+			}
+
+			private string IdxToWord(List<System.Rune> line, int idx)
+			{
+				var words = Regex.Split(
+					new string(line.Select(r=>(char)r).ToArray()),
+					"\\b");
+
+
+				int count = 0;
+				string current = null;
+
+				foreach(var word in words)
+				{
+					current = word;
+					count+= word.Length;
+					if(count > idx){
+						break;
+					}
+				}
+
+				return current?.Trim();
+			}
+		}
+	}
+}