Browse Source

Forward word, backward word, some small code changes

Miguel de Icaza 7 years ago
parent
commit
30602b1f46

+ 5 - 6
Terminal.Gui/Core.cs

@@ -1176,7 +1176,7 @@ namespace Terminal.Gui {
 	///     to the mainloop, allowing user code to use async/await.
 	///   </para>
 	/// </remarks>
-	public class Application {
+	public static class Application {
 		/// <summary>
 		/// The current Console Driver in use.
 		/// </summary>
@@ -1316,7 +1316,7 @@ namespace Terminal.Gui {
 			protected virtual void Dispose (bool disposing)
 			{
 				if (Toplevel != null) {
-					Application.End (Toplevel);
+					End (Toplevel);
 					Toplevel = null;
 				}
 			}
@@ -1509,8 +1509,9 @@ namespace Terminal.Gui {
 			toplevels.Pop ();
 			if (toplevels.Count == 0)
 				Shutdown ();
-			else {
-				Current = toplevels.Peek () as Toplevel;
+			else
+			{
+				Current = toplevels.Peek();
 				Refresh ();
 			}
 		}
@@ -1605,8 +1606,6 @@ namespace Terminal.Gui {
 		/// </summary>
 		public static void RequestStop ()
 		{
-			var ct = Current as Toplevel;
-
 			Current.Running = false;
 		}
 

+ 1 - 1
Terminal.Gui/Dialogs/MessageBox.cs

@@ -21,7 +21,7 @@ namespace Terminal.Gui {
 	/// 
 	/// </code>
 	/// </example>
-	public class MessageBox {
+	public static class MessageBox {
 		/// <summary>
 		/// Presents a message with the specified title and message and a list of buttons to show to the user.
 		/// </summary>

+ 3 - 1
Terminal.Gui/Driver.cs

@@ -583,6 +583,8 @@ namespace Terminal.Gui {
 		{
 			int wch;
 			var code = Curses.get_wch (out wch);
+			if (code == Curses.ERR)
+				return;
 			if (code == Curses.KEY_CODE_YES) {
 				if (wch == Curses.KeyResize) {
 					if (Curses.CheckWinChange ()) {
@@ -602,7 +604,7 @@ namespace Terminal.Gui {
 
 			// Special handling for ESC, we want to try to catch ESC+letter to simulate alt-letter as well as Alt-Fkey
 			if (wch == 27) {
-				Curses.timeout (100);
+				Curses.timeout (200);
 
 				code = Curses.get_wch (out wch);
 				if (code == Curses.KEY_CODE_YES)

+ 4 - 2
Terminal.Gui/MonoCurses/mainloop.cs

@@ -407,8 +407,10 @@ namespace Mono.Terminal {
 				}
 			}
 
-			if (idleHandlers.Count > 0)
-				RunIdle ();
+			lock (idleHandlers){
+				if (idleHandlers.Count > 0)
+					RunIdle();
+			}
 		}
 		
 		/// <summary>

+ 5 - 5
Terminal.Gui/Views/Button.cs

@@ -27,7 +27,7 @@ namespace Terminal.Gui {
 	public class Button : View {
 		ustring text;
 		ustring shown_text;
-		char hot_key;
+		Rune hot_key;
 		int hot_pos = -1;
 		bool is_default;
 
@@ -112,10 +112,10 @@ namespace Terminal.Gui {
 				shown_text = "[ " + text + " ]";
 
 			hot_pos = -1;
-			hot_key = (char)0;
+			hot_key = (Rune)0;
 			int i = 0;
-			foreach (char c in shown_text) {
-				if (Char.IsUpper (c)) {
+			foreach (Rune c in shown_text) {
+				if (Rune.IsUpper (c)) {
 					hot_key = c;
 					hot_pos = i;
 					break;
@@ -197,7 +197,7 @@ namespace Terminal.Gui {
 		public override bool ProcessKey (KeyEvent kb)
 		{
 			var c = kb.KeyValue;
-			if (c == '\n' || c == ' ' || Char.ToUpper ((char)c) == hot_key) {
+			if (c == '\n' || c == ' ' || Rune.ToUpper ((Rune)c) == hot_key) {
 				if (Clicked != null)
 					Clicked ();
 				return true;

+ 3 - 3
Terminal.Gui/Views/Checkbox.cs

@@ -15,7 +15,7 @@ namespace Terminal.Gui {
 	public class CheckBox : View {
 		ustring text;
 		int hot_pos = -1;
-		char hot_key;
+		Rune hot_key;
 
 		/// <summary>
 		///   Toggled event, raised when the CheckButton is toggled.
@@ -74,8 +74,8 @@ namespace Terminal.Gui {
 				int i = 0;
 				hot_pos = -1;
 				hot_key = (char)0;
-				foreach (char c in text) {
-					if (Char.IsUpper (c)) {
+				foreach (Rune c in text) {
+					if (Rune.IsUpper (c)) {
 						hot_key = c;
 						hot_pos = i;
 						break;

+ 1 - 1
Terminal.Gui/Views/Clipboard.cs

@@ -2,7 +2,7 @@
 using NStack;
 
 namespace Terminal.Gui {
-	public class Clipboard {
+	public static class Clipboard {
 		public static ustring Contents { get; set; }
 	}
 }

+ 2 - 2
Terminal.Gui/Views/Label.cs

@@ -91,7 +91,7 @@ namespace Terminal.Gui {
 				if (talign == TextAlignment.Justified) {
 					// TODO: ustring needs this
 			               	var words = str.ToString ().Split (whitespace, StringSplitOptions.RemoveEmptyEntries);
-					int textCount = words.Sum ((arg) => arg.Length);
+					int textCount = words.Sum (arg => arg.Length);
 
 					var spaces = (width- textCount) / (words.Length - 1);
 					var extras = (width - textCount) % words.Length;
@@ -186,7 +186,7 @@ namespace Terminal.Gui {
 		{
 			var result = new List<ustring> ();
 			Recalc (text, result, width, TextAlignment.Left);
-			return result.Count ();
+			return result.Count;
 		}
 
 		/// <summary>

+ 1 - 1
Terminal.Gui/Views/ListView.cs

@@ -137,7 +137,7 @@ namespace Terminal.Gui {
 				} else if (t is string) {
 					RenderUstr (t as string, col, line, width);
 				} else
-					RenderUstr (((string)t).ToString (), col, line, width);
+					RenderUstr (t.ToString (), col, line, width);
 			}
 
 			public bool IsMarked (int item)

+ 1 - 1
Terminal.Gui/Views/Menu.cs

@@ -30,7 +30,7 @@ namespace Terminal.Gui {
 			Help = help ?? "";
 			Action = action;
 			bool nextIsHot = false;
-			foreach (var x in title) {
+			foreach (var x in Title) {
 				if (x == '_')
 					nextIsHot = true;
 				else {

+ 168 - 54
Terminal.Gui/Views/TextView.cs

@@ -16,6 +16,11 @@
 // public API to insert, remove ranges
 // Add word forward/word backwards commands
 // Save buffer API
+// Mouse
+//
+// Desirable:
+//   Move all the text manipulation into the TextModel
+
 
 using System;
 using System.Collections.Generic;
@@ -34,8 +39,6 @@ namespace Terminal.Gui {
 				throw new ArgumentNullException (nameof (file));
 			try {
 				var stream = File.OpenRead (file);
-				if (stream == null)
-					return false;
 			} catch {
 				return false;
 			}
@@ -115,15 +118,32 @@ namespace Terminal.Gui {
 			return sb.ToString ();
 		}
 
+		/// <summary>
+		/// The number of text lines in the model
+		/// </summary>
 		public int Count => lines.Count;
 
+		/// <summary>
+		/// Returns the specified line as a List of Rune
+		/// </summary>
+		/// <returns>The line.</returns>
+		/// <param name="line">Line number to retrieve.</param>
 		public List<Rune> GetLine (int line) => lines [line];
 
+		/// <summary>
+		/// Adds a line to the model at the specified position.
+		/// </summary>
+		/// <param name="pos">Line number where the line will be inserted.</param>
+		/// <param name="runes">The line of text, as a List of Rune.</param>
 		public void AddLine (int pos, List<Rune> runes)
 		{
 			lines.Insert (pos, runes);
 		}
 
+		/// <summary>
+		/// Removes the line at the specified position
+		/// </summary>
+		/// <param name="pos">Position.</param>
 		public void RemoveLine (int pos)
 		{
 			lines.RemoveAt (pos);
@@ -306,15 +326,14 @@ namespace Terminal.Gui {
 		/// Loads the contents of the stream into the TextView.
 		/// </summary>
 		/// <returns><c>true</c>, if stream was loaded, <c>false</c> otherwise.</returns>
-		/// <param name="stream">Stream.</param>
-		public bool LoadStream (Stream stream)
+		/// <param name="stream">Stream to load the contents from.</param>
+		public void LoadStream (Stream stream)
 		{
 			if (stream == null)
 				throw new ArgumentNullException (nameof (stream));
 			ResetPosition ();
-			var res = model.LoadFile (path);
+			model.LoadStream(stream);
 			SetNeedsDisplay ();
-			return res;
 		}
 
 		/// <summary>
@@ -406,10 +425,10 @@ namespace Terminal.Gui {
 			ustring res = StringFromRunes (line.GetRange (startCol, line.Count - startCol));
 
 			for (int row = startRow+1; row < maxrow; row++) {
-				res = res + ustring.Make (10) + StringFromRunes (model.GetLine (row));
+				res = res + ustring.Make ((Rune)10) + StringFromRunes (model.GetLine (row));
 			}
 			line = model.GetLine (maxrow);
-			res = res + ustring.Make (10) + StringFromRunes (line.GetRange (0, endCol));
+			res = res + ustring.Make ((Rune)10) + StringFromRunes (line.GetRange (0, endCol));
 			return res;
 		}
 
@@ -592,15 +611,32 @@ namespace Terminal.Gui {
 				currentColumn = columnTrack;
 			else if (currentColumn > line.Count)
 				currentColumn = line.Count;
-			
+			Adjust ();
+		}
+
+		void Adjust ()
+		{
+			bool need = false;
 			if (currentColumn < leftColumn) {
-				leftColumn = currentColumn;
-				SetNeedsDisplay ();
+				currentColumn = leftColumn;
+				need = true;
 			}
 			if (currentColumn - leftColumn > Frame.Width) {
 				leftColumn = currentColumn - Frame.Width + 1;
-				SetNeedsDisplay ();
+				need = true;
+			}
+			if (currentRow < topRow) {
+				topRow = currentRow;
+				need = true;
+			}
+			if (currentRow - topRow > Frame.Height) {
+				topRow = currentRow - Frame.Height + 1;
+				need = true;
 			}
+			if (need)
+				SetNeedsDisplay ();
+			else
+				PositionCursor ();
 		}
 
 		bool lastWasKill;
@@ -786,7 +822,7 @@ namespace Terminal.Gui {
 				currentLine = GetCurrentLine ();
 				if (currentLine.Count == 0) {
 					model.RemoveLine (currentRow);
-					var val = ustring.Make ('\n');
+					var val = ustring.Make ((Rune)'\n');
 					if (lastWasKill)
 						AppendClipboard (val);
 					else
@@ -816,7 +852,7 @@ namespace Terminal.Gui {
 				selectionStartRow = currentRow;
 				break;
 
-			case (Key)((int)'w' + Key.AltMask):
+			case ((int)'w' + Key.AltMask):
 				SetClipboard (GetRegion ());
 				selecting = false;
 				break;
@@ -828,9 +864,22 @@ namespace Terminal.Gui {
 				break;
 
 			case (Key)((int)'b' + Key.AltMask):
+				var newPos = WordBackward (currentColumn, currentRow);
+				if (newPos.HasValue) {
+					currentColumn = newPos.Value.col;
+					currentRow = newPos.Value.row;
+				}
+				Adjust ();
+
 				break;
 
-			case (Key)((int)'f' + Key.AltMask):
+			case (Key)((int)'f' + Key.AltMask): 
+				newPos = WordForward (currentColumn, currentRow);
+				if (newPos.HasValue) {
+					currentColumn = newPos.Value.col;
+					currentRow = newPos.Value.row;
+				}
+				Adjust ();
 				break;
 
 			case Key.Enter:
@@ -874,69 +923,134 @@ namespace Terminal.Gui {
 			return true;
 		}
 
-#if false
-		int WordForward (int p)
+		IEnumerable<(int col, int row, Rune rune)> ForwardIterator (int col, int row)
 		{
-			if (p >= text.Length)
-				return -1;
+			if (col < 0 || row < 0)
+				yield break;
+			if (row >= model.Count)
+				yield break;
+			var line = GetCurrentLine ();
+			if (col >= line.Count)
+				yield break;
+
+			while (row < model.Count) {
+				for (int c = col; c < line.Count; c++) {
+					yield return (c, row, line [c]);
+				}
+				col = 0;
+				row++;
+				line = GetCurrentLine ();
+			}
+		}
+
+		Rune RuneAt (int col, int row) => model.GetLine (row) [col];
+
+		bool MoveNext (ref int col, ref int row, out Rune rune)
+		{
+			var line = model.GetLine (row);
+			if (col + 1 < line.Count) {
+				col++;
+				rune = line [col];
+				return true;
+			} 
+			while (row + 1 < model.Count){
+				col = 0;
+				row++;
+				line = model.GetLine (row);
+				if (line.Count > 0) {
+					rune = line [0];
+					return true;
+				}
+			}
+			rune = 0;
+			return false;
+		}
 
-			int i = p;
-			if (Rune.IsPunctuation (text [p]) || Rune.IsWhiteSpace (text [p])) {
-				for (; i < text.Length; i++) {
-					var r = text [i];
-					if (Rune.IsLetterOrDigit (r))
+		bool MovePrev (ref int col, ref int row, out Rune rune)
+		{
+			var line = model.GetLine (row);
+
+			if (col > 0) {
+				col--;
+				rune = line [col];
+				return true;
+			}
+			if (row == 0) {
+				rune = 0;
+				return false;
+			}
+			while (row > 0) {
+				row--;
+				line = model.GetLine (row);
+				col = line.Count - 1;
+				if (col >= 0) {
+					rune = line [col];
+					return true;
+				}
+			}
+			rune = 0;
+			return false;
+		}
+
+		(int col, int row)? WordForward (int fromCol, int fromRow)
+		{
+			var col = fromCol;
+			var row = fromRow;
+			var line = GetCurrentLine ();
+			var rune = RuneAt (col, row);
+
+			var srow = row;
+			if (Rune.IsPunctuation (rune) || Rune.IsWhiteSpace (rune)) {
+				while (MoveNext (ref col, ref row, out rune)){
+					if (Rune.IsLetterOrDigit (rune))
 						break;
 				}
-				for (; i < text.Length; i++) {
-					var r = text [i];
-					if (!Rune.IsLetterOrDigit (r))
+				while (MoveNext (ref col, ref row, out rune)) {
+					if (!Rune.IsLetterOrDigit (rune))
 						break;
 				}
 			} else {
-				for (; i < text.Length; i++) {
-					var r = text [i];
-					if (!Rune.IsLetterOrDigit (r))
+				while (MoveNext (ref col, ref row, out rune)) {
+					if (!Rune.IsLetterOrDigit (rune))
 						break;
 				}
 			}
-			if (i != p)
-				return i;
-			return -1;
+			if (fromCol != col || fromRow != row)
+				return (col, row);
+			return null;
 		}
 
-		int WordBackward (int p)
+		(int col, int row)? WordBackward (int fromCol, int fromRow)
 		{
-			if (p == 0)
-				return -1;
-
-			int i = p - 1;
-			if (i == 0)
-				return 0;
+			if (fromRow == 0 && fromCol == 0)
+				return null;
+			
+			var col = fromCol;
+			var row = fromRow;
+			var line = GetCurrentLine ();
+			var rune = RuneAt (col, row);
 
-			var ti = text [i];
-			if (Rune.IsPunctuation (ti) || Rune.IsSymbol (ti) || Rune.IsWhiteSpace (ti)) {
-				for (; i >= 0; i--) {
-					if (Rune.IsLetterOrDigit (text [i]))
+			if (Rune.IsPunctuation (rune) || Rune.IsSymbol (rune) || Rune.IsWhiteSpace (rune)) {
+				while (MovePrev (ref col, ref row, out rune)){
+					if (Rune.IsLetterOrDigit (rune))
 						break;
 				}
-				for (; i >= 0; i--) {
-					if (!Rune.IsLetterOrDigit (text [i]))
+				while (MovePrev (ref col, ref row, out rune)){
+					if (!Rune.IsLetterOrDigit (rune))
 						break;
 				}
 			} else {
-				for (; i >= 0; i--) {
-					if (!Rune.IsLetterOrDigit (text [i]))
+				while (MovePrev (ref col, ref row, out rune)) {
+					if (!Rune.IsLetterOrDigit (rune))
 						break;
 				}
 			}
-			i++;
-
-			if (i != p)
-				return i;
-
-			return -1;
+			if (fromCol != col || fromRow != row)
+				return (col, row);
+			return null;
 		}
 
+#if false
 		public override bool MouseEvent (MouseEvent ev)
 		{
 			if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked))

+ 1 - 1
demo.cs

@@ -2,7 +2,7 @@ using Terminal.Gui;
 using System;
 using Mono.Terminal;
 
-class Demo {
+static class Demo {
 	class Box10x : View {
 		public Box10x (int x, int y) : base (new Rect (x, y, 10, 10))
 		{