mirror of
https://github.com/Tyrrrz/CliFx.git
synced 2025-10-25 15:19:17 +00:00
Refactor
This commit is contained in:
@@ -1,12 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CliFx.Tests.Internal;
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
@@ -14,30 +8,6 @@ namespace CliFx.Tests
|
||||
{
|
||||
public partial class DirectivesSpecs
|
||||
{
|
||||
[Fact]
|
||||
public async Task Debug_directive_can_be_specified_to_have_the_application_wait_until_debugger_is_attached()
|
||||
{
|
||||
// We can't actually attach a debugger in tests, so instead just cancel execution after some time
|
||||
|
||||
// Arrange
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(1));
|
||||
var stdOut = new StringBuilder();
|
||||
|
||||
var command = Cli.Wrap("dotnet")
|
||||
.WithArguments(a => a
|
||||
.Add(Dummy.Program.Location)
|
||||
.Add("[debug]"))
|
||||
.WithEnvironmentVariables(e => e
|
||||
.Set("ENV_TARGET", "Mars")) | stdOut;
|
||||
|
||||
// Act
|
||||
await command.ExecuteAsync(cts.Token).Task.IgnoreCancellation();
|
||||
var stdOutData = stdOut.ToString();
|
||||
|
||||
// Assert
|
||||
stdOutData.Should().Contain("Attach debugger to");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Preview_directive_can_be_specified_to_print_provided_arguments_as_they_were_parsed()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
@@ -23,24 +23,17 @@ namespace CliFx
|
||||
/// </summary>
|
||||
public bool IsPreviewModeAllowed { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Prompt debugger launch when application is in debug mode
|
||||
/// </summary>
|
||||
public bool PromptDebuggerLaunchInDebugMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="ApplicationConfiguration"/>.
|
||||
/// </summary>
|
||||
public ApplicationConfiguration(
|
||||
IReadOnlyList<Type> commandTypes,
|
||||
bool isDebugModeAllowed,
|
||||
bool isPreviewModeAllowed,
|
||||
bool promptDebuggerLaunchInDebugMode)
|
||||
bool isPreviewModeAllowed)
|
||||
{
|
||||
CommandTypes = commandTypes;
|
||||
IsDebugModeAllowed = isDebugModeAllowed;
|
||||
IsPreviewModeAllowed = isPreviewModeAllowed;
|
||||
PromptDebuggerLaunchInDebugMode = promptDebuggerLaunchInDebugMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,13 +41,15 @@ namespace CliFx
|
||||
private void WriteError(string message) => _console.WithForegroundColor(ConsoleColor.Red, () =>
|
||||
_console.Error.WriteLine(message));
|
||||
|
||||
private async ValueTask WaitForDebuggerAsync()
|
||||
private async ValueTask LaunchAndWaitForDebuggerAsync()
|
||||
{
|
||||
var processId = ProcessEx.GetCurrentProcessId();
|
||||
|
||||
_console.WithForegroundColor(ConsoleColor.Green, () =>
|
||||
_console.Output.WriteLine($"Attach debugger to PID {processId} to continue."));
|
||||
|
||||
Debugger.Launch();
|
||||
|
||||
while (!Debugger.IsAttached)
|
||||
await Task.Delay(100);
|
||||
}
|
||||
@@ -125,19 +127,7 @@ namespace CliFx
|
||||
// Debug mode
|
||||
if (_configuration.IsDebugModeAllowed && input.IsDebugDirectiveSpecified)
|
||||
{
|
||||
if (_configuration.PromptDebuggerLaunchInDebugMode)
|
||||
{
|
||||
// Prompt debugger launcher dialog
|
||||
if (!Debugger.IsAttached)
|
||||
{
|
||||
Debugger.Launch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ensure debugger is attached and continue
|
||||
await WaitForDebuggerAsync();
|
||||
}
|
||||
await LaunchAndWaitForDebuggerAsync();
|
||||
}
|
||||
|
||||
// Preview mode
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using CliFx.Domain;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx
|
||||
{
|
||||
@@ -16,7 +16,6 @@ namespace CliFx
|
||||
private readonly HashSet<Type> _commandTypes = new HashSet<Type>();
|
||||
|
||||
private bool _isDebugModeAllowed = true;
|
||||
private bool _promptDebuggerLaunch = false;
|
||||
private bool _isPreviewModeAllowed = true;
|
||||
private string? _title;
|
||||
private string? _executableName;
|
||||
@@ -79,10 +78,9 @@ namespace CliFx
|
||||
/// <summary>
|
||||
/// Specifies whether debug mode (enabled with [debug] directive) is allowed in the application.
|
||||
/// </summary>
|
||||
public CliApplicationBuilder AllowDebugMode(bool isAllowed = true, bool promptDebuggerLaunch = false)
|
||||
public CliApplicationBuilder AllowDebugMode(bool isAllowed = true)
|
||||
{
|
||||
_isDebugModeAllowed = isAllowed;
|
||||
_promptDebuggerLaunch = promptDebuggerLaunch;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -168,7 +166,7 @@ namespace CliFx
|
||||
_typeActivator ??= new DefaultTypeActivator();
|
||||
|
||||
var metadata = new ApplicationMetadata(_title, _executableName, _versionText, _description);
|
||||
var configuration = new ApplicationConfiguration(_commandTypes.ToArray(), _isDebugModeAllowed, _isPreviewModeAllowed, _promptDebuggerLaunch);
|
||||
var configuration = new ApplicationConfiguration(_commandTypes.ToArray(), _isDebugModeAllowed, _isPreviewModeAllowed);
|
||||
|
||||
return new CliApplication(metadata, configuration, _console, _typeActivator);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CliFx.Exceptions;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Domain
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CliFx.Attributes;
|
||||
using CliFx.Domain;
|
||||
using CliFx.Internal;
|
||||
using CliFx.Internal.Extensions;
|
||||
|
||||
namespace CliFx.Exceptions
|
||||
{
|
||||
|
||||
@@ -14,9 +14,7 @@ namespace CliFx.Exceptions
|
||||
private readonly bool _isMessageSet;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an exit code associated with this exception.
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use exit codes between 1 and 255
|
||||
/// otherwise it may overflow and yield unexpected results.
|
||||
/// Exit code returned by the application when this exception is handled.
|
||||
/// </summary>
|
||||
public int ExitCode { get; }
|
||||
|
||||
@@ -28,14 +26,9 @@ namespace CliFx.Exceptions
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandException"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The exception message.</param>
|
||||
/// <param name="innerException">The inner exception.</param>
|
||||
/// <param name="exitCode">
|
||||
/// The exit code associated with this exception.
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use exit codes between 1 and 255
|
||||
/// otherwise it may overflow and yield unexpected results.
|
||||
/// </param>
|
||||
/// <param name="showHelp">Whether to show the help text after handling this exception.</param>
|
||||
/// <remarks>
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use values between 1 and 255 to avoid overflow.
|
||||
/// </remarks>
|
||||
public CommandException(string? message, Exception? innerException, int exitCode = DefaultExitCode, bool showHelp = false)
|
||||
: base(message, innerException)
|
||||
{
|
||||
@@ -49,13 +42,9 @@ namespace CliFx.Exceptions
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandException"/>.
|
||||
/// </summary>
|
||||
/// <param name="message">The exception message.</param>
|
||||
/// <param name="exitCode">
|
||||
/// The exit code associated with this exception.
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use exit codes between 1 and 255
|
||||
/// otherwise it may overflow and yield unexpected results.
|
||||
/// </param>
|
||||
/// <param name="showHelp">Whether to show the help text after handling this exception.</param>
|
||||
/// <remarks>
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use values between 1 and 255 to avoid overflow.
|
||||
/// </remarks>
|
||||
public CommandException(string? message, int exitCode = DefaultExitCode, bool showHelp = false)
|
||||
: this(message, null, exitCode, showHelp)
|
||||
{
|
||||
@@ -64,12 +53,9 @@ namespace CliFx.Exceptions
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="CommandException"/>.
|
||||
/// </summary>
|
||||
/// <param name="exitCode">
|
||||
/// The exit code associated with this exception.
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use exit codes between 1 and 255
|
||||
/// otherwise it may overflow and yield unexpected results.
|
||||
/// </param>
|
||||
/// <param name="showHelp">Whether to show the help text after handling this exception.</param>
|
||||
/// <remarks>
|
||||
/// On Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use values between 1 and 255 to avoid overflow.
|
||||
/// </remarks>
|
||||
public CommandException(int exitCode = DefaultExitCode, bool showHelp = false)
|
||||
: this(null, exitCode, showHelp)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CliFx.Internal
|
||||
namespace CliFx.Internal.Extensions
|
||||
{
|
||||
internal static class CollectionExtensions
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CliFx.Internal
|
||||
namespace CliFx.Internal.Extensions
|
||||
{
|
||||
internal static class StringExtensions
|
||||
{
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace CliFx.Internal
|
||||
namespace CliFx.Internal.Extensions
|
||||
{
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace CliFx.Internal
|
||||
namespace CliFx.Internal.Extensions
|
||||
{
|
||||
internal static class VersionExtensions
|
||||
{
|
||||
@@ -396,11 +396,11 @@ You can run `myapp.exe cmd1 [command] --help` to show help on a specific command
|
||||
|
||||
You may have noticed that commands in CliFx don't return exit codes. This is by design as exit codes are considered a higher-level concern and thus handled by `CliApplication`, not by individual commands.
|
||||
|
||||
Commands can report execution failure simply by throwing exceptions just like any other C# code. When an exception is thrown, `CliApplication` will catch it, print the error, and return an exit code `1` to the calling process.
|
||||
Commands can report execution failure simply by throwing exceptions just like any other C# code. When an exception is thrown, `CliApplication` will catch it, print the error, and return `1` as the exit code to the calling process.
|
||||
|
||||
If you want to communicate a specific error through exit code, you can instead throw an instance of `CommandException` which takes an exit code as a parameter. When a command throws an exception of type `CommandException`, it is assumed that this was a result of a handled error and, as such, only the exception message will be printed to the error stream. If a command throws an exception of any other type, the full stack trace will be printed as well.
|
||||
|
||||
> Please note that on Unix systems an exit code is 8-bit unsigned integer so it's strongly recommended to use exit codes between `1` and `255` otherwise it may overflow and yield unexpected results.
|
||||
> Note: Unix systems rely on 8-bit unsigned integers for exit codes, so it's strongly recommended to use values between `1` and `255` to avoid potential overflow issues.
|
||||
|
||||
```c#
|
||||
[Command]
|
||||
|
||||
Reference in New Issue
Block a user