Forward word, backward word, some small code changes

This commit is contained in:
Miguel de Icaza
2018-03-23 23:46:01 -04:00
parent 045bb85108
commit 30602b1f46
12 changed files with 218 additions and 101 deletions

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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)

View File

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

View File

@@ -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;

View File

@@ -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;

View File

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

View File

@@ -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>

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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;
}
IEnumerable<(int col, int row, Rune rune)> ForwardIterator (int col, int row)
{
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;
}
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;
}
while (MoveNext (ref col, ref row, out rune)) {
if (!Rune.IsLetterOrDigit (rune))
break;
}
} else {
while (MoveNext (ref col, ref row, out rune)) {
if (!Rune.IsLetterOrDigit (rune))
break;
}
}
if (fromCol != col || fromRow != row)
return (col, row);
return null;
}
(int col, int row)? WordBackward (int fromCol, int fromRow)
{
if (fromRow == 0 && fromCol == 0)
return null;
var col = fromCol;
var row = fromRow;
var line = GetCurrentLine ();
var rune = RuneAt (col, row);
if (Rune.IsPunctuation (rune) || Rune.IsSymbol (rune) || Rune.IsWhiteSpace (rune)) {
while (MovePrev (ref col, ref row, out rune)){
if (Rune.IsLetterOrDigit (rune))
break;
}
while (MovePrev (ref col, ref row, out rune)){
if (!Rune.IsLetterOrDigit (rune))
break;
}
} else {
while (MovePrev (ref col, ref row, out rune)) {
if (!Rune.IsLetterOrDigit (rune))
break;
}
}
if (fromCol != col || fromRow != row)
return (col, row);
return null;
}
#if false
int WordForward (int p)
{
if (p >= text.Length)
return -1;
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))
break;
}
for (; i < text.Length; i++) {
var r = text [i];
if (!Rune.IsLetterOrDigit (r))
break;
}
} else {
for (; i < text.Length; i++) {
var r = text [i];
if (!Rune.IsLetterOrDigit (r))
break;
}
}
if (i != p)
return i;
return -1;
}
int WordBackward (int p)
{
if (p == 0)
return -1;
int i = p - 1;
if (i == 0)
return 0;
var ti = text [i];
if (Rune.IsPunctuation (ti) || Rune.IsSymbol (ti) || Rune.IsWhiteSpace (ti)) {
for (; i >= 0; i--) {
if (Rune.IsLetterOrDigit (text [i]))
break;
}
for (; i >= 0; i--) {
if (!Rune.IsLetterOrDigit (text [i]))
break;
}
} else {
for (; i >= 0; i--) {
if (!Rune.IsLetterOrDigit (text [i]))
break;
}
}
i++;
if (i != p)
return i;
return -1;
}
public override bool MouseEvent (MouseEvent ev)
{
if (!ev.Flags.HasFlag (MouseFlags.Button1Clicked))

View File

@@ -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))
{