Skip to content

Commit 815daeb

Browse files
committed
chore: add comment
1 parent 18b355f commit 815daeb

File tree

6 files changed

+129
-4
lines changed

6 files changed

+129
-4
lines changed

src/Flucli.Test/Program.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
using System.Text;
2-
using System.Text.Unicode;
1+
using Flucli.Utils.Extensions;
2+
using System.Text;
33

44
namespace Flucli.Test;
55

66
internal class Program
77
{
88
static void Main(string[] args)
99
{
10+
string[] _ = "explorer.exe /select,\"C:\\Windows\\explorer.exe\""
11+
.ToArguments().ToArray();
12+
1013
Task.Run(async () =>
1114
{
1215
// ---
1316
Console.WriteLine("CASE1");
1417
{
15-
CliResult result = await @"D:\ema\utils\DouyinLiveRecorder\DouyinLiveRecorder.v3.0.8\DouyinLiveRecorder.exe"
18+
CliResult result = await @"test.exe"
1619
.WithArguments("")
1720
.WithStandardErrorPipe(PipeTarget.ToDelegate((a) =>
1821
{

src/Flucli/CliExtensions.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,46 @@ namespace Flucli;
66

77
public static class CliExtensions
88
{
9+
/// <summary>
10+
/// Creates a new instance of the Cli class using the provided command-line string.
11+
/// </summary>
12+
/// <param name="cli">A command-line string to initialize the Cli instance with.</param>
13+
/// <returns>A new Cli instance initialized with the given command-line string.</returns>
914
public static Cli CreateCli(this string cli)
1015
{
1116
return new Cli(cli);
1217
}
1318

19+
/// <summary>
20+
/// Creates a new instance of the Cli class using a tuple containing a file name and arguments.
21+
/// </summary>
22+
/// <param name="cli">A tuple where the first item is the file name, and the second item is an enumerable of arguments.</param>
23+
/// <returns>A new Cli instance initialized with the given file name and arguments.</returns>
1424
public static Cli CreateCli(this (string FileName, IEnumerable<string> Arguments) cli)
1525
{
1626
return new Cli(cli.FileName).WithArguments(cli.Arguments);
1727
}
1828

29+
/// <summary>
30+
/// Initializes a Cli instance with the specified command and its arguments.
31+
/// </summary>
32+
/// <param name="cli">The command to be executed.</param>
33+
/// <param name="arguments">A single string of arguments associated with the command.</param>
34+
/// <returns>A new Cli instance initialized with the given command and arguments.</returns>
1935
public static Cli WithArguments(this string cli, string arguments)
2036
{
2137
return new Cli(cli).WithArguments(arguments);
2238
}
2339

40+
/// <summary>
41+
/// Parses a command-line string into a series of chained Cli instances,
42+
/// supporting commands separated by a pipe ('|') symbol.
43+
/// Note: Parsing commands with pipe symbols in program options is not supported.
44+
/// </summary>
45+
/// <param name="cli">The command-line string to parse, potentially containing pipe symbols.</param>
46+
/// <returns>
47+
/// A Cli instance representing the first command in the chain, with linked Cli instances for each subsequent piped command.
48+
/// </returns>
2449
public static Cli ParseCli(this string cli)
2550
{
2651
// The command string containing | is uncommon.

src/Flucli/Utils/BufferSizes.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
internal static class BufferSizes
44
{
5+
/// <summary>
6+
/// Default buffer size for general stream operations, typically used to optimize data transfer.
7+
/// </summary>
58
public const int Stream = 81920;
9+
10+
/// <summary>
11+
/// Default buffer size for StreamReader operations, typically used for reading smaller chunks of data efficiently.
12+
/// </summary>
613
public const int StreamReader = 1024;
714
}

src/Flucli/Utils/Extensions/ArgumentExtension.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,73 @@ namespace Flucli.Utils.Extensions;
77

88
public static class ArgumentExtension
99
{
10+
/// <summary>
11+
/// Parses a command-line string into individual arguments, preserving quoted sections as single arguments.
12+
/// </summary>
13+
/// <param name="cli">The command-line string to parse.</param>
14+
/// <returns>An IEnumerable of parsed argument strings.</returns>
1015
public static IEnumerable<string> ToArguments(this string cli)
1116
{
1217
List<string> args = [];
1318
StringBuilder currentArg = new();
14-
bool inQuotes = false;
19+
bool inQuotes = false; // Tracks if currently inside quotes
1520

1621
for (int i = 0; i < cli.Length; i++)
1722
{
1823
char c = cli[i];
1924

2025
if (c == '"')
2126
{
27+
// Toggle quote state when encountering a quote character
2228
inQuotes = !inQuotes;
29+
30+
// Append the quote to the current argument
2331
currentArg.Append(c);
2432
}
2533
else if (c == ' ' && !inQuotes)
2634
{
35+
// If a space is encountered outside of quotes, treat it as an argument separator
2736
if (currentArg.Length > 0)
2837
{
38+
// Add the completed argument
2939
args.Add(currentArg.ToString());
40+
41+
// Clear for the next argument
3042
currentArg.Clear();
3143
}
3244
}
3345
else
3446
{
47+
// Append character to current argument
3548
currentArg.Append(c);
3649
}
3750
}
3851

3952
if (currentArg.Length > 0)
4053
{
54+
// Add the last argument if it exists
4155
args.Add(currentArg.ToString());
4256
}
4357

4458
return args;
4559
}
4660

61+
/// <summary>
62+
/// Joins a collection of arguments into a single command-line string, quoting arguments as needed.
63+
/// </summary>
64+
/// <param name="cli">The arguments to join into a command-line string.</param>
65+
/// <returns>A single string representing the command-line.</returns>
4766
public static string ToArguments(this IEnumerable<string> cli)
4867
{
4968
return string.Join(" ", cli?.Select(arg => arg.ToQuoteMarkArguments()) ?? []);
5069
}
5170

71+
/// <summary>
72+
/// Adds quotes to an argument string if necessary, with options for handling existing quotes.
73+
/// </summary>
74+
/// <param name="arg">The argument string to process.</param>
75+
/// <param name="quoteType">Specifies how to handle existing quotes within the argument.</param>
76+
/// <returns>The argument string, possibly with added quotes.</returns>
5277
public static string ToQuoteMarkArguments(this string arg, QuoteReplace quoteType = QuoteReplace.None)
5378
{
5479
if (string.IsNullOrEmpty(arg))
@@ -75,6 +100,11 @@ public static string ToQuoteMarkArguments(this string arg, QuoteReplace quoteTyp
75100
return arg;
76101
}
77102

103+
/// <summary>
104+
/// Splits a command-line string into a file name and its arguments.
105+
/// </summary>
106+
/// <param name="cli">The full command-line string.</param>
107+
/// <returns>A tuple containing the file name and an enumerable of arguments.</returns>
78108
public static (string, IEnumerable<string>) ToFileNameWithArguments(this string cli)
79109
{
80110
IEnumerable<string> args = cli.ToArguments();
@@ -93,6 +123,11 @@ public static (string, IEnumerable<string>) ToFileNameWithArguments(this string
93123
}
94124
}
95125

126+
/// <summary>
127+
/// Converts a plain string to a SecureString, which is a more secure way to handle sensitive information.
128+
/// </summary>
129+
/// <param name="str">The plain string to convert.</param>
130+
/// <returns>A SecureString containing the characters of the original string.</returns>
96131
public static SecureString ToSecureString(this string str)
97132
{
98133
SecureString secureString = new();
@@ -105,10 +140,24 @@ public static SecureString ToSecureString(this string str)
105140
return secureString;
106141
}
107142

143+
/// <summary>
144+
/// Options for handling quotes within argument strings.
145+
/// </summary>
108146
public enum QuoteReplace
109147
{
148+
/// <summary>
149+
/// No special handling for quotes
150+
/// </summary>
110151
None,
152+
153+
/// <summary>
154+
/// Replace each quote with two quotes
155+
/// </summary>
111156
DoubleQuote,
157+
158+
/// <summary>
159+
/// Escape each quote with a backslash
160+
/// </summary>
112161
BackSlashQuote,
113162
}
114163
}

src/Flucli/Utils/Extensions/StreamExtensions.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ namespace Flucli.Utils.Extensions;
77

88
internal static class StreamExtensions
99
{
10+
/// <summary>
11+
/// Asynchronously copies data from a source stream to a destination stream with an optional auto-flush feature.
12+
/// </summary>
13+
/// <param name="source">The source stream to read data from.</param>
14+
/// <param name="destination">The destination stream to write data to.</param>
15+
/// <param name="autoFlush">Whether to flush the destination stream after each write operation.</param>
16+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
1017
public static async Task CopyToAsync(this Stream source, Stream destination, bool autoFlush, CancellationToken cancellationToken = default)
1118
{
1219
byte[] buffer = new byte[BufferSizes.Stream];
@@ -33,6 +40,12 @@ await destination
3340
}
3441
}
3542

43+
/// <summary>
44+
/// Asynchronously copies data from a source stream to a destination stream without auto-flush.
45+
/// </summary>
46+
/// <param name="source">The source stream to read data from.</param>
47+
/// <param name="destination">The destination stream to write data to.</param>
48+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
3649
public static async Task CopyToAsync(this Stream source, Stream destination, CancellationToken cancellationToken)
3750
{
3851
byte[] buffer = new byte[BufferSizes.Stream];
@@ -45,6 +58,15 @@ public static async Task CopyToAsync(this Stream source, Stream destination, Can
4558
}
4659
}
4760

61+
/// <summary>
62+
/// Asynchronously reads a specified number of characters from a StreamReader into a buffer.
63+
/// </summary>
64+
/// <param name="reader">The StreamReader to read from.</param>
65+
/// <param name="buffer">The character array buffer to store read characters.</param>
66+
/// <param name="index">The starting index in the buffer to begin storing read characters.</param>
67+
/// <param name="count">The maximum number of characters to read.</param>
68+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
69+
/// <returns>The total number of characters read.</returns>
4870
public static async Task<int> ReadAsync(this StreamReader reader, char[] buffer, int index, int count, CancellationToken cancellationToken = default)
4971
{
5072
_ = reader ?? throw new ArgumentNullException(nameof(reader));

src/Flucli/Utils/Extensions/TaskExtensions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ namespace Flucli.Utils.Extensions;
66

77
internal static class TaskExtensions
88
{
9+
/// <summary>
10+
/// Waits for the specified task to complete within the given timeout period or throws a TimeoutException if it doesn't.
11+
/// Also accepts a CancellationToken to allow task cancellation.
12+
/// </summary>
13+
/// <param name="task">The task to wait on.</param>
14+
/// <param name="timeout">The maximum time to wait for the task to complete.</param>
15+
/// <param name="cancellationToken">The token to observe for cancellation.</param>
16+
/// <exception cref="TimeoutException">Thrown if the task does not complete within the specified timeout.</exception>
917
public static async Task WaitAsync(this Task task, TimeSpan timeout, CancellationToken cancellationToken)
1018
{
1119
Task cancellationTask = Task.Delay(timeout, cancellationToken);
@@ -19,9 +27,20 @@ public static async Task WaitAsync(this Task task, TimeSpan timeout, Cancellatio
1927
}
2028
}
2129

30+
/// <summary>
31+
/// Waits for the specified task to complete, allowing cancellation via the CancellationToken.
32+
/// </summary>
33+
/// <param name="task">The task to wait on.</param>
34+
/// <param name="cancellationToken">The token to observe for cancellation.</param>
2235
public static async Task WaitAsync(this Task task, CancellationToken cancellationToken)
2336
=> await task.WaitAsync(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false);
2437

38+
/// <summary>
39+
/// Waits for the specified task to complete within the given timeout period.
40+
/// </summary>
41+
/// <param name="task">The task to wait on.</param>
42+
/// <param name="timeout">The maximum time to wait for the task to complete.</param>
43+
/// <exception cref="TimeoutException">Thrown if the task does not complete within the specified timeout.</exception>
2544
public static async Task WaitAsync(this Task task, TimeSpan timeout)
2645
=> await task.WaitAsync(timeout, CancellationToken.None).ConfigureAwait(false);
2746
}

0 commit comments

Comments
 (0)