mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-27 00:07:58 +01:00
* Investigating new file dialog * Column sorting * Add navigationStack * Append autocomplete half working * Change autocomplete append to use draw effect instead of selection effect * WIP on FileDialog2 * Refactor sort order and add more 'ls' colors * Refactor history to its own class * FileDialog2 navigation fixes/improvements * Added centered Title * Add tree view and split container * Add FileDialogState * Add AllowsMultipleSelection * Add result fields and Scenario * Added FileDialo2 test file * Fix FileDialog2 Redraw padding to respect max/min view bounds * Fix unit tests and warnings * Started on better keyboard navigation in FileDialog2 * Update to match new SplitContainer API * Quality of Life improvements * Fix recommending parent folder * Remove border from SplitContainer in FileDialog2 and fixed tests * Bugfixes and improvements to FileDialog2 * usability improvements to FileDialog2 * Add multi select and OpenMode * Enforce OpenMode when making a multi selection * Prevent typing illegal characters * Added AllowedTypes to FileDialog2 * Added combo box filter AllowedType * Improve code readability by reordering members * Do not update FileDialog2 text box when selecting ".." in TableView * Fix history navigation in FileDialog2 * Restore selection after navigating backwards in history * Add FileDialog2 tests * Make FileDialog2 Title user configurable * Fix DirectTyping_Allowed unit test when running on linux * Change Home/End to go to first/last cell in table in FileDialog2 * Remove overloaded Title property * Switch to `ustring.IsNullOrEmpty` * Update to latest TileView API * Add TableView navigation by letter using CollectionNavigator * Fix recreating search navigator too often * Add tests for proper disposing * Make Ctrl+F10 toggle split line focusability * Fix layout bug in first tile when orientation is horizontal * Switch to GenerateImage * Fix not calling base constructor * Revert "Merges latest LineCanvas into TileView" * Fix keyboard tab navigation problems * Workaround for changing CanFocus throwing Exceptions sometimes * Update to latest splitcontainer API * Adjust suggestions to be gray and properly update on keystrokes * Move ok and cancel to bottom * Add MustExist and fix multi selection of 1 result * bugfixes and quality of life * Navigating to .. clears path up to current dir * Better arrow key navigation * Make title pretty and informative * Fix test * Fix test * Trim default Titles to be more compact and readable * Fix bad merge changes * Remove EscSeqReq files that are not in v2... came from develop?! * Fix nullable and enable toggle select on table view * Fix multi select return value * Add icon and monochrome support * Add search elements * Add search for current directory * WIP: Async search * Thread safety and disposal * Improve UX * Fix for rapid search results * Fix warnings and whitespace * Don't add more than 10000 search results * Add support for adjusting search matching * Added ISearchMatcher example to FileDialog2Example * Remove double spaces after periods * Make MaxSearchResults a config setting * Localization for FileDialog2 * Fix build error * Support for custom open button Text * Improve file dialog scenario UX * Change feedback to a drawing effect in center of screen * Explore MenuBar instead of ComboBox for AllowedTypes * Fix prompt and move file open into try/catch for errors reading files * Open menu when tabbed to * FileDialog2 improvements - Expose table/tree style properties - Rename Monochrome to UseColors and default to false - IconGetter no longer forces space - On Windows in Scenario just use a backslash for folder icon (i.e. not unicode) - * Add style settings in scenario and make autocomplete case insensitive on Windows * Move ok button text to Style * xmldoc * Remove old FileDialog and re-wire OpenDialog and SaveDialog to use FileDialog2 base * localization * Move open/save dialog to their own files * Rename FileDialog2 to FileDialog * Fix repetition in string * Add IAllowedType * Get rid of AllowedTypesIsStrict User now adds the `IAllowedType` implementation `AllowedTypeAny` * Add max length to AllowedType ToString * Pressing Enter in find restarts search instead of confirm selection * Add TreeRootGetter for customizing the quick access items in FileDialog * Add FilesSelected event Allows user to do things like confirm dialogs on selecting existing file(s) * Update to new sender, event args signature * Fix naming on MouseEventArgs * Fix mouse events naming * Revert "Fix naming on MouseEventArgs" This reverts commit2f557f52d9. * Add deletion support * Move delete keybinding to tableview * Scaffold for rename and new operations * Prevent delete dialog popping up again on cancel * Add rename and new folder implementations * Add rename,delete,new to context menu * On rename or new, reselect the file in its new location in tree * Support searching on multiple terms * Localization support for new/rename/delete * Refactor internal classes and add class diagram * Move some visual properties to FileDialogStyle * Ensure MultiSelected is never null and always contains Path if relevant * Fix spacing/indentation * WIP: Add new namespace Terminal.Gui.FileServices * Improve appearance of back/forward/up * Move SpinnerLabel to Views * Add SpinnerView * Code formatting * Add AutoSpin test * Avoid ever removing spinner timeout twice * Make SpinnerView show/hide instead of stopping * WIP: Refactor to use 3 sub PRs - SpinnerView - Suggest Append Autocomplete - Caption TextField * Add FilepathSuggestionGenerator * WIP: FileDialog autocomplete append mostly working again * Improve file autocomplete * Move IconGetter to Style and provide default implementation - Depends on `UseUnicodeCharacters` - Also updated up/back/collapse/expand tree to use spicier icons * Fix failing unit test * Improved colors and layout * Adjust use of unicode * Fix UseUnicodeCharacters * Update table style to include scroll indicators and lines * Fix cycle suggestion with down cursor * Adjust sort indicators * Add default sort order on isDir then name * Always use left/right unicode arrows * Fix autocomplete suggesting in empty textbox * Press escape to cancel ongoing search (when search box is focused) * When entering a TreeView if there is no selection then select first object * Move CursorIsAtEnd to TextField * Improve layout * Change UseColors to be a cell color fill * Fxied tests for new apis * Remove manual title drawing code * Fix MoveEnd name conflicting with base class * Fix merge conflicts * Switched to IFileSystem for unit testing * Add unit test * Revert "Fix MoveEnd name conflicting with base class" This reverts commita5f9c07022. * Fix MoveEnd name collision with 'new' keyword * Fixed tree not toggling * DateTime fixes and mocking * Fix TestDirectoryContents_Windows * Expose UseColors and UseUnicodeCharacters as config settings * Fix linter settings having removed curly brackets * Fix namespace on test * Move tests to file services folder * Remove the FileServices namespace * Updated class diagram * Clear title from tests for futureproofing * Localization support for FileDialog title * Remove trailing whitespace in "open existing" * Fix listing suggestions immediately after folder path entered --------- Co-authored-by: Tig <tig@users.noreply.github.com>
317 lines
12 KiB
C#
317 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO.Abstractions.TestingHelpers;
|
|
using System.Linq;
|
|
using Terminal.Gui;
|
|
using Xunit;
|
|
using Xunit.Abstractions;
|
|
|
|
namespace Terminal.Gui.FileServicesTests {
|
|
public class FileDialogTests {
|
|
|
|
readonly ITestOutputHelper output;
|
|
|
|
public FileDialogTests (ITestOutputHelper output)
|
|
{
|
|
this.output = output;
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void OnLoad_TextBoxIsFocused ()
|
|
{
|
|
var dlg = GetInitializedFileDialog ();
|
|
|
|
var tf = dlg.Subviews.FirstOrDefault (t => t.HasFocus);
|
|
Assert.NotNull (tf);
|
|
Assert.IsType<TextField> (tf);
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void DirectTyping_Allowed ()
|
|
{
|
|
var dlg = GetInitializedFileDialog ();
|
|
var tf = dlg.Subviews.OfType<TextField> ().First (t => t.HasFocus);
|
|
tf.ClearAllSelection ();
|
|
tf.CursorPosition = tf.Text.Length;
|
|
Assert.True (tf.HasFocus);
|
|
|
|
SendSlash ();
|
|
|
|
Assert.Equal (
|
|
new DirectoryInfo (Environment.CurrentDirectory + Path.DirectorySeparatorChar).FullName,
|
|
new DirectoryInfo (dlg.Path + Path.DirectorySeparatorChar).FullName
|
|
);
|
|
|
|
// continue typing the rest of the path
|
|
Send ("bob");
|
|
Send ('.', ConsoleKey.OemPeriod, false);
|
|
Send ("csv");
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
Send ('\n', ConsoleKey.Enter, false);
|
|
Assert.False (dlg.Canceled);
|
|
Assert.Equal ("bob.csv", Path.GetFileName (dlg.Path));
|
|
}
|
|
|
|
private void SendSlash ()
|
|
{
|
|
if (Path.DirectorySeparatorChar == '/') {
|
|
Send ('/', ConsoleKey.Separator, false);
|
|
} else {
|
|
Send ('\\', ConsoleKey.Separator, false);
|
|
}
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void DirectTyping_AutoComplete ()
|
|
{
|
|
var dlg = GetInitializedFileDialog ();
|
|
var openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
|
|
Directory.CreateDirectory (openIn);
|
|
|
|
var expectedDest = Path.Combine (openIn, "xx");
|
|
Directory.CreateDirectory (expectedDest);
|
|
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
Send ("x");
|
|
|
|
// nothing selected yet
|
|
Assert.True (dlg.Canceled);
|
|
Assert.Equal ("x", Path.GetFileName (dlg.Path));
|
|
|
|
// complete auto typing
|
|
Send ('\t', ConsoleKey.Tab, false);
|
|
|
|
// but do not close dialog
|
|
Assert.True (dlg.Canceled);
|
|
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
|
|
|
|
// press enter again to confirm the dialog
|
|
Send ('\n', ConsoleKey.Enter, false);
|
|
Assert.False (dlg.Canceled);
|
|
Assert.EndsWith ("xx" + Path.DirectorySeparatorChar, dlg.Path);
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void DoNotConfirmSelectionWhenFindFocused ()
|
|
{
|
|
var dlg = GetInitializedFileDialog ();
|
|
var openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
Directory.CreateDirectory (openIn);
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
Send ('f', ConsoleKey.F, false, false, true);
|
|
|
|
Assert.IsType<TextField> (dlg.MostFocused);
|
|
var tf = (TextField)dlg.MostFocused;
|
|
Assert.Equal ("Enter Search", tf.Caption);
|
|
|
|
// Dialog has not yet been confirmed with a choice
|
|
Assert.True (dlg.Canceled);
|
|
|
|
//pressing enter while search focused should not confirm path
|
|
Send ('\n', ConsoleKey.Enter, false);
|
|
|
|
Assert.True (dlg.Canceled);
|
|
|
|
// tabbing out of search
|
|
Send ('\t', ConsoleKey.Tab, false);
|
|
|
|
//should allow enter to confirm path
|
|
Send ('\n', ConsoleKey.Enter, false);
|
|
|
|
// Dialog has not yet been confirmed with a choice
|
|
Assert.False (dlg.Canceled);
|
|
}
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void TestDirectoryContents_Linux ()
|
|
{
|
|
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform (System.Runtime.InteropServices.OSPlatform.Windows)) {
|
|
// Cannot run test except on linux :(
|
|
// See: https://github.com/TestableIO/System.IO.Abstractions/issues/800
|
|
return;
|
|
}
|
|
|
|
// Arrange
|
|
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), "/");
|
|
fileSystem.MockTime (() => new DateTime (2010, 01, 01, 11, 12, 43));
|
|
|
|
fileSystem.AddFile (@"/myfile.txt", new MockFileData ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) });
|
|
fileSystem.AddFile (@"/demo/jQuery.js", new MockFileData ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) });
|
|
fileSystem.AddFile (@"/demo/image.gif", new MockFileData (new byte [] { 0x12, 0x34, 0x56, 0xd2 }) { LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10) });
|
|
|
|
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"/demo/subfolder");
|
|
m.Create ();
|
|
m.LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10);
|
|
|
|
fileSystem.AddFile (@"/demo/subfolder/image2.gif", new MockFileData (new byte [] { 0x12, 0x34, 0x56, 0xd2 }) { LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10) });
|
|
|
|
var fd = new FileDialog (fileSystem) {
|
|
Height = 15
|
|
};
|
|
fd.Path = @"/demo/";
|
|
Begin (fd);
|
|
fd.Title = string.Empty;
|
|
|
|
fd.Redraw (fd.Bounds);
|
|
|
|
fd.Style.DateFormat = "yyyy-MM-dd hh:mm:ss";
|
|
|
|
string expected =
|
|
@"
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
│/demo/ │
|
|
│[▲] │
|
|
│┌────────────┬──────────┬──────────────────────────────┬─────────┐│
|
|
││Filename (▲)│Size │Modified │Type ││
|
|
│├────────────┼──────────┼──────────────────────────────┼─────────┤│
|
|
││.. │ │ │dir ││
|
|
││\subfolder │ │2002-01-01T22:42:10 │dir ││
|
|
││image.gif │4.00 bytes│2002-01-01T22:42:10 │.gif ││
|
|
││jQuery.js │7.00 bytes│2001-01-01T11:44:42 │.js ││
|
|
│ │
|
|
│ │
|
|
│ │
|
|
│[ ►► ] Enter Search [ Cancel ] [ Ok ] │
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
";
|
|
TestHelpers.AssertDriverContentsAre (expected, output, true);
|
|
}
|
|
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void TestDirectoryContents_Windows ()
|
|
{
|
|
if (!System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform (System.Runtime.InteropServices.OSPlatform.Windows)) {
|
|
// Can only run this test on windows :(
|
|
// See: https://github.com/TestableIO/System.IO.Abstractions/issues/800
|
|
return;
|
|
}
|
|
// Arrange
|
|
var fileSystem = new MockFileSystem (new Dictionary<string, MockFileData> (), @"c:\");
|
|
fileSystem.MockTime (() => new DateTime (2010, 01, 01, 11, 12, 43));
|
|
|
|
fileSystem.AddFile (@"c:\myfile.txt", new MockFileData ("Testing is meh.") { LastWriteTime = new DateTime (2001, 01, 01, 11, 12, 11) });
|
|
fileSystem.AddFile (@"c:\demo\jQuery.js", new MockFileData ("some js") { LastWriteTime = new DateTime (2001, 01, 01, 11, 44, 42) });
|
|
fileSystem.AddFile (@"c:\demo\image.gif", new MockFileData (new byte [] { 0x12, 0x34, 0x56, 0xd2 }) { LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10) });
|
|
|
|
var m = (MockDirectoryInfo)fileSystem.DirectoryInfo.New (@"c:\demo\subfolder");
|
|
m.Create ();
|
|
m.LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10);
|
|
|
|
fileSystem.AddFile (@"c:\demo\subfolder\image2.gif", new MockFileData (new byte [] { 0x12, 0x34, 0x56, 0xd2 }) { LastWriteTime = new DateTime (2002, 01, 01, 22, 42, 10) });
|
|
|
|
var fd = new FileDialog (fileSystem) {
|
|
Height = 15
|
|
};
|
|
fd.Path = @"c:\demo\";
|
|
Begin (fd);
|
|
fd.Title = string.Empty;
|
|
|
|
fd.Redraw (fd.Bounds);
|
|
|
|
fd.Style.DateFormat = "yyyy-MM-dd hh:mm:ss";
|
|
|
|
string expected =
|
|
@"
|
|
┌──────────────────────────────────────────────────────────────────┐
|
|
│c:\demo\ │
|
|
│[▲] │
|
|
│┌────────────┬──────────┬──────────────────────────────┬─────────┐│
|
|
││Filename (▲)│Size │Modified │Type ││
|
|
│├────────────┼──────────┼──────────────────────────────┼─────────┤│
|
|
││.. │ │ │dir ││
|
|
││\subfolder │ │2002-01-01T22:42:10 │dir ││
|
|
││image.gif │4.00 bytes│2002-01-01T22:42:10 │.gif ││
|
|
││jQuery.js │7.00 bytes│2001-01-01T11:44:42 │.js ││
|
|
│ │
|
|
│ │
|
|
│ │
|
|
│[ ►► ] Enter Search [ Cancel ] [ Ok ] │
|
|
└──────────────────────────────────────────────────────────────────┘
|
|
";
|
|
TestHelpers.AssertDriverContentsAre (expected, output, true);
|
|
}
|
|
|
|
[Theory, AutoInitShutdown]
|
|
[InlineData (true)]
|
|
[InlineData (false)]
|
|
public void CancelSelection (bool cancel)
|
|
{
|
|
var dlg = GetInitializedFileDialog ();
|
|
var openIn = Path.Combine (Environment.CurrentDirectory, "zz");
|
|
Directory.CreateDirectory (openIn);
|
|
dlg.Path = openIn + Path.DirectorySeparatorChar;
|
|
|
|
dlg.FilesSelected += (s, e) => e.Cancel = cancel;
|
|
|
|
//pressing enter will complete the current selection
|
|
// unless the event cancels the confirm
|
|
Send ('\n', ConsoleKey.Enter, false);
|
|
|
|
Assert.Equal (cancel, dlg.Canceled);
|
|
}
|
|
|
|
private void Send (char ch, ConsoleKey ck, bool shift = false, bool alt = false, bool control = false)
|
|
{
|
|
Application.Driver.SendKeys (ch, ck, shift, alt, control);
|
|
}
|
|
private void Send (string chars)
|
|
{
|
|
foreach (var ch in chars) {
|
|
Application.Driver.SendKeys (ch, ConsoleKey.NoName, false, false, false);
|
|
}
|
|
|
|
}
|
|
/*
|
|
[Fact, AutoInitShutdown]
|
|
public void Autocomplete_NoSuggestion_WhenTextMatchesExactly ()
|
|
{
|
|
var tb = new TextFieldWithAppendAutocomplete ();
|
|
ForceFocus (tb);
|
|
|
|
tb.Text = "/bob/fish";
|
|
tb.CursorPosition = tb.Text.Length;
|
|
tb.GenerateSuggestions (null, "fish", "fishes");
|
|
|
|
// should not report success for autocompletion because we already have that exact
|
|
// string
|
|
Assert.False (tb.AcceptSelectionIfAny ());
|
|
}
|
|
|
|
|
|
[Fact, AutoInitShutdown]
|
|
public void Autocomplete_AcceptSuggstion ()
|
|
{
|
|
var tb = new TextFieldWithAppendAutocomplete ();
|
|
ForceFocus (tb);
|
|
|
|
tb.Text = @"/bob/fi";
|
|
tb.CursorPosition = tb.Text.Length;
|
|
tb.GenerateSuggestions (null, "fish", "fishes");
|
|
|
|
Assert.True (tb.AcceptSelectionIfAny ());
|
|
Assert.Equal (@"/bob/fish", tb.Text);
|
|
}*/
|
|
|
|
|
|
private FileDialog GetInitializedFileDialog ()
|
|
{
|
|
var dlg = new FileDialog ();
|
|
Begin (dlg);
|
|
|
|
return dlg;
|
|
}
|
|
private void Begin (FileDialog dlg)
|
|
{
|
|
dlg.BeginInit ();
|
|
dlg.EndInit ();
|
|
Application.Begin (dlg);
|
|
}
|
|
}
|
|
} |