Skip to content

Commit ab02108

Browse files
committed
Added environment variables fallback
1 parent 738e06b commit ab02108

File tree

4 files changed

+31
-21
lines changed

4 files changed

+31
-21
lines changed

Clap.Net/Attributes.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ public sealed class ArgAttribute : Attribute
2929
public string? Description { get; init; }
3030
public bool Required { get; init; }
3131
public bool Last { get; init; }
32+
public string? Env { get; init; }
3233
}

Clap.Net/ClapGenerator.cs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ internal record NamedArgumentModel(
3838
string? Description,
3939
char? ShortName,
4040
string? LongName,
41+
string? Env,
4142
ITypeSymbol MemberType,
4243
bool Required
4344
) : ArgumentModel(Symbol, MemberType, VariableName);
@@ -177,6 +178,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
177178
var shortName = argAttribute.NamedArguments.FirstOrDefault(a => a.Key is nameof(ArgAttribute.ShortName)).Value.Value;
178179
var longName = argAttribute.NamedArguments.FirstOrDefault(a => a.Key is nameof(ArgAttribute.LongName)).Value.Value;
179180
var required = argAttribute.NamedArguments.FirstOrDefault(a => a.Key is nameof(ArgAttribute.Required)).Value.Value;
181+
var env = argAttribute.NamedArguments.FirstOrDefault(a => a.Key is nameof(ArgAttribute.Env)).Value.Value;
180182

181183
if (shortName is not null || longName is not null)
182184
{
@@ -187,6 +189,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
187189
description as string,
188190
shortName as char?,
189191
longName as string,
192+
env as string,
190193
memberType,
191194
required as bool? ?? false
192195
));
@@ -317,7 +320,10 @@ public partial {{commandModel.Kind}} {{typeName}}
317320
case NamedArgumentModel arg:
318321
{
319322
var type = arg.MemberType.ToDisplayString(TypeNameFormat);
320-
var defaultValue = GetDefaultValueString(arg.MemberType);
323+
var initialValue = GetDefaultValueString(arg.MemberType);
324+
var defaultValue = arg.Env is { } env
325+
? $"Environment.GetEnvironmentVariable(\"{env}\") is {{ }} env ? {GetArgConversion(arg.MemberType, "env")} : {initialValue}"
326+
: initialValue;
321327

322328
writer.WriteLine($"// Argument '{arg.Symbol.Name}' is a named argument");
323329
writer.WriteLine($"{type} {arg.VariableName} = {defaultValue};");
@@ -607,29 +613,29 @@ private static void WriteArraySetter(Utf8IndentedWriter writer, string variableN
607613
""");
608614
}
609615

610-
private static string? GetArgConversion(ITypeSymbol member)
616+
private static string? GetArgConversion(ITypeSymbol member, string variableName = "args[index]")
611617
{
612618
var nullable = member.NullableAnnotation is NullableAnnotation.Annotated;
613619
return member.ToDisplayString(TypeNameFormat).TrimEnd('?') switch
614620
{
615-
"System.String" => "args[index]",
616-
"System.Int32" => nullable ? $"int.TryParse(args[index], out var v) ? v : null" : $"int.Parse(args[index])",
617-
"System.Int64" => nullable ? $"long.TryParse(args[index], out var v) ? v : null" : $"long.Parse(args[index])",
618-
"System.Single" => nullable ? $"float.TryParse(args[index], out var v) ? v : null" : $"float.Parse(args[index])",
619-
"System.Double" => nullable ? $"double.TryParse(args[index], out var v) ? v : null" : $"double.Parse(args[index])",
620-
"System.Decimal" => nullable ? $"decimal.TryParse(args[index], out var v) ? v : null" : $"decimal.Parse(args[index])",
621-
"System.Boolean" => nullable ? $"bool.TryParse(args[index], out var v) ? v : null" : $"bool.Parse(args[index])",
622-
"System.Byte" => nullable ? $"byte.TryParse(args[index], out var v) ? v : null" : $"byte.Parse(args[index])",
623-
"System.SByte" => nullable ? $"sbyte.TryParse(args[index], out var v) ? v : null" : $"sbyte.Parse(args[index])",
624-
"System.Int16" => nullable ? $"short.TryParse(args[index], out var v) ? v : null" : $"short.Parse(args[index])",
625-
"System.UInt16" => nullable ? $"ushort.TryParse(args[index], out var v) ? v : null" : $"ushort.Parse(args[index])",
626-
"System.UInt32" => nullable ? $"uint.TryParse(args[index], out var v) ? v : null" : $"uint.Parse(args[index])",
627-
"System.UInt64" => nullable ? $"ulong.TryParse(args[index], out var v) ? v : null" : $"ulong.Parse(args[index])",
628-
"System.Char" => nullable ? $"char.TryParse(args[index], out var v) ? v : null" : $"char.Parse(args[index])",
629-
"System.DateTime" => nullable ? $"DateTime.TryParse(args[index], out var v) ? v : null" : $"DateTime.Parse(args[index])",
630-
"System.TimeSpan" => nullable ? $"TimeSpan.TryParse(args[index], out var v) ? v : null" : $"TimeSpan.Parse(args[index])",
631-
"System.Guid" => nullable ? $"Guid.TryParse(args[index], out var v) ? v : null" : $"Guid.Parse(args[index])",
632-
var other => $"Convert.ChangeType(args[index], typeof({(nullable ? $"{other}?" : other)}))"
621+
"System.String" => variableName,
622+
"System.Int32" => nullable ? $"int.TryParse({variableName}, out var v) ? v : null" : $"int.Parse({variableName})",
623+
"System.Int64" => nullable ? $"long.TryParse({variableName}, out var v) ? v : null" : $"long.Parse({variableName})",
624+
"System.Single" => nullable ? $"float.TryParse({variableName}, out var v) ? v : null" : $"float.Parse({variableName})",
625+
"System.Double" => nullable ? $"double.TryParse({variableName}, out var v) ? v : null" : $"double.Parse({variableName})",
626+
"System.Decimal" => nullable ? $"decimal.TryParse({variableName}, out var v) ? v : null" : $"decimal.Parse({variableName})",
627+
"System.Boolean" => nullable ? $"bool.TryParse({variableName}, out var v) ? v : null" : $"bool.Parse({variableName})",
628+
"System.Byte" => nullable ? $"byte.TryParse({variableName}, out var v) ? v : null" : $"byte.Parse({variableName})",
629+
"System.SByte" => nullable ? $"sbyte.TryParse({variableName}, out var v) ? v : null" : $"sbyte.Parse({variableName})",
630+
"System.Int16" => nullable ? $"short.TryParse({variableName}, out var v) ? v : null" : $"short.Parse({variableName})",
631+
"System.UInt16" => nullable ? $"ushort.TryParse({variableName}, out var v) ? v : null" : $"ushort.Parse({variableName})",
632+
"System.UInt32" => nullable ? $"uint.TryParse({variableName}, out var v) ? v : null" : $"uint.Parse({variableName})",
633+
"System.UInt64" => nullable ? $"ulong.TryParse({variableName}, out var v) ? v : null" : $"ulong.Parse({variableName})",
634+
"System.Char" => nullable ? $"char.TryParse({variableName}, out var v) ? v : null" : $"char.Parse({variableName})",
635+
"System.DateTime" => nullable ? $"DateTime.TryParse({variableName}, out var v) ? v : null" : $"DateTime.Parse({variableName})",
636+
"System.TimeSpan" => nullable ? $"TimeSpan.TryParse({variableName}, out var v) ? v : null" : $"TimeSpan.Parse({variableName})",
637+
"System.Guid" => nullable ? $"Guid.TryParse({variableName}, out var v) ? v : null" : $"Guid.Parse({variableName})",
638+
var other => $"Convert.ChangeType({variableName}, typeof({(nullable ? $"{other}?" : other)}))"
633639
};
634640
}
635641

Clap.TestConsole/Examples/Git.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ namespace Clap.TestConsole.Examples;
55
[Command(Name = "git", Summary = "A fictional versioning CLI")]
66
public partial struct Git
77
{
8+
[Arg(ShortName = 'u', LongName = "username", Env = "GIT_USER_NAME", Description = "The user name to use for the commit")]
9+
public string? UserName { get; init; }
10+
811
[Arg(ShortName = 'v', Description = "Prints verbose output")]
912
public bool Verbose { get; init; }
1013

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ dotnet run -- "~/Downloads/tree.png" -e "jpg" publish "https://yourdomain.com/up
101101
- [ ] [Option] (named arguments)
102102
- [x] Short and long flags (e.g., -v, --verbose)
103103
- [x] Aliases for options
104-
- [ ] Environment variable fallback
104+
- [x] Environment variable fallback
105105
- [x] Default values (handled by language)
106106
- [x] Required vs optional
107107
- [ ] [Switch] (bool flags)

0 commit comments

Comments
 (0)