Skip to content

Commit cbf4cc8

Browse files
committed
Breaking change: enforce construction-time metadata
1 parent 2c80b2b commit cbf4cc8

5 files changed

Lines changed: 38 additions & 46 deletions

File tree

src/XenoAtom.CommandLine.Terminal.Tests/TerminalMarkupCommandOutputTests.cs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,12 @@ public async Task Help_IsRendered_WithMarkupOutput()
2424
{
2525
UseTerminalWindowWidth = false,
2626
})
27-
})
28-
{
29-
new CommandUsage(),
30-
"Options:",
31-
{ "n|name=", "The {NAME}", _ => { } },
32-
new HelpOption(),
33-
(ctx, _) => ValueTask.FromResult(0)
34-
};
35-
36-
app.Options["name"].EnvironmentVariable = "APP_NAME";
27+
});
28+
app.Add(new CommandUsage());
29+
app.Add("Options:");
30+
app.Add("n|name=", "The {NAME}", _ => { }, envVar: "APP_NAME", hidden: false);
31+
app.Add(new HelpOption());
32+
app.Add((ctx, _) => ValueTask.FromResult(0));
3733

3834
var result = await app.RunAsync(["--help"], new CommandRunConfig(Width: 80));
3935
Assert.AreEqual(0, result);
@@ -120,12 +116,9 @@ public async Task Error_ContainsEnvironmentVariableSourceContext()
120116
{
121117
EnvironmentVariableResolver = _ => "oops",
122118
OutputFactory = _ => new TerminalMarkupCommandOutput()
123-
})
124-
{
125-
{ "a|age=", "Age", (int _) => { } },
126-
(ctx, _) => ValueTask.FromResult(0)
127-
};
128-
app.Options["age"].EnvironmentVariable = "APP_AGE";
119+
});
120+
app.Add("a|age=", "Age", (int _) => { }, envVar: "APP_AGE");
121+
app.Add((ctx, _) => ValueTask.FromResult(0));
129122

130123
var result = await app.RunAsync([]);
131124
Assert.AreEqual(1, result);
@@ -149,9 +142,9 @@ public async Task Help_DoesNotRenderHiddenOptionsArgumentsAndCommands()
149142

150143
var hiddenCommand = new Command("hidden-cmd", hiddenCommandDescription)
151144
{
152-
(ctx, _) => ValueTask.FromResult(0)
145+
Hidden = true,
153146
};
154-
hiddenCommand.Hidden = true;
147+
hiddenCommand.Add((ctx, _) => ValueTask.FromResult(0));
155148

156149
var app = new CommandApp(
157150
"app",

src/XenoAtom.CommandLine.Terminal.Tests/TerminalVisualCommandOutputTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ public async Task VisualOutput_Help_DoesNotRenderHiddenOptionsArgumentsAndComman
238238

239239
var hiddenCommand = new Command("hidden-cmd", hiddenCommandDescription)
240240
{
241-
(ctx, _) => ValueTask.FromResult(0)
241+
Hidden = true,
242242
};
243-
hiddenCommand.Hidden = true;
243+
hiddenCommand.Add((ctx, _) => ValueTask.FromResult(0));
244244

245245
var app = new CommandApp(
246246
"app",

src/XenoAtom.CommandLine/Command.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public Command(string name, string? help = null, Func<bool>? active = null) : ba
5454
/// <summary>
5555
/// Gets or sets a boolean indicating if this command is hidden from help.
5656
/// </summary>
57-
public bool Hidden { get; set; }
57+
public bool Hidden { get; init; }
5858

5959
/// <summary>
6060
/// Gets the description of this command.
@@ -69,7 +69,7 @@ public Command(string name, string? help = null, Func<bool>? active = null) : ba
6969
/// <summary>
7070
/// Gets the name of the options used when creating the usage help for this command.
7171
/// </summary>
72-
public string OptionsSectionName { get; set; }
72+
public string OptionsSectionName { get; init; }
7373

7474
/// <summary>
7575
/// Gets the sub-commands of this command.

src/XenoAtom.CommandLine/CommandExtensions.cs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,12 @@ public static TCommand Add<TCommand>(
217217
if (CommandArgument.IsArgumentPrototype(prototype))
218218
throw new ArgumentException("Environment variable fallback is only supported for options, not positional arguments.", nameof(prototype));
219219

220-
var option = new ActionOption(prototype, description, 1, delegate (OptionValueCollection v) { action(v[0]); }, hidden);
221-
ConfigureOptionEnvironment(option, envVar, envVarDelimiter);
220+
ArgumentException.ThrowIfNullOrWhiteSpace(envVar);
221+
var option = new ActionOption(prototype, description, 1, delegate (OptionValueCollection v) { action(v[0]); }, hidden)
222+
{
223+
EnvironmentVariable = envVar,
224+
EnvironmentVariableDelimiter = envVarDelimiter
225+
};
222226
command.Add(option);
223227
return command;
224228
}
@@ -260,11 +264,12 @@ public static TCommand Add<TCommand>(
260264
return command;
261265
}
262266

263-
var option = new ActionOption(prototype, description, 1, delegate (OptionValueCollection v) { action(v[0]); }, hidden, validate);
264-
if (!string.IsNullOrWhiteSpace(envVar))
267+
var normalizedEnvVar = string.IsNullOrWhiteSpace(envVar) ? null : envVar;
268+
var option = new ActionOption(prototype, description, 1, delegate (OptionValueCollection v) { action(v[0]); }, hidden, validate)
265269
{
266-
ConfigureOptionEnvironment(option, envVar, envVarDelimiter);
267-
}
270+
EnvironmentVariable = normalizedEnvVar,
271+
EnvironmentVariableDelimiter = normalizedEnvVar is null ? null : envVarDelimiter
272+
};
268273
command.Add(option);
269274
return command;
270275
}
@@ -747,11 +752,12 @@ private static TCommand AddTypedAction<TCommand, T>(
747752
return command;
748753
}
749754

750-
var option = new ActionOption<T>(prototype, description, action, validate, hidden);
751-
if (!string.IsNullOrWhiteSpace(envVar))
755+
var normalizedEnvVar = string.IsNullOrWhiteSpace(envVar) ? null : envVar;
756+
var option = new ActionOption<T>(prototype, description, action, validate, hidden)
752757
{
753-
ConfigureOptionEnvironment(option, envVar, envVarDelimiter);
754-
}
758+
EnvironmentVariable = normalizedEnvVar,
759+
EnvironmentVariableDelimiter = normalizedEnvVar is null ? null : envVarDelimiter
760+
};
755761

756762
command.Add(option);
757763
return command;
@@ -781,11 +787,12 @@ private static TCommand AddTypedList<TCommand, T>(
781787
return command;
782788
}
783789

784-
var option = new ActionOption<T>(prototype, description, list.Add, validate, hidden);
785-
if (!string.IsNullOrWhiteSpace(envVar))
790+
var normalizedEnvVar = string.IsNullOrWhiteSpace(envVar) ? null : envVar;
791+
var option = new ActionOption<T>(prototype, description, list.Add, validate, hidden)
786792
{
787-
ConfigureOptionEnvironment(option, envVar, envVarDelimiter);
788-
}
793+
EnvironmentVariable = normalizedEnvVar,
794+
EnvironmentVariableDelimiter = normalizedEnvVar is null ? null : envVarDelimiter
795+
};
789796

790797
command.Add(option);
791798
return command;
@@ -800,14 +807,6 @@ private static void EnsurePrototypeIsNotRemainder(string prototype, bool isListB
800807
}
801808
}
802809

803-
private static void ConfigureOptionEnvironment(Option option, string envVar, char? envVarDelimiter)
804-
{
805-
ArgumentNullException.ThrowIfNull(option);
806-
ArgumentException.ThrowIfNullOrWhiteSpace(envVar);
807-
option.EnvironmentVariable = envVar;
808-
option.EnvironmentVariableDelimiter = envVarDelimiter;
809-
}
810-
811810
private sealed class ActionOption<T> : Option
812811
where T : ISpanParsable<T>
813812
{

src/XenoAtom.CommandLine/Option.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public string[] GetValueSeparators()
123123
/// Gets or sets the environment variable used as a fallback when this option
124124
/// is not provided explicitly on the command line.
125125
/// </summary>
126-
public string? EnvironmentVariable { get; set; }
126+
public string? EnvironmentVariable { get; init; }
127127

128128
/// <summary>
129129
/// Gets or sets the delimiter used to split an environment variable value into
@@ -132,7 +132,7 @@ public string[] GetValueSeparators()
132132
/// <remarks>
133133
/// When null, the environment variable value is treated as a single occurrence.
134134
/// </remarks>
135-
public char? EnvironmentVariableDelimiter { get; set; }
135+
public char? EnvironmentVariableDelimiter { get; init; }
136136

137137
internal bool WasSetOnCommandLine { get; set; }
138138

0 commit comments

Comments
 (0)