Merge pull request #1364 from BDisp/textview-load-file

Fixes #1314. TextView now exposes file exceptions from callers.
This commit is contained in:
Charlie Kindel
2021-07-21 08:55:05 -07:00
committed by GitHub
3 changed files with 337 additions and 129 deletions

View File

@@ -38,15 +38,10 @@ namespace Terminal.Gui {
public bool LoadFile (string file)
{
if (file == null)
throw new ArgumentNullException (nameof (file));
try {
FilePath = file;
var stream = File.OpenRead (file);
} catch {
return false;
}
LoadStream (File.OpenRead (file));
FilePath = file ?? throw new ArgumentNullException (nameof (file));
var stream = File.OpenRead (file);
LoadStream (stream);
return true;
}
@@ -54,12 +49,9 @@ namespace Terminal.Gui {
{
if (FilePath == null)
throw new ArgumentNullException (nameof (FilePath));
try {
FilePath = null;
lines = new List<List<Rune>> ();
} catch {
return false;
}
FilePath = null;
lines = new List<List<Rune>> ();
return true;
}
@@ -79,14 +71,21 @@ namespace Terminal.Gui {
{
var lines = new List<List<Rune>> ();
int start = 0, i = 0;
var hasCR = false;
// ASCII code 13 = Carriage Return.
// ASCII code 10 = Line Feed.
for (; i < content.Length; i++) {
if (content [i] == 13) {
hasCR = true;
continue;
}
if (content [i] == 10) {
if (i - start > 0)
lines.Add (ToRunes (content [start, i]));
lines.Add (ToRunes (content [start, hasCR ? i - 1 : i]));
else
lines.Add (ToRunes (ustring.Empty));
start = i + 1;
hasCR = false;
}
}
if (i - start >= 0)
@@ -109,16 +108,23 @@ namespace Terminal.Gui {
var buff = new BufferedStream (input);
int v;
var line = new List<byte> ();
var wasNewLine = false;
while ((v = buff.ReadByte ()) != -1) {
if (v == 13) {
continue;
}
if (v == 10) {
Append (line);
line.Clear ();
wasNewLine = true;
continue;
}
line.Add ((byte)v);
wasNewLine = false;
}
if (line.Count > 0)
if (line.Count > 0 || wasNewLine)
Append (line);
buff.Dispose ();
}
public void LoadString (ustring content)
@@ -200,7 +206,7 @@ namespace Terminal.Gui {
last = last < lines.Count ? last : lines.Count;
for (int i = first; i < last; i++) {
var line = GetLine (i);
var tabSum = line.Sum (r => r == '\t' ? tabWidth - 1 : 0);
var tabSum = line.Sum (r => r == '\t' ? Math.Max (tabWidth - 1, 0) : 0);
var l = line.Count + tabSum;
if (l > maxLength) {
maxLength = l;
@@ -230,7 +236,7 @@ namespace Terminal.Gui {
for (int i = start; i < t.Count; i++) {
var r = t [i];
size += Rune.ColumnWidth (r);
if (r == '\t' && tabWidth > 0) {
if (r == '\t') {
size += tabWidth + 1;
}
if (i == pX || (size > pX)) {
@@ -255,7 +261,7 @@ namespace Terminal.Gui {
var rune = t [i];
size += Rune.ColumnWidth (rune);
len += Rune.RuneLen (rune);
if (rune == '\t' && tabWidth > 0) {
if (rune == '\t') {
size += tabWidth + 1;
len += tabWidth - 1;
}
@@ -270,7 +276,7 @@ namespace Terminal.Gui {
{
s = Rune.ColumnWidth (r);
l = Rune.RuneLen (r);
if (r == '\t' && tWidth > 0) {
if (r == '\t') {
s += tWidth + 1;
l += tWidth - 1;
}
@@ -1126,6 +1132,7 @@ namespace Terminal.Gui {
Multiline = false;
AllowsTab = false;
}
SetNeedsDisplay ();
}
}
@@ -1143,12 +1150,10 @@ namespace Terminal.Gui {
if (allowsTab && !multiline) {
Multiline = true;
}
if (!allowsTab && multiline) {
Multiline = false;
}
if (!allowsTab && tabWidth > 0) {
tabWidth = 0;
}
SetNeedsDisplay ();
}
}
@@ -1159,12 +1164,10 @@ namespace Terminal.Gui {
get => tabWidth;
set {
tabWidth = Math.Max (value, 0);
if (tabWidth == 0 && AllowsTab) {
AllowsTab = false;
}
if (tabWidth > 0 && !AllowsTab) {
AllowsTab = true;
}
SetNeedsDisplay ();
}
}
@@ -1241,10 +1244,8 @@ namespace Terminal.Gui {
/// <param name="path">Path to the file to load.</param>
public bool LoadFile (string path)
{
if (path == null)
throw new ArgumentNullException (nameof (path));
ResetPosition ();
var res = model.LoadFile (path);
ResetPosition ();
SetNeedsDisplay ();
return res;
}
@@ -1256,10 +1257,8 @@ namespace Terminal.Gui {
/// <param name="stream">Stream to load the contents from.</param>
public void LoadStream (Stream stream)
{
if (stream == null)
throw new ArgumentNullException (nameof (stream));
ResetPosition ();
model.LoadStream (stream);
ResetPosition ();
SetNeedsDisplay ();
}
@@ -1269,8 +1268,8 @@ namespace Terminal.Gui {
/// <returns><c>true</c>, if stream was closed, <c>false</c> otherwise.</returns>
public bool CloseFile ()
{
ResetPosition ();
var res = model.CloseFile ();
ResetPosition ();
SetNeedsDisplay ();
return res;
}
@@ -1298,23 +1297,18 @@ namespace Terminal.Gui {
SetNeedsDisplay (new Rect (0, minRow, Frame.Width, maxRow));
}
var line = model.GetLine (currentRow);
var retreat = 0;
var col = 0;
if (line.Count > 0) {
retreat = Math.Max (SpecialRune (line [Math.Min (Math.Max (currentColumn - leftColumn - 1, 0), line.Count - 1)])
? 1 : 0, 0);
for (int idx = leftColumn; idx < line.Count; idx++) {
if (idx >= currentColumn)
break;
var cols = Rune.ColumnWidth (line [idx]);
if (line [idx] == '\t' && TabWidth > 0) {
if (line [idx] == '\t') {
cols += TabWidth + 1;
}
TextModel.SetCol (ref col, Frame.Width, cols);
}
}
col += retreat;
if ((col >= leftColumn || col < Frame.Width)
&& topRow <= currentRow && currentRow - topRow + BottomOffset < Frame.Height) {
ResetCursorVisibility ();
@@ -1701,10 +1695,10 @@ namespace Terminal.Gui {
&& HasFocus && idxCol < lineRuneCount) {
ColorUsed (line, idxCol);
} else {
ColorNormal (line,idxCol);
ColorNormal (line, idxCol);
}
if (rune == '\t' && TabWidth > 0) {
if (rune == '\t') {
cols += TabWidth + 1;
if (col + cols > right) {
cols = right - col;
@@ -1714,10 +1708,8 @@ namespace Terminal.Gui {
AddRune (col + i, row, ' ');
}
}
} else if (!SpecialRune (rune)) {
AddRune (col, row, rune);
} else {
col++;
AddRune (col, row, rune);
}
if (!TextModel.SetCol (ref col, bounds.Right, cols)) {
break;
@@ -1740,17 +1732,6 @@ namespace Terminal.Gui {
PositionCursor ();
}
bool SpecialRune (Rune rune)
{
switch (rune) {
case (uint)Key.Enter:
case 0xd:
return true;
default:
return false;
}
}
///<inheritdoc/>
public override bool CanFocus {
get => base.CanFocus;
@@ -1974,7 +1955,7 @@ namespace Terminal.Gui {
List<Rune> rest;
// if the user presses Left (without any control keys) and they are at the start of the text
if(kb.Key == Key.CursorLeft && currentColumn == 0 && currentRow == 0) {
if (kb.Key == Key.CursorLeft && currentColumn == 0 && currentRow == 0) {
// do not respond (this lets the key press fall through to navigation system - which usually changes focus backward)
return false;
}

View File

@@ -35,6 +35,7 @@ namespace UICatalog {
new MenuItem ("_Open", "", () => Open()),
new MenuItem ("_Save", "", () => Save()),
new MenuItem ("_Save As", "", () => SaveAs()),
new MenuItem ("_Close", "", () => CloseFile()),
null,
new MenuItem ("_Quit", "", () => Quit()),
}),
@@ -67,7 +68,10 @@ namespace UICatalog {
new MenuItem (" B_ox Fix", "", () => SetCursor(CursorVisibility.BoxFix)),
new MenuItem (" U_nderline Fix","", () => SetCursor(CursorVisibility.UnderlineFix))
}),
new MenuBarItem ("Forma_t", CreateWrapChecked ())
new MenuBarItem ("Forma_t", new MenuItem [] {
CreateWrapChecked (),
CreateAllowsTabChecked ()
})
});
Top.Add (menu);
@@ -134,8 +138,11 @@ namespace UICatalog {
Win.KeyPress += (e) => {
if (winDialog != null && (e.KeyEvent.Key == Key.Esc
|| e.KeyEvent.Key.HasFlag (Key.Q | Key.CtrlMask))) {
|| e.KeyEvent.Key == (Key.Q | Key.CtrlMask))) {
DisposeWinDialog ();
} else if (e.KeyEvent.Key == (Key.Q | Key.CtrlMask)) {
Quit ();
e.Handled = true;
}
};
}
@@ -151,9 +158,9 @@ namespace UICatalog {
{
}
private void New ()
private void New (bool checkChanges = true)
{
if (!CanCloseFile ()) {
if (checkChanges && !CanCloseFile ()) {
return;
}
@@ -166,9 +173,9 @@ namespace UICatalog {
private void LoadFile ()
{
if (_fileName != null) {
// BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
//_textView.LoadFile(_fileName);
_textView.Text = System.IO.File.ReadAllText (_fileName);
// FIXED: BUGBUG: #452 TextView.LoadFile keeps file open and provides no way of closing it
_textView.LoadFile (_fileName);
//_textView.Text = System.IO.File.ReadAllText (_fileName);
_originalText = _textView.Text.ToByteArray ();
Win.Title = _fileName;
_saved = true;
@@ -312,7 +319,7 @@ namespace UICatalog {
var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = false };
Application.Run (d);
if (!d.Canceled) {
if (!d.Canceled && d.FilePaths.Count > 0) {
_fileName = d.FilePaths [0];
LoadFile ();
}
@@ -321,7 +328,7 @@ namespace UICatalog {
private bool Save ()
{
if (_fileName != null) {
// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
// FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
// As a result files saved on Windows and then read back will show invalid chars.
return SaveFile (Win.Title.ToString (), _fileName);
} else {
@@ -359,6 +366,7 @@ namespace UICatalog {
Win.Title = title;
_fileName = file;
System.IO.File.WriteAllText (_fileName, _textView.Text.ToString ());
_originalText = _textView.Text.ToByteArray ();
_saved = true;
MessageBox.Query ("Save File", "File was successfully saved.", "Ok");
@@ -370,15 +378,33 @@ namespace UICatalog {
return true;
}
private void CloseFile ()
{
if (!CanCloseFile ()) {
return;
}
try {
_textView.CloseFile ();
New (false);
} catch (Exception ex) {
MessageBox.ErrorQuery ("Error", ex.Message, "Ok");
}
}
private void Quit ()
{
if (!CanCloseFile ()) {
return;
}
Application.RequestStop ();
}
private void CreateDemoFile (string fileName)
{
var sb = new StringBuilder ();
// BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
// FIXED: BUGBUG: #279 TextView does not know how to deal with \r\n, only \r
sb.Append ("Hello world.\n");
sb.Append ("This is a test of the Emergency Broadcast System.\n");
@@ -401,10 +427,11 @@ namespace UICatalog {
return new MenuItem [] { item };
}
private MenuItem [] CreateWrapChecked ()
private MenuItem CreateWrapChecked ()
{
var item = new MenuItem ();
item.Title = "Word Wrap";
var item = new MenuItem {
Title = "Word Wrap"
};
item.CheckType |= MenuItemCheckStyle.Checked;
item.Checked = false;
item.Action += () => {
@@ -419,7 +446,21 @@ namespace UICatalog {
}
};
return new MenuItem [] { item };
return item;
}
private MenuItem CreateAllowsTabChecked ()
{
var item = new MenuItem {
Title = "Allows Tab"
};
item.CheckType |= MenuItemCheckStyle.Checked;
item.Checked = true;
item.Action += () => {
_textView.AllowsTab = item.Checked = !item.Checked;
};
return item;
}
private void CreateFindReplace (bool isFind = true)
@@ -674,10 +715,5 @@ namespace UICatalog {
return d;
}
public override void Run ()
{
base.Run ();
}
}
}

View File

@@ -1,13 +1,19 @@
using System;
using System.Linq;
using System.Reflection;
using Xunit;
using Xunit.Abstractions;
namespace Terminal.Gui.Views {
public class TextViewTests {
private static TextView _textView;
readonly ITestOutputHelper output;
// This class enables test functions annoated with the [InitShutdown] attribute
public TextViewTests (ITestOutputHelper output)
{
this.output = output;
}
// This class enables test functions annotated with the [InitShutdown] attribute
// to have a function called before the test function is called and after.
//
// This is necessary because a) Application is a singleton and Init/Shutdown must be called
@@ -42,7 +48,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Changing_Selection_Or_CursorPosition_Update_SelectedLength_And_SelectedText ()
{
_textView.SelectionStartColumn = 2;
@@ -58,7 +65,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("B to jump between ", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Selection_With_Value_Less_Than_Zero_Changes_To_Zero ()
{
_textView.SelectionStartColumn = -2;
@@ -69,7 +77,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Selection_With_Value_Greater_Than_Text_Length_Changes_To_Text_Length ()
{
_textView.CursorPosition = new Point (2, 0);
@@ -81,7 +90,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("B to jump between text fields.", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Selection_With_Empty_Text ()
{
_textView = new TextView ();
@@ -94,7 +104,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Selection_And_CursorPosition_With_Value_Greater_Than_Text_Length_Changes_Both_To_Text_Length ()
{
_textView.CursorPosition = new Point (33, 2);
@@ -108,7 +119,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void CursorPosition_With_Value_Less_Than_Zero_Changes_To_Zero ()
{
_textView.CursorPosition = new Point (-1, -1);
@@ -118,7 +130,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void CursorPosition_With_Value_Greater_Than_Text_Length_Changes_To_Text_Length ()
{
_textView.CursorPosition = new Point (33, 1);
@@ -128,7 +141,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordForward_With_No_Selection ()
{
_textView.CursorPosition = new Point (0, 0);
@@ -190,7 +204,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordBackward_With_No_Selection ()
{
_textView.CursorPosition = new Point (_textView.Text.Length, 0);
@@ -252,7 +267,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordForward_With_Selection ()
{
_textView.CursorPosition = new Point (0, 0);
@@ -316,7 +332,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordBackward_With_Selection ()
{
_textView.CursorPosition = new Point (_textView.Text.Length, 0);
@@ -380,7 +397,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordForward_With_The_Same_Values_For_SelectedStart_And_CursorPosition_And_Not_Starting_At_Beginning_Of_The_Text ()
{
_textView.CursorPosition = new Point (10, 0);
@@ -428,7 +446,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordBackward_With_The_Same_Values_For_SelectedStart_And_CursorPosition_And_Not_Starting_At_Beginning_Of_The_Text ()
{
_textView.CursorPosition = new Point (10, 0);
@@ -468,7 +487,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordForward_With_No_Selection_And_With_More_Than_Only_One_Whitespace_And_With_Only_One_Letter ()
{
// 1 2 3 4 5
@@ -565,7 +585,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordBackward_With_No_Selection_And_With_More_Than_Only_One_Whitespace_And_With_Only_One_Letter ()
{
// 1 2 3 4 5
@@ -670,7 +691,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordBackward_Multiline_With_Selection ()
{
// 4 3 2 1
@@ -784,7 +806,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void WordForward_Multiline_With_Selection ()
{
// 1 2 3 4
@@ -897,7 +920,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_To_End_Delete_Forwards_And_Copy_To_The_Clipboard ()
{
_textView.Text = "This is the first line.\nThis is the second line.";
@@ -932,7 +956,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_To_Start_Delete_Backwards_And_Copy_To_The_Clipboard ()
{
_textView.Text = "This is the first line.\nThis is the second line.";
@@ -968,7 +993,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_Delete_WordForward ()
{
_textView.Text = "This is the first line.";
@@ -1011,7 +1037,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_Delete_WordBackward ()
{
_textView.Text = "This is the first line.";
@@ -1055,7 +1082,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_Delete_WordForward_Multiline ()
{
_textView.Text = "This is the first line.\nThis is the second line.";
@@ -1134,7 +1162,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Kill_Delete_WordBackward_Multiline ()
{
_textView.Text = "This is the first line.\nThis is the second line.";
@@ -1213,7 +1242,8 @@ namespace Terminal.Gui.Views {
}
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Copy_Or_Cut_Null_If_No_Selection ()
{
_textView.SelectionStartColumn = 0;
@@ -1224,7 +1254,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Copy_Or_Cut_Not_Null_If_Has_Selection ()
{
_textView.SelectionStartColumn = 20;
@@ -1236,7 +1267,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Copy_Or_Cut_And_Paste_With_Selection ()
{
_textView.SelectionStartColumn = 20;
@@ -1254,7 +1286,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("TAB to jump between text fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Copy_Or_Cut_And_Paste_With_No_Selection ()
{
_textView.SelectionStartColumn = 20;
@@ -1282,7 +1315,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("TAB to jump between texttext fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Cut_Not_Allowed_If_ReadOnly_Is_True ()
{
_textView.ReadOnly = true;
@@ -1302,7 +1336,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Paste_Always_Clear_The_SelectedText ()
{
_textView.SelectionStartColumn = 20;
@@ -1314,7 +1349,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("", _textView.SelectedText);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void TextChanged_Event ()
{
_textView.TextChanged += () => {
@@ -1328,7 +1364,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("changed", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Used_Is_True_By_Default ()
{
_textView.CursorPosition = new Point (10, 0);
@@ -1343,7 +1380,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("TAB to jumusedp between text fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Used_Is_False ()
{
_textView.Used = false;
@@ -1359,7 +1397,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("TAB to jumusedtween text fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Copy_Without_Selection ()
{
_textView.Text = "This is the first line.\nThis is the second line.\n";
@@ -1377,8 +1416,9 @@ namespace Terminal.Gui.Views {
Assert.Equal (new Point (3, 3), _textView.CursorPosition);
}
[Fact][InitShutdown]
public void TabWidth_Setting_To_Zero_Changes_AllowsTab_To_False_If_True ()
[Fact]
[InitShutdown]
public void TabWidth_Setting_To_Zero_Keeps_AllowsTab ()
{
Assert.Equal (4, _textView.TabWidth);
Assert.True (_textView.AllowsTab);
@@ -1386,23 +1426,24 @@ namespace Terminal.Gui.Views {
Assert.True (_textView.Multiline);
_textView.TabWidth = -1;
Assert.Equal (0, _textView.TabWidth);
Assert.False (_textView.AllowsTab);
Assert.False (_textView.AllowsReturn);
Assert.False (_textView.Multiline);
Assert.True (_textView.AllowsTab);
Assert.True (_textView.AllowsReturn);
Assert.True (_textView.Multiline);
_textView.ProcessKey (new KeyEvent (Key.Tab, new KeyModifiers ()));
Assert.Equal ("TAB to jump between text fields.", _textView.Text);
Assert.Equal ("\tTAB to jump between text fields.", _textView.Text);
_textView.ProcessKey (new KeyEvent (Key.BackTab, new KeyModifiers ()));
Assert.Equal ("TAB to jump between text fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void AllowsTab_Setting_To_True_Changes_TabWidth_To_Default_If_It_Is_Zero ()
{
_textView.TabWidth = 0;
Assert.Equal (0, _textView.TabWidth);
Assert.False (_textView.AllowsTab);
Assert.False (_textView.AllowsReturn);
Assert.False (_textView.Multiline);
Assert.True (_textView.AllowsTab);
Assert.True (_textView.AllowsReturn);
Assert.True (_textView.Multiline);
_textView.AllowsTab = true;
Assert.True (_textView.AllowsTab);
Assert.Equal (4, _textView.TabWidth);
@@ -1410,7 +1451,8 @@ namespace Terminal.Gui.Views {
Assert.True (_textView.Multiline);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void AllowsReturn_Setting_To_True_Changes_Multiline_To_True_If_It_Is_False ()
{
Assert.True (_textView.AllowsReturn);
@@ -1431,7 +1473,8 @@ namespace Terminal.Gui.Views {
"TAB to jump between text fields.", _textView.Text);
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Multiline_Setting_Changes_AllowsReturn_And_AllowsTab_And_Height ()
{
Assert.True (_textView.Multiline);
@@ -1458,7 +1501,8 @@ namespace Terminal.Gui.Views {
Assert.Equal ("Dim.Absolute(10)", _textView.Height.ToString ());
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Tab_Test_Follow_By_BackTab ()
{
Application.Top.Add (_textView);
@@ -1493,7 +1537,8 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void BackTab_Test_Follow_By_Tab ()
{
Application.Top.Add (_textView);
@@ -1535,7 +1580,8 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight ()
{
Application.Top.Add (_textView);
@@ -1577,7 +1623,8 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Tab_Test_Follow_By_BackTab_With_Text ()
{
Application.Top.Add (_textView);
@@ -1612,7 +1659,8 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Tab_Test_Follow_By_Home_And_Then_Follow_By_End_And_Then_Follow_By_BackTab_With_Text ()
{
Application.Top.Add (_textView);
@@ -1669,7 +1717,8 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact][InitShutdown]
[Fact]
[InitShutdown]
public void Tab_Test_Follow_By_CursorLeft_And_Then_Follow_By_CursorRight_With_Text ()
{
Application.Top.Add (_textView);
@@ -1712,6 +1761,20 @@ namespace Terminal.Gui.Views {
Application.Run ();
}
[Fact]
public void TextView_MultiLine_But_Without_Tabs ()
{
var view = new TextView ();
// the default for TextView
Assert.True (view.Multiline);
view.AllowsTab = false;
Assert.False (view.AllowsTab);
Assert.True (view.Multiline);
}
private int GetLeftCol (int start)
{
var lines = _textView.Text.Split (Environment.NewLine);
@@ -1751,5 +1814,133 @@ namespace Terminal.Gui.Views {
return col;
}
[Fact]
public void LoadFile_Throws_If_File_Is_Null ()
{
var tv = new TextView ();
Assert.Throws<ArgumentNullException> (() => tv.LoadFile (null));
}
[Fact]
public void LoadFile_Throws_If_File_Is_Empty ()
{
var tv = new TextView ();
Assert.Throws<ArgumentException> (() => tv.LoadFile (""));
}
[Fact]
public void LoadFile_Throws_If_File_Not_Exist ()
{
var tv = new TextView ();
Assert.Throws<System.IO.FileNotFoundException> (() => tv.LoadFile ("blabla"));
}
[Fact]
public void LoadStream_Throws_If_Stream_Is_Null ()
{
var tv = new TextView ();
Assert.Throws<ArgumentNullException> (() => tv.LoadStream (null));
}
[Fact]
public void LoadStream_Stream_Is_Empty ()
{
var tv = new TextView ();
tv.LoadStream (new System.IO.MemoryStream ());
Assert.Equal ("", tv.Text);
}
[Fact]
public void LoadStream_CRLF ()
{
var text = "This is the first line.\r\nThis is the second line.\r\n";
var tv = new TextView ();
tv.LoadStream (new System.IO.MemoryStream (System.Text.Encoding.ASCII.GetBytes (text)));
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
}
[Fact]
public void LoadStream_LF ()
{
var text = "This is the first line.\nThis is the second line.\n";
var tv = new TextView ();
tv.LoadStream (new System.IO.MemoryStream (System.Text.Encoding.ASCII.GetBytes (text)));
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
}
[Fact]
public void StringToRunes_Slipts_CRLF ()
{
var text = "This is the first line.\r\nThis is the second line.\r\n";
var tv = new TextView ();
tv.Text = text;
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
}
[Fact]
public void StringToRunes_Slipts_LF ()
{
var text = "This is the first line.\nThis is the second line.\n";
var tv = new TextView ();
tv.Text = text;
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
}
[Fact]
public void CloseFile_Throws_If_FilePath_Is_Null ()
{
var tv = new TextView ();
Assert.Throws<ArgumentNullException> (() => tv.CloseFile ());
}
[Fact]
public void WordWrap_Gets_Sets ()
{
var tv = new TextView () { WordWrap = true };
Assert.True (tv.WordWrap);
tv.WordWrap = false;
Assert.False (tv.WordWrap);
}
[Fact]
public void WordWrap_True_Text_Always_Returns_Unwrapped ()
{
var text = "This is the first line.\nThis is the second line.\n";
var tv = new TextView () { Width = 10 };
tv.Text = text;
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
tv.WordWrap = true;
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
}
[Fact]
[InitShutdown]
public void WordWrap_WrapModel_Output ()
{
// 0123456789
var text = "This is the first line.\nThis is the second line.\n";
var tv = new TextView () { Width = 10, Height = 10 };
tv.Text = text;
Assert.Equal ($"This is the first line.{Environment.NewLine}This is the second line.{Environment.NewLine}", tv.Text);
tv.WordWrap = true;
Application.Top.Add (tv);
tv.Redraw (tv.Bounds);
string expected = @"
This is
the
first
line.
This is
the
second
line.
";
GraphViewTests.AssertDriverContentsAre (expected, output);
}
}
}