McpOptions/McpServerConfig/PlaywrightOptions with ApplyEnvironment (PLAYWRIGHT_* variables, quote-aware ExtraArgs split) and Validate; ShellWords; mcpServers from the user settings.json. New project in the solution and referenced by the extension tests.
44 lines
1.5 KiB
C#
44 lines
1.5 KiB
C#
using System.Text;
|
|
|
|
namespace Volcanic.AgenticCore.Extensions.Mcp;
|
|
|
|
/// <summary>Splits a command-line fragment into argv the way a POSIX shell would, without expansion.</summary>
|
|
internal static class ShellWords
|
|
{
|
|
/// <summary>Whitespace separates words; '…' is literal; "…" allows \" and \\. Backslashes elsewhere are kept (Windows paths).</summary>
|
|
public static IReadOnlyList<string> Split(string text)
|
|
{
|
|
var words = new List<string>();
|
|
var current = new StringBuilder();
|
|
var inWord = false;
|
|
char? quote = null;
|
|
for (var i = 0; i < text.Length; i++)
|
|
{
|
|
var c = text[i];
|
|
if (quote == '\'')
|
|
{
|
|
if (c == '\'') quote = null; else current.Append(c);
|
|
continue;
|
|
}
|
|
if (quote == '"')
|
|
{
|
|
if (c == '"') quote = null;
|
|
else if (c == '\\' && i + 1 < text.Length && text[i + 1] is '"' or '\\') current.Append(text[++i]);
|
|
else current.Append(c);
|
|
continue;
|
|
}
|
|
if (char.IsWhiteSpace(c))
|
|
{
|
|
if (inWord) { words.Add(current.ToString()); current.Clear(); inWord = false; }
|
|
continue;
|
|
}
|
|
inWord = true;
|
|
if (c is '"' or '\'') quote = c;
|
|
else current.Append(c);
|
|
}
|
|
if (quote is { } open) throw new FormatException($"unterminated {open} quote");
|
|
if (inWord) words.Add(current.ToString());
|
|
return words;
|
|
}
|
|
}
|