From 4bdd3ccc6c4d9e019a32536d7d6033cd23765fcc Mon Sep 17 00:00:00 2001
From: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Date: Tue, 23 Jan 2024 23:30:27 +0200
Subject: [PATCH] Refactor
---
CliFx/Attributes/CommandAttribute.cs | 23 ++++-----
CliFx/Attributes/CommandOptionAttribute.cs | 54 ++++++++++-----------
CliFx/Infrastructure/ConsoleReader.cs | 10 +---
CliFx/Infrastructure/ConsoleWriter.cs | 21 ++++----
CliFx/Infrastructure/FakeConsole.cs | 37 +++++++-------
CliFx/Infrastructure/FakeInMemoryConsole.cs | 6 +--
CliFx/Infrastructure/IConsole.cs | 18 +++----
CliFx/Infrastructure/SystemConsole.cs | 20 ++++----
8 files changed, 91 insertions(+), 98 deletions(-)
diff --git a/CliFx/Attributes/CommandAttribute.cs b/CliFx/Attributes/CommandAttribute.cs
index 6c97f95..2066428 100644
--- a/CliFx/Attributes/CommandAttribute.cs
+++ b/CliFx/Attributes/CommandAttribute.cs
@@ -8,6 +8,16 @@ namespace CliFx.Attributes;
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class CommandAttribute : Attribute
{
+ ///
+ /// Initializes an instance of .
+ ///
+ public CommandAttribute(string name) => Name = name;
+
+ ///
+ /// Initializes an instance of .
+ ///
+ public CommandAttribute() { }
+
///
/// Command name.
///
@@ -23,17 +33,4 @@ public sealed class CommandAttribute : Attribute
/// This is shown to the user in the help text.
///
public string? Description { get; set; }
-
- ///
- /// Initializes an instance of .
- ///
- public CommandAttribute(string name)
- {
- Name = name;
- }
-
- ///
- /// Initializes an instance of .
- ///
- public CommandAttribute() { }
}
diff --git a/CliFx/Attributes/CommandOptionAttribute.cs b/CliFx/Attributes/CommandOptionAttribute.cs
index f4c4343..96d237a 100644
--- a/CliFx/Attributes/CommandOptionAttribute.cs
+++ b/CliFx/Attributes/CommandOptionAttribute.cs
@@ -9,6 +9,33 @@ namespace CliFx.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public sealed class CommandOptionAttribute : Attribute
{
+ ///
+ /// Initializes an instance of .
+ ///
+ private CommandOptionAttribute(string? name, char? shortName)
+ {
+ Name = name;
+ ShortName = shortName;
+ }
+
+ ///
+ /// Initializes an instance of .
+ ///
+ public CommandOptionAttribute(string name, char shortName)
+ : this(name, (char?)shortName) { }
+
+ ///
+ /// Initializes an instance of .
+ ///
+ public CommandOptionAttribute(string name)
+ : this(name, null) { }
+
+ ///
+ /// Initializes an instance of .
+ ///
+ public CommandOptionAttribute(char shortName)
+ : this(null, (char?)shortName) { }
+
///
/// Option name.
///
@@ -67,31 +94,4 @@ public sealed class CommandOptionAttribute : Attribute
/// Validators must derive from .
///
public Type[] Validators { get; set; } = Array.Empty();
-
- ///
- /// Initializes an instance of .
- ///
- private CommandOptionAttribute(string? name, char? shortName)
- {
- Name = name;
- ShortName = shortName;
- }
-
- ///
- /// Initializes an instance of .
- ///
- public CommandOptionAttribute(string name, char shortName)
- : this(name, (char?)shortName) { }
-
- ///
- /// Initializes an instance of .
- ///
- public CommandOptionAttribute(string name)
- : this(name, null) { }
-
- ///
- /// Initializes an instance of .
- ///
- public CommandOptionAttribute(char shortName)
- : this(null, (char?)shortName) { }
}
diff --git a/CliFx/Infrastructure/ConsoleReader.cs b/CliFx/Infrastructure/ConsoleReader.cs
index 69f7dd2..ef83201 100644
--- a/CliFx/Infrastructure/ConsoleReader.cs
+++ b/CliFx/Infrastructure/ConsoleReader.cs
@@ -11,8 +11,8 @@ namespace CliFx.Infrastructure;
///
// Both the underlying stream AND the stream reader must be synchronized!
// https://github.com/Tyrrrz/CliFx/issues/123
-public partial class ConsoleReader(IConsole console, Stream stream, Encoding encoding)
- : StreamReader(stream, encoding, false, 4096)
+public class ConsoleReader(IConsole console, Stream stream, Encoding encoding)
+ : StreamReader(Stream.Synchronized(stream), encoding, false, 4096)
{
///
/// Initializes an instance of .
@@ -86,9 +86,3 @@ public partial class ConsoleReader(IConsole console, Stream stream, Encoding enc
[ExcludeFromCodeCoverage, MethodImpl(MethodImplOptions.Synchronized)]
protected override void Dispose(bool disposing) => base.Dispose(disposing);
}
-
-public partial class ConsoleReader
-{
- internal static ConsoleReader Create(IConsole console, Stream stream) =>
- new(console, Stream.Synchronized(stream));
-}
diff --git a/CliFx/Infrastructure/ConsoleWriter.cs b/CliFx/Infrastructure/ConsoleWriter.cs
index 17676b1..9222859 100644
--- a/CliFx/Infrastructure/ConsoleWriter.cs
+++ b/CliFx/Infrastructure/ConsoleWriter.cs
@@ -12,9 +12,18 @@ namespace CliFx.Infrastructure;
///
// Both the underlying stream AND the stream writer must be synchronized!
// https://github.com/Tyrrrz/CliFx/issues/123
-public partial class ConsoleWriter(IConsole console, Stream stream, Encoding encoding)
- : StreamWriter(stream, encoding.WithoutPreamble(), 256)
+public class ConsoleWriter : StreamWriter
{
+ ///
+ /// Initializes an instance of .
+ ///
+ public ConsoleWriter(IConsole console, Stream stream, Encoding encoding)
+ : base(Stream.Synchronized(stream), encoding.WithoutPreamble(), 256)
+ {
+ Console = console;
+ AutoFlush = true;
+ }
+
///
/// Initializes an instance of .
///
@@ -24,7 +33,7 @@ public partial class ConsoleWriter(IConsole console, Stream stream, Encoding enc
///
/// Console that owns this stream.
///
- public IConsole Console { get; } = console;
+ public IConsole Console { get; }
// The following overrides are required to establish thread-safe behavior
// in methods deriving from StreamWriter.
@@ -260,9 +269,3 @@ public partial class ConsoleWriter(IConsole console, Stream stream, Encoding enc
[ExcludeFromCodeCoverage, MethodImpl(MethodImplOptions.Synchronized)]
protected override void Dispose(bool disposing) => base.Dispose(disposing);
}
-
-public partial class ConsoleWriter
-{
- internal static ConsoleWriter Create(IConsole console, Stream stream) =>
- new(console, Stream.Synchronized(stream)) { AutoFlush = true };
-}
diff --git a/CliFx/Infrastructure/FakeConsole.cs b/CliFx/Infrastructure/FakeConsole.cs
index 2ef7622..5497389 100644
--- a/CliFx/Infrastructure/FakeConsole.cs
+++ b/CliFx/Infrastructure/FakeConsole.cs
@@ -6,15 +6,24 @@ using System.Threading;
namespace CliFx.Infrastructure;
///
-/// Implementation of that uses the provided fake
-/// standard input, output, and error streams.
-/// Use this implementation in tests to verify command interactions with the console.
+/// Implementation of that uses the provided fake standard input, output, and error streams.
+/// Use this implementation in tests to verify how a command interacts with the console.
///
public class FakeConsole : IConsole, IDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly ConcurrentQueue _keys = new();
+ ///
+ /// Initializes an instance of .
+ ///
+ public FakeConsole(Stream? input = null, Stream? output = null, Stream? error = null)
+ {
+ Input = new ConsoleReader(this, input ?? Stream.Null);
+ Output = new ConsoleWriter(this, output ?? Stream.Null);
+ Error = new ConsoleWriter(this, error ?? Stream.Null);
+ }
+
///
public ConsoleReader Input { get; }
@@ -52,14 +61,9 @@ public class FakeConsole : IConsole, IDisposable
public int CursorTop { get; set; }
///
- /// Initializes an instance of .
+ /// Enqueues a simulated key press, which can then be read by calling .
///
- public FakeConsole(Stream? input = null, Stream? output = null, Stream? error = null)
- {
- Input = ConsoleReader.Create(this, input ?? Stream.Null);
- Output = ConsoleWriter.Create(this, output ?? Stream.Null);
- Error = ConsoleWriter.Create(this, error ?? Stream.Null);
- }
+ public void EnqueueKey(ConsoleKeyInfo key) => _keys.Enqueue(key);
///
public ConsoleKeyInfo ReadKey(bool intercept = false) =>
@@ -70,11 +74,6 @@ public class FakeConsole : IConsole, IDisposable
+ $"Use the `{nameof(EnqueueKey)}(...)` method to simulate a key press."
);
- ///
- /// Enqueues a simulated key press, which can then be read by calling .
- ///
- public void EnqueueKey(ConsoleKeyInfo key) => _keys.Enqueue(key);
-
///
public void ResetColor()
{
@@ -85,11 +84,8 @@ public class FakeConsole : IConsole, IDisposable
///
public void Clear() { }
- ///
- public CancellationToken RegisterCancellationHandler() => _cancellationTokenSource.Token;
-
///
- /// Sends a cancellation signal to the currently executing command.
+ /// Simulates a cancellation request.
///
///
/// If the command is not cancellation-aware (i.e. it doesn't call ),
@@ -108,6 +104,9 @@ public class FakeConsole : IConsole, IDisposable
}
}
+ ///
+ public CancellationToken RegisterCancellationHandler() => _cancellationTokenSource.Token;
+
///
public virtual void Dispose() => _cancellationTokenSource.Dispose();
}
diff --git a/CliFx/Infrastructure/FakeInMemoryConsole.cs b/CliFx/Infrastructure/FakeInMemoryConsole.cs
index daac26d..0be8646 100644
--- a/CliFx/Infrastructure/FakeInMemoryConsole.cs
+++ b/CliFx/Infrastructure/FakeInMemoryConsole.cs
@@ -3,9 +3,9 @@
namespace CliFx.Infrastructure;
///
-/// Implementation of that uses fake
-/// standard input, output, and error streams backed by in-memory stores.
-/// Use this implementation in tests to verify command interactions with the console.
+/// Implementation of that uses fake standard input, output, and error streams
+/// backed by in-memory stores.
+/// Use this implementation in tests to verify how a command interacts with the console.
///
public class FakeInMemoryConsole : FakeConsole
{
diff --git a/CliFx/Infrastructure/IConsole.cs b/CliFx/Infrastructure/IConsole.cs
index 32e1071..50e5c39 100644
--- a/CliFx/Infrastructure/IConsole.cs
+++ b/CliFx/Infrastructure/IConsole.cs
@@ -5,47 +5,47 @@ using CliFx.Utils;
namespace CliFx.Infrastructure;
///
-/// Abstraction for the console layer.
+/// Abstraction for interacting with the console layer.
///
public interface IConsole
{
///
- /// Input stream (stdin).
+ /// Console's standard input stream.
///
ConsoleReader Input { get; }
///
- /// Gets a value that indicates whether input has been redirected from the standard input stream.
+ /// Whether the input stream has been redirected.
///
bool IsInputRedirected { get; }
///
- /// Output stream (stdout).
+ /// Console's standard output stream.
///
ConsoleWriter Output { get; }
///
- /// Gets a value that indicates whether output has been redirected from the standard output stream.
+ /// Whether the output stream has been redirected.
///
bool IsOutputRedirected { get; }
///
- /// Error stream (stderr).
+ /// Console's standard error stream.
///
ConsoleWriter Error { get; }
///
- /// Gets a value that indicates whether error output has been redirected from the standard error stream.
+ /// Whether the error stream has been redirected.
///
bool IsErrorRedirected { get; }
///
- /// Gets or sets the foreground color of the console
+ /// Gets or sets the current foreground color of the console.
///
ConsoleColor ForegroundColor { get; set; }
///
- /// Gets or sets the background color of the console.
+ /// Gets or sets the current background color of the console.
///
ConsoleColor BackgroundColor { get; set; }
diff --git a/CliFx/Infrastructure/SystemConsole.cs b/CliFx/Infrastructure/SystemConsole.cs
index a253782..f696637 100644
--- a/CliFx/Infrastructure/SystemConsole.cs
+++ b/CliFx/Infrastructure/SystemConsole.cs
@@ -10,6 +10,16 @@ public class SystemConsole : IConsole, IDisposable
{
private CancellationTokenSource? _cancellationTokenSource;
+ ///
+ /// Initializes an instance of .
+ ///
+ public SystemConsole()
+ {
+ Input = new ConsoleReader(this, Console.OpenStandardInput());
+ Output = new ConsoleWriter(this, Console.OpenStandardOutput());
+ Error = new ConsoleWriter(this, Console.OpenStandardError());
+ }
+
///
public ConsoleReader Input { get; }
@@ -70,16 +80,6 @@ public class SystemConsole : IConsole, IDisposable
set => Console.CursorTop = value;
}
- ///
- /// Initializes an instance of .
- ///
- public SystemConsole()
- {
- Input = ConsoleReader.Create(this, Console.OpenStandardInput());
- Output = ConsoleWriter.Create(this, Console.OpenStandardOutput());
- Error = ConsoleWriter.Create(this, Console.OpenStandardError());
- }
-
///
public ConsoleKeyInfo ReadKey(bool intercept = false) => Console.ReadKey(intercept);