Skip to content

Commit b910ad8

Browse files
committed
restruct: method ToArguments from string
1 parent 7c7da4f commit b910ad8

File tree

4 files changed

+109
-47
lines changed

4 files changed

+109
-47
lines changed

src/Flucli.Test/Program.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,23 @@ internal class Program
77
{
88
static void Main(string[] args)
99
{
10-
string[] _ = "explorer.exe /select,\"C:\\Windows\\explorer.exe\""
11-
.ToArguments().ToArray();
10+
// Argument parser
11+
{
12+
// Output: explorer.exe, /select,"C:\Windows\explorer.exe"
13+
string[] _1 = "explorer.exe /select,\"C:\\Windows\\explorer.exe\""
14+
.ToArguments().ToArray();
15+
16+
string _2 = new string[]
17+
{
18+
"https://test.com",
19+
"\"https://test.com\"",
20+
"https://",
21+
"https:/",
22+
"https:",
23+
"https",
24+
"/select,\"C:\\Windows\\explorer.exe\"",
25+
}.ToArguments();
26+
}
1227

1328
Task.Run(async () =>
1429
{

src/Flucli/Cli.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,10 @@ public override string ToString()
469469
{
470470
if (PipeTo != null)
471471
{
472-
return $"{FileName.ToQuoteMarkArguments()} {Arguments} | {PipeTo}";
472+
return $"{FileName.ToArguments()} {Arguments} | {PipeTo}";
473473
}
474474

475-
return $"{FileName.ToQuoteMarkArguments()} {Arguments}";
475+
return $"{FileName.ToArguments()} {Arguments}";
476476
}
477477

478478
public static Cli operator |(Cli source, PipeTarget target)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
namespace Flucli.Utils;
2+
3+
public class ArgumentBuilderOption
4+
{
5+
/// <summary>
6+
/// Default Quote
7+
/// </summary>
8+
public const string Quote = "\"";
9+
10+
/// <summary>
11+
/// <seealso cref="QuoteReplace.DoubleQuote"/>
12+
/// </summary>
13+
public const string DoubleQuote = "\"";
14+
15+
/// <summary>
16+
/// <seealso cref="QuoteReplace.BackSlashQuote"/>
17+
/// </summary>
18+
public const string BackSlashQuote = "\\\"";
19+
20+
/// <summary>
21+
/// Single instance of this class.
22+
/// </summary>
23+
public static ArgumentBuilderOption Default { get; } = new();
24+
25+
/// <summary>
26+
/// Options for handling separator within argument strings.
27+
/// </summary>
28+
public string Separator { get; set; } = " ";
29+
30+
/// <summary>
31+
/// Options for handling quotes within argument strings.
32+
/// </summary>
33+
public QuoteReplace QuoteReplace { get; set; } = QuoteReplace.None;
34+
35+
/// <summary>
36+
/// Some issues to be fixed here about url scheme.
37+
/// Which argument Starts with `https://` or `http://` should be added quote.
38+
/// </summary>
39+
public bool IsQuoteScheme { get; set; } = true;
40+
}
41+
42+
/// <summary>
43+
/// Options for handling quotes within argument strings.
44+
/// </summary>
45+
public enum QuoteReplace
46+
{
47+
/// <summary>
48+
/// No special handling for quotes
49+
/// </summary>
50+
None,
51+
52+
/// <summary>
53+
/// Replace each quote with two quotes
54+
/// </summary>
55+
DoubleQuote,
56+
57+
/// <summary>
58+
/// Escape each quote with a backslash
59+
/// </summary>
60+
BackSlashQuote,
61+
}

src/Flucli/Utils/Extensions/ArgumentExtension.cs

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Security;
45
using System.Text;
@@ -62,40 +63,52 @@ public static IEnumerable<string> ToArguments(this string cli)
6263
/// Joins a collection of arguments into a single command-line string, quoting arguments as needed.
6364
/// </summary>
6465
/// <param name="cli">The arguments to join into a command-line string.</param>
66+
/// <param name="option"></param>
6567
/// <returns>A single string representing the command-line.</returns>
66-
public static string ToArguments(this IEnumerable<string> cli)
68+
public static string ToArguments(this IEnumerable<string> cli, ArgumentBuilderOption? option = null)
6769
{
68-
return string.Join(" ", cli?.Select(arg => arg.ToQuoteMarkArguments()) ?? []);
70+
option ??= ArgumentBuilderOption.Default;
71+
72+
return string.Join(option.Separator, cli?.Select(arg => arg.ToArguments(option)) ?? []);
6973
}
7074

7175
/// <summary>
7276
/// Adds quotes to an argument string if necessary, with options for handling existing quotes.
7377
/// </summary>
7478
/// <param name="arg">The argument string to process.</param>
75-
/// <param name="quoteType">Specifies how to handle existing quotes within the argument.</param>
79+
/// <param name="option"></param>
7680
/// <returns>The argument string, possibly with added quotes.</returns>
77-
public static string ToQuoteMarkArguments(this string arg, QuoteReplace quoteType = QuoteReplace.None)
81+
public static string ToArguments(this string arg, ArgumentBuilderOption? option = null)
7882
{
7983
if (string.IsNullOrEmpty(arg))
8084
{
8185
return arg;
8286
}
8387

84-
switch (quoteType)
88+
option ??= ArgumentBuilderOption.Default;
89+
90+
string quote = ArgumentBuilderOption.Quote;
91+
92+
switch (option.QuoteReplace)
8593
{
8694
case QuoteReplace.DoubleQuote:
87-
arg = arg.Replace("\"", "\"\"");
95+
arg = arg.Replace(ArgumentBuilderOption.Quote, ArgumentBuilderOption.DoubleQuote);
96+
quote = ArgumentBuilderOption.DoubleQuote;
8897
break;
8998

9099
case QuoteReplace.BackSlashQuote:
91-
arg = arg.Replace("\"", "\\\"");
100+
arg = arg.Replace(ArgumentBuilderOption.Quote, ArgumentBuilderOption.BackSlashQuote);
101+
quote = ArgumentBuilderOption.BackSlashQuote;
92102
break;
93103
}
94104

95-
if (!(arg.StartsWith("\"") && arg.EndsWith("\"")) // If the argument is not already quoted
96-
&& arg.Contains(' ') || arg.Contains('\"')) // And if the argument contains spaces or quotes
105+
// If the argument is not already quoted
106+
// if the argument contains spaces
107+
// If the argument is a valid URI
108+
if ((!(arg.StartsWith(quote) && arg.EndsWith(quote)) && arg.Contains(' '))
109+
|| (option.IsQuoteScheme && Uri.TryCreate(arg, UriKind.Absolute, out _)))
97110
{
98-
arg = $"\"{arg}\"";
111+
arg = quote + arg + quote;
99112
}
100113
return arg;
101114
}
@@ -109,18 +122,12 @@ public static (string, IEnumerable<string>) ToFileNameWithArguments(this string
109122
{
110123
IEnumerable<string> args = cli.ToArguments();
111124

112-
if (args.Count() == 0)
113-
{
114-
return (cli, []);
115-
}
116-
else if (args.Count() == 1)
117-
{
118-
return (args.First(), []);
119-
}
120-
else
125+
return args.Count() switch
121126
{
122-
return (args.First(), args.Skip(1));
123-
}
127+
0 => (cli, []),
128+
1 => (args.First(), []),
129+
_ => (args.First(), args.Skip(1)),
130+
};
124131
}
125132

126133
/// <summary>
@@ -139,25 +146,4 @@ public static SecureString ToSecureString(this string str)
139146
secureString.MakeReadOnly();
140147
return secureString;
141148
}
142-
143-
/// <summary>
144-
/// Options for handling quotes within argument strings.
145-
/// </summary>
146-
public enum QuoteReplace
147-
{
148-
/// <summary>
149-
/// No special handling for quotes
150-
/// </summary>
151-
None,
152-
153-
/// <summary>
154-
/// Replace each quote with two quotes
155-
/// </summary>
156-
DoubleQuote,
157-
158-
/// <summary>
159-
/// Escape each quote with a backslash
160-
/// </summary>
161-
BackSlashQuote,
162-
}
163149
}

0 commit comments

Comments
 (0)