mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Fixes #4243 - ConsoleDriverFacade.CreateClipboard now honors FakeDriver.FakeBehaviors.UseFakeClipboard (#4244)
* updatd ConsoleDriverFacade.CreateClipboard to honor FakeDriver.FakeBehaviors.UseFakeClipboard * Code cleanup of fake driver v2
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
using System.Diagnostics;
|
#nullable enable
|
||||||
|
|
||||||
namespace Terminal.Gui.App;
|
namespace Terminal.Gui.App;
|
||||||
|
|
||||||
/// <summary>Provides cut, copy, and paste support for the OS clipboard.</summary>
|
/// <summary>Provides cut, copy, and paste support for the OS clipboard.</summary>
|
||||||
@@ -20,10 +19,10 @@ namespace Terminal.Gui.App;
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public static class Clipboard
|
public static class Clipboard
|
||||||
{
|
{
|
||||||
private static string _contents = string.Empty;
|
private static string? _contents = string.Empty;
|
||||||
|
|
||||||
/// <summary>Gets (copies from) or sets (pastes to) the contents of the OS clipboard.</summary>
|
/// <summary>Gets (copies from) or sets (pastes to) the contents of the OS clipboard.</summary>
|
||||||
public static string Contents
|
public static string? Contents
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
@@ -31,13 +30,8 @@ public static class Clipboard
|
|||||||
{
|
{
|
||||||
if (IsSupported)
|
if (IsSupported)
|
||||||
{
|
{
|
||||||
string clipData = Application.Driver?.Clipboard.GetClipboardData ();
|
// throw new InvalidOperationException ($"{Application.Driver?.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
|
||||||
|
string? clipData = Application.Driver?.Clipboard?.GetClipboardData () ?? string.Empty;
|
||||||
if (clipData is null)
|
|
||||||
{
|
|
||||||
// throw new InvalidOperationException ($"{Application.Driver?.GetType ().Name}.GetClipboardData returned null instead of string.Empty");
|
|
||||||
clipData = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
_contents = clipData;
|
_contents = clipData;
|
||||||
}
|
}
|
||||||
@@ -55,12 +49,9 @@ public static class Clipboard
|
|||||||
{
|
{
|
||||||
if (IsSupported)
|
if (IsSupported)
|
||||||
{
|
{
|
||||||
if (value is null)
|
value ??= string.Empty;
|
||||||
{
|
|
||||||
value = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.Driver?.Clipboard.SetClipboardData (value);
|
Application.Driver?.Clipboard?.SetClipboardData (value);
|
||||||
}
|
}
|
||||||
|
|
||||||
_contents = value;
|
_contents = value;
|
||||||
@@ -74,126 +65,5 @@ public static class Clipboard
|
|||||||
|
|
||||||
/// <summary>Returns true if the environmental dependencies are in place to interact with the OS clipboard.</summary>
|
/// <summary>Returns true if the environmental dependencies are in place to interact with the OS clipboard.</summary>
|
||||||
/// <remarks></remarks>
|
/// <remarks></remarks>
|
||||||
public static bool IsSupported => Application.Driver?.Clipboard.IsSupported ?? false;
|
public static bool IsSupported => Application.Driver?.Clipboard?.IsSupported ?? false;
|
||||||
|
}
|
||||||
/// <summary>Copies the _contents of the OS clipboard to <paramref name="result"/> if possible.</summary>
|
|
||||||
/// <param name="result">The _contents of the OS clipboard if successful, <see cref="string.Empty"/> if not.</param>
|
|
||||||
/// <returns><see langword="true"/> the OS clipboard was retrieved, <see langword="false"/> otherwise.</returns>
|
|
||||||
public static bool TryGetClipboardData (out string result)
|
|
||||||
{
|
|
||||||
if (IsSupported && Application.Driver!.Clipboard.TryGetClipboardData (out result))
|
|
||||||
{
|
|
||||||
_contents = result;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = string.Empty;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Pastes the <paramref name="text"/> to the OS clipboard if possible.</summary>
|
|
||||||
/// <param name="text">The text to paste to the OS clipboard.</param>
|
|
||||||
/// <returns><see langword="true"/> the OS clipboard was set, <see langword="false"/> otherwise.</returns>
|
|
||||||
public static bool TrySetClipboardData (string text)
|
|
||||||
{
|
|
||||||
if (IsSupported && Application.Driver!.Clipboard.TrySetClipboardData (text))
|
|
||||||
{
|
|
||||||
_contents = text;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper class for console drivers to invoke shell commands to interact with the clipboard. Used primarily by
|
|
||||||
/// CursesDriver, but also used in Unit tests which is why it is in IConsoleDriver.cs.
|
|
||||||
/// </summary>
|
|
||||||
internal static class ClipboardProcessRunner
|
|
||||||
{
|
|
||||||
public static (int exitCode, string result) Bash (
|
|
||||||
string commandLine,
|
|
||||||
string inputText = "",
|
|
||||||
bool waitForOutput = false
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var arguments = $"-c \"{commandLine}\"";
|
|
||||||
(int exitCode, string result) = Process ("bash", arguments, inputText, waitForOutput);
|
|
||||||
|
|
||||||
return (exitCode, result.TrimEnd ());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool DoubleWaitForExit (this Process process)
|
|
||||||
{
|
|
||||||
bool result = process.WaitForExit (500);
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
process.WaitForExit ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool FileExists (this string value) { return !string.IsNullOrEmpty (value) && !value.Contains ("not found"); }
|
|
||||||
|
|
||||||
public static (int exitCode, string result) Process (
|
|
||||||
string cmd,
|
|
||||||
string arguments,
|
|
||||||
string input = null,
|
|
||||||
bool waitForOutput = true
|
|
||||||
)
|
|
||||||
{
|
|
||||||
var output = string.Empty;
|
|
||||||
|
|
||||||
using (var process = new Process
|
|
||||||
{
|
|
||||||
StartInfo = new()
|
|
||||||
{
|
|
||||||
FileName = cmd,
|
|
||||||
Arguments = arguments,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
RedirectStandardInput = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
CreateNoWindow = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
{
|
|
||||||
TaskCompletionSource<bool> eventHandled = new ();
|
|
||||||
process.Start ();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (input))
|
|
||||||
{
|
|
||||||
process.StandardInput.Write (input);
|
|
||||||
process.StandardInput.Close ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process.WaitForExit (5000))
|
|
||||||
{
|
|
||||||
var timeoutError =
|
|
||||||
$@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
|
|
||||||
|
|
||||||
throw new TimeoutException (timeoutError);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (waitForOutput && process.StandardOutput.Peek () != -1)
|
|
||||||
{
|
|
||||||
output = process.StandardOutput.ReadToEnd ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.ExitCode > 0)
|
|
||||||
{
|
|
||||||
output = $@"Process failed to run. Command line: {cmd} {arguments}.
|
|
||||||
Output: {output}
|
|
||||||
Error: {process.StandardError.ReadToEnd ()}";
|
|
||||||
}
|
|
||||||
|
|
||||||
return (process.ExitCode, output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
79
Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs
Normal file
79
Terminal.Gui/App/Clipboard/ClipboardProcessRunner.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Terminal.Gui.App;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class for console drivers to invoke shell commands to interact with the clipboard. Used primarily by
|
||||||
|
/// CursesDriver, but also used in Unit tests which is why it is in IConsoleDriver.cs.
|
||||||
|
/// </summary>
|
||||||
|
internal static class ClipboardProcessRunner
|
||||||
|
{
|
||||||
|
public static (int exitCode, string result) Bash (
|
||||||
|
string commandLine,
|
||||||
|
string inputText = "",
|
||||||
|
bool waitForOutput = false
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var arguments = $"-c \"{commandLine}\"";
|
||||||
|
(int exitCode, string result) = Process ("bash", arguments, inputText, waitForOutput);
|
||||||
|
|
||||||
|
return (exitCode, result.TrimEnd ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool FileExists (this string value) { return !string.IsNullOrEmpty (value) && !value.Contains ("not found"); }
|
||||||
|
|
||||||
|
public static (int exitCode, string result) Process (
|
||||||
|
string cmd,
|
||||||
|
string arguments,
|
||||||
|
string? input = null,
|
||||||
|
bool waitForOutput = true
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var output = string.Empty;
|
||||||
|
|
||||||
|
using var process = new Process ();
|
||||||
|
|
||||||
|
process.StartInfo = new()
|
||||||
|
{
|
||||||
|
FileName = cmd,
|
||||||
|
Arguments = arguments,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
RedirectStandardInput = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
TaskCompletionSource<bool> eventHandled = new ();
|
||||||
|
process.Start ();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty (input))
|
||||||
|
{
|
||||||
|
process.StandardInput.Write (input);
|
||||||
|
process.StandardInput.Close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!process.WaitForExit (5000))
|
||||||
|
{
|
||||||
|
var timeoutError =
|
||||||
|
$@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
|
||||||
|
|
||||||
|
throw new TimeoutException (timeoutError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (waitForOutput && process.StandardOutput.Peek () != -1)
|
||||||
|
{
|
||||||
|
output = process.StandardOutput.ReadToEnd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.ExitCode > 0)
|
||||||
|
{
|
||||||
|
output = $@"Process failed to run. Command line: {cmd} {arguments}.
|
||||||
|
Output: {output}
|
||||||
|
Error: {process.StandardError.ReadToEnd ()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (process.ExitCode, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
//
|
#nullable enable
|
||||||
|
//
|
||||||
// FakeDriver.cs: A fake IConsoleDriver for unit tests.
|
// FakeDriver.cs: A fake IConsoleDriver for unit tests.
|
||||||
//
|
//
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
public bool UseFakeClipboard { get; internal set; }
|
public bool UseFakeClipboard { get; internal set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Behaviors FakeBehaviors = new ();
|
public static Behaviors FakeBehaviors { get; } = new ();
|
||||||
public override bool SupportsTrueColor => false;
|
public override bool SupportsTrueColor => false;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -47,8 +48,8 @@ public class FakeDriver : ConsoleDriver
|
|||||||
|
|
||||||
public FakeDriver ()
|
public FakeDriver ()
|
||||||
{
|
{
|
||||||
Cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = FakeConsole.WIDTH;
|
base.Cols = FakeConsole.WindowWidth = FakeConsole.BufferWidth = FakeConsole.WIDTH;
|
||||||
Rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
|
base.Rows = FakeConsole.WindowHeight = FakeConsole.BufferHeight = FakeConsole.HEIGHT;
|
||||||
|
|
||||||
if (FakeBehaviors.UseFakeClipboard)
|
if (FakeBehaviors.UseFakeClipboard)
|
||||||
{
|
{
|
||||||
@@ -87,7 +88,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
FakeConsole.Clear ();
|
FakeConsole.Clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private FakeMainLoop _mainLoopDriver;
|
private FakeMainLoop? _mainLoopDriver;
|
||||||
|
|
||||||
public override MainLoop Init ()
|
public override MainLoop Init ()
|
||||||
{
|
{
|
||||||
@@ -124,7 +125,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
|
|
||||||
for (int row = top; row < rows; row++)
|
for (int row = top; row < rows; row++)
|
||||||
{
|
{
|
||||||
if (!_dirtyLines [row])
|
if (!_dirtyLines! [row])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -144,7 +145,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
|
|
||||||
for (; col < cols; col++)
|
for (; col < cols; col++)
|
||||||
{
|
{
|
||||||
if (!Contents [row, col].IsDirty)
|
if (!Contents! [row, col].IsDirty)
|
||||||
{
|
{
|
||||||
if (output.Length > 0)
|
if (output.Length > 0)
|
||||||
{
|
{
|
||||||
@@ -168,7 +169,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
lastCol = col;
|
lastCol = col;
|
||||||
}
|
}
|
||||||
|
|
||||||
Attribute attr = Contents [row, col].Attribute.Value;
|
Attribute attr = Contents [row, col].Attribute!.Value;
|
||||||
|
|
||||||
// Performance: Only send the escape sequence if the attribute has changed.
|
// Performance: Only send the escape sequence if the attribute has changed.
|
||||||
if (attr != redrawAttr)
|
if (attr != redrawAttr)
|
||||||
@@ -209,18 +210,18 @@ public class FakeDriver : ConsoleDriver
|
|||||||
|
|
||||||
//SetCursorVisibility (savedVisibility);
|
//SetCursorVisibility (savedVisibility);
|
||||||
|
|
||||||
void WriteToConsole (StringBuilder output, ref int lastCol, int row, ref int outputWidth)
|
void WriteToConsole (StringBuilder outputSb, ref int lastColumn, int row, ref int outputWidth)
|
||||||
{
|
{
|
||||||
FakeConsole.CursorTop = row;
|
FakeConsole.CursorTop = row;
|
||||||
FakeConsole.CursorLeft = lastCol;
|
FakeConsole.CursorLeft = lastColumn;
|
||||||
|
|
||||||
foreach (char c in output.ToString ())
|
foreach (char c in outputSb.ToString ())
|
||||||
{
|
{
|
||||||
FakeConsole.Write (c);
|
FakeConsole.Write (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
output.Clear ();
|
outputSb.Clear ();
|
||||||
lastCol += outputWidth;
|
lastColumn += outputWidth;
|
||||||
outputWidth = 0;
|
outputWidth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -506,7 +507,7 @@ public class FakeDriver : ConsoleDriver
|
|||||||
|
|
||||||
public class FakeClipboard : ClipboardBase
|
public class FakeClipboard : ClipboardBase
|
||||||
{
|
{
|
||||||
public Exception FakeException;
|
public Exception? FakeException { get; set; }
|
||||||
|
|
||||||
private readonly bool _isSupportedAlwaysFalse;
|
private readonly bool _isSupportedAlwaysFalse;
|
||||||
private string _contents = string.Empty;
|
private string _contents = string.Empty;
|
||||||
@@ -536,19 +537,14 @@ public class FakeDriver : ConsoleDriver
|
|||||||
return _contents;
|
return _contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetClipboardDataImpl (string text)
|
protected override void SetClipboardDataImpl (string? text)
|
||||||
{
|
{
|
||||||
if (text is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException (nameof (text));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FakeException is { })
|
if (FakeException is { })
|
||||||
{
|
{
|
||||||
throw FakeException;
|
throw FakeException;
|
||||||
}
|
}
|
||||||
|
|
||||||
_contents = text;
|
_contents = text ?? throw new ArgumentNullException (nameof (text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.Runtime.InteropServices;
|
#nullable enable
|
||||||
using Microsoft.Extensions.Logging;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Terminal.Gui.Drivers;
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
private CursorVisibility _lastCursor = CursorVisibility.Default;
|
private CursorVisibility _lastCursor = CursorVisibility.Default;
|
||||||
|
|
||||||
/// <summary>The event fired when the terminal is resized.</summary>
|
/// <summary>The event fired when the terminal is resized.</summary>
|
||||||
public event EventHandler<SizeChangedEventArgs> SizeChanged;
|
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
|
||||||
|
|
||||||
public IInputProcessor InputProcessor { get; }
|
public IInputProcessor InputProcessor { get; }
|
||||||
public IOutputBuffer OutputBuffer => _outputBuffer;
|
public IOutputBuffer OutputBuffer => _outputBuffer;
|
||||||
@@ -48,6 +48,13 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
|
|
||||||
private void CreateClipboard ()
|
private void CreateClipboard ()
|
||||||
{
|
{
|
||||||
|
if (FakeDriver.FakeBehaviors.UseFakeClipboard)
|
||||||
|
{
|
||||||
|
Clipboard = new FakeDriver.FakeClipboard ();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PlatformID p = Environment.OSVersion.Platform;
|
PlatformID p = Environment.OSVersion.Platform;
|
||||||
|
|
||||||
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
|
if (p == PlatformID.Win32NT || p == PlatformID.Win32S || p == PlatformID.Win32Windows)
|
||||||
@@ -88,7 +95,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
/// to.
|
/// to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The rectangle describing the of <see cref="Clip"/> region.</value>
|
/// <value>The rectangle describing the of <see cref="Clip"/> region.</value>
|
||||||
public Region Clip
|
public Region? Clip
|
||||||
{
|
{
|
||||||
get => _outputBuffer.Clip;
|
get => _outputBuffer.Clip;
|
||||||
set => _outputBuffer.Clip = value;
|
set => _outputBuffer.Clip = value;
|
||||||
@@ -114,7 +121,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
/// The contents of the application output. The driver outputs this buffer to the terminal.
|
/// The contents of the application output. The driver outputs this buffer to the terminal.
|
||||||
/// <remarks>The format of the array is rows, columns. The first index is the row, the second index is the column.</remarks>
|
/// <remarks>The format of the array is rows, columns. The first index is the row, the second index is the column.</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Cell [,] Contents
|
public Cell [,]? Contents
|
||||||
{
|
{
|
||||||
get => _outputBuffer.Contents;
|
get => _outputBuffer.Contents;
|
||||||
set => _outputBuffer.Contents = value;
|
set => _outputBuffer.Contents = value;
|
||||||
@@ -229,7 +236,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raised each time <see cref="ConsoleDriver.ClearContents"/> is called. For benchmarking.
|
/// Raised each time <see cref="ConsoleDriver.ClearContents"/> is called. For benchmarking.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<EventArgs> ClearedContents;
|
public event EventHandler<EventArgs>? ClearedContents;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills the specified rectangle with the specified rune, using <see cref="ConsoleDriver.CurrentAttribute"/>
|
/// Fills the specified rectangle with the specified rune, using <see cref="ConsoleDriver.CurrentAttribute"/>
|
||||||
@@ -397,7 +404,7 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Event fired when a key is pressed down. This is a precursor to <see cref="ConsoleDriver.KeyUp"/>.</summary>
|
/// <summary>Event fired when a key is pressed down. This is a precursor to <see cref="ConsoleDriver.KeyUp"/>.</summary>
|
||||||
public event EventHandler<Key> KeyDown;
|
public event EventHandler<Key>? KeyDown;
|
||||||
|
|
||||||
/// <summary>Event fired when a key is released.</summary>
|
/// <summary>Event fired when a key is released.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
@@ -405,10 +412,10 @@ internal class ConsoleDriverFacade<T> : IConsoleDriver, IConsoleDriverFacade
|
|||||||
/// processing is
|
/// processing is
|
||||||
/// complete.
|
/// complete.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public event EventHandler<Key> KeyUp;
|
public event EventHandler<Key>? KeyUp;
|
||||||
|
|
||||||
/// <summary>Event fired when a mouse event occurs.</summary>
|
/// <summary>Event fired when a mouse event occurs.</summary>
|
||||||
public event EventHandler<MouseEventArgs> MouseEvent;
|
public event EventHandler<MouseEventArgs>? MouseEvent;
|
||||||
|
|
||||||
/// <summary>Simulates a key press.</summary>
|
/// <summary>Simulates a key press.</summary>
|
||||||
/// <param name="keyChar">The key character.</param>
|
/// <param name="keyChar">The key character.</param>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
namespace Terminal.Gui.Drivers;
|
#nullable enable
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface for v2 driver abstraction layer
|
/// Interface for v2 driver abstraction layer
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public interface IOutputBuffer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The contents of the application output. The driver outputs this buffer to the terminal when UpdateScreen is called.
|
/// The contents of the application output. The driver outputs this buffer to the terminal when UpdateScreen is called.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Cell [,] Contents { get; set; }
|
Cell [,]? Contents { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the clip rectangle that <see cref="AddRune(Rune)"/> and <see cref="AddStr(string)"/> are subject
|
/// Gets or sets the clip rectangle that <see cref="AddRune(Rune)"/> and <see cref="AddStr(string)"/> are subject
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Drawing;
|
||||||
|
using TerminalGuiFluentTesting;
|
||||||
|
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
public class FakeApplicationFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an initialized fake application which will be cleaned up when result object
|
||||||
|
/// is disposed.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IDisposable SetupFakeApplication ()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource ();
|
||||||
|
var fakeInput = new FakeNetInput (cts.Token);
|
||||||
|
FakeOutput output = new ();
|
||||||
|
output.Size = new (25, 25);
|
||||||
|
|
||||||
|
IApplication origApp = ApplicationImpl.Instance;
|
||||||
|
|
||||||
|
var sizeMonitor = new FakeSizeMonitor ();
|
||||||
|
|
||||||
|
var v2 = new ApplicationV2 (new FakeNetComponentFactory (fakeInput, output, sizeMonitor));
|
||||||
|
|
||||||
|
ApplicationImpl.ChangeInstance (v2);
|
||||||
|
v2.Init (null, "v2net");
|
||||||
|
|
||||||
|
ConsoleDriverFacade<ConsoleKeyInfo> d = (ConsoleDriverFacade<ConsoleKeyInfo>)Application.Driver!;
|
||||||
|
|
||||||
|
sizeMonitor.SizeChanging += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.Size != null)
|
||||||
|
{
|
||||||
|
Size s = e.Size.Value;
|
||||||
|
output.Size = s;
|
||||||
|
d.OutputBuffer.SetWindowSize (s.Width, s.Height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new FakeApplicationLifecycle (origApp, cts);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#nullable enable
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
internal class FakeApplicationLifecycle (IApplication origApp, CancellationTokenSource hardStop) : IDisposable
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
hardStop.Cancel ();
|
||||||
|
|
||||||
|
Application.Top?.Dispose ();
|
||||||
|
Application.Shutdown ();
|
||||||
|
ApplicationImpl.ChangeInstance (origApp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#nullable enable
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
public class FakeDriverFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of <see cref="FakeDriverV2"/> using default options
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public IFakeDriverV2 Create ()
|
||||||
|
{
|
||||||
|
return new FakeDriverV2 (
|
||||||
|
new (),
|
||||||
|
new (),
|
||||||
|
new (),
|
||||||
|
() => DateTime.Now,
|
||||||
|
new ());
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Tests/TerminalGuiFluentTesting/FakeDriver/FakeDriverV2.cs
Normal file
58
Tests/TerminalGuiFluentTesting/FakeDriver/FakeDriverV2.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Drawing;
|
||||||
|
using TerminalGuiFluentTesting;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||||
|
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of <see cref="IConsoleDriver"/> that uses fake input/output.
|
||||||
|
/// This is a lightweight alternative to <see cref="GuiTestContext"/> (if you don't
|
||||||
|
/// need the entire application main loop running).
|
||||||
|
/// </summary>
|
||||||
|
internal class FakeDriverV2 : ConsoleDriverFacade<ConsoleKeyInfo>, IFakeDriverV2
|
||||||
|
{
|
||||||
|
internal FakeDriverV2 (
|
||||||
|
ConcurrentQueue<ConsoleKeyInfo> inputBuffer,
|
||||||
|
OutputBuffer outputBuffer,
|
||||||
|
FakeOutput fakeOutput,
|
||||||
|
Func<DateTime> datetimeFunc,
|
||||||
|
FakeSizeMonitor sizeMonitor
|
||||||
|
) :
|
||||||
|
base (
|
||||||
|
new NetInputProcessor (inputBuffer),
|
||||||
|
outputBuffer,
|
||||||
|
fakeOutput,
|
||||||
|
new (new AnsiResponseParser (), datetimeFunc),
|
||||||
|
sizeMonitor)
|
||||||
|
{
|
||||||
|
FakeOutput fakeOutput1;
|
||||||
|
InputBuffer = inputBuffer;
|
||||||
|
SizeMonitor = sizeMonitor;
|
||||||
|
OutputBuffer = outputBuffer;
|
||||||
|
ConsoleOutput = fakeOutput1 = fakeOutput;
|
||||||
|
|
||||||
|
SizeChanged += (_, e) =>
|
||||||
|
{
|
||||||
|
if (e.Size != null)
|
||||||
|
{
|
||||||
|
Size s = e.Size.Value;
|
||||||
|
fakeOutput1.Size = s;
|
||||||
|
OutputBuffer.SetWindowSize (s.Width, s.Height);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetBufferSize (int width, int height)
|
||||||
|
{
|
||||||
|
SizeMonitor.RaiseSizeChanging (new (width, height));
|
||||||
|
OutputBuffer.SetWindowSize (width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConsoleOutput ConsoleOutput { get; }
|
||||||
|
public ConcurrentQueue<ConsoleKeyInfo> InputBuffer { get; }
|
||||||
|
public new OutputBuffer OutputBuffer { get; }
|
||||||
|
public FakeSizeMonitor SizeMonitor { get; }
|
||||||
|
}
|
||||||
20
Tests/TerminalGuiFluentTesting/FakeDriver/FakeSizeMonitor.cs
Normal file
20
Tests/TerminalGuiFluentTesting/FakeDriver/FakeSizeMonitor.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#nullable enable
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
public class FakeSizeMonitor : IWindowSizeMonitor
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public event EventHandler<SizeChangedEventArgs>? SizeChanging;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Poll () { return false; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises the <see cref="SizeChanging"/> event.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newSize"></param>
|
||||||
|
public void RaiseSizeChanging (Size newSize) { SizeChanging?.Invoke (this, new (newSize)); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#nullable enable
|
||||||
|
namespace Terminal.Gui.Drivers;
|
||||||
|
|
||||||
|
#pragma warning disable CS1591
|
||||||
|
public interface IFakeDriverV2 : IConsoleDriver, IConsoleDriverFacade
|
||||||
|
{
|
||||||
|
void SetBufferSize (int width, int height);
|
||||||
|
}
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Drawing;
|
|
||||||
using TerminalGuiFluentTesting;
|
|
||||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
||||||
|
|
||||||
namespace Terminal.Gui.Drivers;
|
|
||||||
|
|
||||||
public class FakeApplicationFactory
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates an initialized fake application which will be cleaned up when result object
|
|
||||||
/// is disposed.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IDisposable SetupFakeApplication ()
|
|
||||||
{
|
|
||||||
var cts = new CancellationTokenSource ();
|
|
||||||
var fakeInput = new FakeNetInput (cts.Token);
|
|
||||||
FakeOutput output = new ();
|
|
||||||
output.Size = new (25, 25);
|
|
||||||
|
|
||||||
|
|
||||||
IApplication origApp = ApplicationImpl.Instance;
|
|
||||||
|
|
||||||
var sizeMonitor = new FakeSizeMonitor ();
|
|
||||||
|
|
||||||
var v2 = new ApplicationV2 (new FakeNetComponentFactory (fakeInput, output, sizeMonitor));
|
|
||||||
|
|
||||||
ApplicationImpl.ChangeInstance (v2);
|
|
||||||
v2.Init (null,"v2net");
|
|
||||||
|
|
||||||
var d = (ConsoleDriverFacade<ConsoleKeyInfo>)Application.Driver!;
|
|
||||||
sizeMonitor.SizeChanging += (_, e) =>
|
|
||||||
{
|
|
||||||
if (e.Size != null)
|
|
||||||
{
|
|
||||||
var s = e.Size.Value;
|
|
||||||
output.Size = s;
|
|
||||||
d.OutputBuffer.SetWindowSize (s.Width, s.Height);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new FakeApplicationLifecycle (origApp,cts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FakeApplicationLifecycle : IDisposable
|
|
||||||
{
|
|
||||||
private readonly IApplication _origApp;
|
|
||||||
private readonly CancellationTokenSource _hardStop;
|
|
||||||
|
|
||||||
public FakeApplicationLifecycle (IApplication origApp, CancellationTokenSource hardStop)
|
|
||||||
{
|
|
||||||
_origApp = origApp;
|
|
||||||
_hardStop = hardStop;
|
|
||||||
}
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose ()
|
|
||||||
{
|
|
||||||
_hardStop.Cancel();
|
|
||||||
|
|
||||||
Application.Top?.Dispose ();
|
|
||||||
Application.Shutdown ();
|
|
||||||
ApplicationImpl.ChangeInstance (_origApp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FakeDriverFactory
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a new instance of <see cref="FakeDriverV2"/> using default options
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public IFakeDriverV2 Create ()
|
|
||||||
{
|
|
||||||
return new FakeDriverV2 (
|
|
||||||
new ConcurrentQueue<ConsoleKeyInfo> (),
|
|
||||||
new OutputBuffer (),
|
|
||||||
new FakeOutput (),
|
|
||||||
() => DateTime.Now,
|
|
||||||
new FakeSizeMonitor ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IFakeDriverV2 : IConsoleDriver, IConsoleDriverFacade
|
|
||||||
{
|
|
||||||
void SetBufferSize (int width, int height);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of <see cref="IConsoleDriver"/> that uses fake input/output.
|
|
||||||
/// This is a lightweight alternative to <see cref="GuiTestContext"/> (if you don't
|
|
||||||
/// need the entire application main loop running).
|
|
||||||
/// </summary>
|
|
||||||
class FakeDriverV2 : ConsoleDriverFacade<ConsoleKeyInfo>, IFakeDriverV2
|
|
||||||
{
|
|
||||||
public ConcurrentQueue<ConsoleKeyInfo> InputBuffer { get; }
|
|
||||||
public FakeSizeMonitor SizeMonitor { get; }
|
|
||||||
public new OutputBuffer OutputBuffer { get; }
|
|
||||||
|
|
||||||
public IConsoleOutput ConsoleOutput { get; }
|
|
||||||
|
|
||||||
private FakeOutput _fakeOutput;
|
|
||||||
|
|
||||||
internal FakeDriverV2 (
|
|
||||||
ConcurrentQueue<ConsoleKeyInfo> inputBuffer,
|
|
||||||
OutputBuffer outputBuffer,
|
|
||||||
FakeOutput fakeOutput,
|
|
||||||
Func<DateTime> datetimeFunc,
|
|
||||||
FakeSizeMonitor sizeMonitor) :
|
|
||||||
base (new NetInputProcessor (inputBuffer),
|
|
||||||
outputBuffer,
|
|
||||||
fakeOutput,
|
|
||||||
new (new AnsiResponseParser (), datetimeFunc),
|
|
||||||
sizeMonitor)
|
|
||||||
{
|
|
||||||
InputBuffer = inputBuffer;
|
|
||||||
SizeMonitor = sizeMonitor;
|
|
||||||
OutputBuffer = outputBuffer;
|
|
||||||
ConsoleOutput = _fakeOutput = fakeOutput;
|
|
||||||
SizeChanged += (_, e) =>
|
|
||||||
{
|
|
||||||
if (e.Size != null)
|
|
||||||
{
|
|
||||||
var s = e.Size.Value;
|
|
||||||
_fakeOutput.Size = s;
|
|
||||||
OutputBuffer.SetWindowSize (s.Width,s.Height);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetBufferSize (int width, int height)
|
|
||||||
{
|
|
||||||
SizeMonitor.RaiseSizeChanging (new Size (width,height));
|
|
||||||
OutputBuffer.SetWindowSize (width,height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FakeSizeMonitor : IWindowSizeMonitor
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public event EventHandler<SizeChangedEventArgs>? SizeChanging;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public bool Poll ()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Raises the <see cref="SizeChanging"/> event.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="newSize"></param>
|
|
||||||
public void RaiseSizeChanging (Size newSize)
|
|
||||||
{
|
|
||||||
SizeChanging?.Invoke (this,new (newSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ namespace TerminalGuiFluentTesting;
|
|||||||
|
|
||||||
internal class FakeOutput : IConsoleOutput
|
internal class FakeOutput : IConsoleOutput
|
||||||
{
|
{
|
||||||
public IOutputBuffer LastBuffer { get; set; }
|
public IOutputBuffer? LastBuffer { get; set; }
|
||||||
public Size Size { get; set; }
|
public Size Size { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
Reference in New Issue
Block a user