Skip to content

Commit

Permalink
添加对yaml文件作为变量的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
personball committed Jul 27, 2023
1 parent bd56f18 commit 060d80f
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 43 deletions.
7 changes: 7 additions & 0 deletions Generator/GenerateCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ protected static IEnumerable<Option> Options()
// yield return SyntaxOpt;
yield return VarStringOpt;
yield return VarJsonFileOpt;
yield return VarYamlFileOpt;
yield return OutputOpt;
yield return OverrideOpt;
yield return WatchOpt;
Expand Down Expand Up @@ -62,6 +63,12 @@ protected static IEnumerable<Option> Options()
parseArgument: result => result.Tokens.Select(t => t.Value.Split('=')).ToDictionary(p => p[0], p => new FileInfo(p[1]))
);

public static Option<Dictionary<string, FileInfo>> VarYamlFileOpt = new Option<Dictionary<string, FileInfo>>(
aliases: new string[] { "--var-yaml-file" },
description: VzLocales.L(VzLocales.Keys.GOptVarYamlFileOptDesc),
parseArgument: result => result.Tokens.Select(t => t.Value.Split('=')).ToDictionary(p => p[0], p => new FileInfo(p[1]))
);

public static Option<FileSystemInfo> TplPathOpt = new Option<FileSystemInfo>(
aliases: new string[] { "--template", "-t" },
description: VzLocales.L(VzLocales.Keys.GOptTplPathOptDesc)
Expand Down
44 changes: 43 additions & 1 deletion Generator/Liquid/LiquidTemplateExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.CommandLine.Invocation;
using System.Text.Json;
using System.Text.RegularExpressions;

using Scriban;
using Scriban.Runtime;
Expand All @@ -11,9 +12,11 @@
using vz_generator.Generator.Liquid.Scriban;
using vz_generator.Localization;

using YamlDotNet.Serialization;

namespace vz_generator.Generator.Liquid;

public class LiquidTemplateExecutor
public partial class LiquidTemplateExecutor
{
private readonly GeneratorSetting _setting;
private readonly InvocationContext _context;
Expand Down Expand Up @@ -54,6 +57,42 @@ public async Task ExecuteAsync()
using var json = JsonDocument.Parse(text);
variableObj.Add(item.Name, ConvertFromJson(json.RootElement));
}

if (item.Type == TemplateVariableType.YamlFile)
{
var file = new FileInfo(item.DefaultValue);
if (!file.Exists)
{
throw new ArgumentNullException("--var-yaml-file", $"{item.DefaultValue} Not Found!");
}

var text = await file.OpenText().ReadToEndAsync();
// validate yaml content if multi object separate with ---
var lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (lines.Any() && lines.Length > 1)
{
var remainLines = lines;
var firstLine = lines.First();
if (YamlObjectSeparatorRegex().IsMatch(firstLine))
{
remainLines = lines.Skip(1).ToArray();
}

if (remainLines.Any(s => YamlObjectSeparatorRegex().IsMatch(s)))
{
throw new ArgumentNullException("--var-yaml-file",
VzLocales.L(
VzLocales.Keys.GOptVarYamlFileContentContainsMultiObject));
}
}

var yamlDeserializer = new DeserializerBuilder().Build();
var yamlObject = yamlDeserializer.Deserialize(new StringReader(text));
var yamlSerializer = new SerializerBuilder().JsonCompatible().Build();

using var json = JsonDocument.Parse(yamlSerializer.Serialize(yamlObject));
variableObj.Add(item.Name, ConvertFromJson(json.RootElement));
}
}

tplContext.PushGlobal(variableObj);
Expand Down Expand Up @@ -262,4 +301,7 @@ private static object ConvertFromJson(JsonElement element)
}
private static readonly object BoolTrue = true;
private static readonly object BoolFalse = false;

[GeneratedRegex("^[-]{3,}")]
private static partial Regex YamlObjectSeparatorRegex();
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.CommandLine;

using vz_generator.Commands;
using vz_generator.Commands.Settings;

Expand Down Expand Up @@ -31,7 +33,6 @@ public async Task ResolveAsync(ResolveContext context)
await _inner.ResolveAsync(context);

// override by cli options

// variables merge 同名覆盖,不存在则添加
var vars = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.VarStringOpt) ?? new Dictionary<string, string>();
foreach (var item in vars)
Expand All @@ -53,18 +54,39 @@ public async Task ResolveAsync(ResolveContext context)
}
}

var jsons = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.VarJsonFileOpt) ?? new Dictionary<string, FileInfo>();
OverrideVariablesFileInfoIfExists(context,GenerateCommand.VarJsonFileOpt, TemplateVariableType.JsonFile);

OverrideVariablesFileInfoIfExists(context,GenerateCommand.VarYamlFileOpt, TemplateVariableType.YamlFile);

// templatePath 有则覆盖
var tplPath = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.TplPathOpt);
if (tplPath != null)
{
context.Result.TemplatePath = tplPath.FullName;
}

// output 有则覆盖
var output = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.OutputOpt);
if (output != null)
{
context.Result.Output = output.FullName;
}
}

private void OverrideVariablesFileInfoIfExists(ResolveContext context, Option<Dictionary<string, FileInfo>> opt, TemplateVariableType variableType)
{
var jsons = context.InvocationContext.ParseResult.GetValueForOption(opt) ?? new Dictionary<string, FileInfo>();
foreach (var item in jsons)
{
var entry = context.Result.Variables.FirstOrDefault(v => v.Type == TemplateVariableType.JsonFile && v.Name == item.Key);
var entry = context.Result.Variables.FirstOrDefault(v => v.Type == variableType && v.Name == item.Key);
if (entry == null)
{
context.Result.Variables.Add(
new TemplateVariable
{
Name = item.Key,
DefaultValue = item.Value.FullName,
Type = TemplateVariableType.JsonFile
Type = variableType
}
);
}
Expand All @@ -73,19 +95,5 @@ public async Task ResolveAsync(ResolveContext context)
entry.DefaultValue = item.Value.FullName;
}
}

// templatePath 有则覆盖
var tplPath = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.TplPathOpt);
if (tplPath != null)
{
context.Result.TemplatePath = tplPath.FullName;
}

// output 有则覆盖
var output = context.InvocationContext.ParseResult.GetValueForOption(GenerateCommand.OutputOpt);
if (output != null)
{
context.Result.Output = output.FullName;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,23 @@ public async Task ResolveAsync(ResolveContext context)

foreach (var item in context.Result.Variables.Where(v => string.IsNullOrWhiteSpace(v.DefaultValue)))
{
if (item.Type == TemplateVariableType.String)
{
item.DefaultValue = Prompt.Input<string>(
VzLocales.L(VzLocales.Keys.GSettingTemplateVariableValueCliPrompt, item.Name));
}
else
var promptMsg = $"Missing variable:{item.Name}";

switch (item.Type)
{
item.DefaultValue = Prompt.Input<string>(
VzLocales.L(VzLocales.Keys.GSettingTemplateVariableValueForJsonFileCliPrompt, item.Name));
case TemplateVariableType.String:
promptMsg = VzLocales.L(VzLocales.Keys.GSettingTemplateVariableValueCliPrompt, item.Name);
break;
case TemplateVariableType.JsonFile:
promptMsg = VzLocales.L(VzLocales.Keys.GSettingTemplateVariableValueForJsonFileCliPrompt, item.Name);
break;
case TemplateVariableType.YamlFile:
promptMsg = VzLocales.L(VzLocales.Keys.GSettingTemplateVariableValueForYamlFileCliPrompt, item.Name);
break;
default: break;
}

item.DefaultValue = Prompt.Input<string>(promptMsg);
}

if (string.IsNullOrWhiteSpace(context.Result.Output))
Expand Down
28 changes: 15 additions & 13 deletions Generator/Settings/TemplateVariableType.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Text.Json.Serialization;

namespace vz_generator.Commands.Settings;

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum TemplateVariableType
{
String = 0,

JsonFile = 1,
// JsonFileUri = 2
}
// TODO: load json from uri
using System.Text.Json.Serialization;

namespace vz_generator.Commands.Settings;

[JsonConverter(typeof(JsonStringEnumConverter))]
public enum TemplateVariableType
{
String = 0,

JsonFile = 1,

YamlFile = 2,
// JsonFileUri
}
// TODO: load json from uri
Binary file modified Initializer/samples.zip
Binary file not shown.
Binary file modified Localization/Resources/VzLocales.resources
Binary file not shown.
3 changes: 3 additions & 0 deletions Localization/Resources/VzLocales.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ GOptTplPathOptDesc=(Optional) specify file path of single template or directory
GOptSyntaxOptDesc=(Optional) specify syntax of template.
GOptVarStringOptDesc=(Optional) fill value for string variables, --var key1=val1 --var key2=val2 can override default value of same key in the settings, will ask for missing variables.
GOptVarJsonFileOptDesc=(Optional) fill file path for json variables, --var-json-file key1=./path/to/jsonfile --var-json-file key2=./path/to/jsonfile2 can override default value of same key in the settings, will ask for missing ones.
GOptVarYamlFileOptDesc=(Optional) fill file path for yaml variables, --var-yaml-file key1=./path/to/yamlfile --var-yaml-file key2=./path/to/yamlfile2 can override default value of same key in the settings, will ask for missing ones.
GOptVarYamlFileContentContainsMultiObject=Multiple objects (separated by '---') in one yaml file is invalid! To be a variable, every object should has its own name.
GOptOutputOptDesc=(Optional) specify output path. can override the value in settings, if both not set, default is ./output。
GOptOverrideOptDesc=(Optional) declare when output file exists, override it or not. True override it; False skip it; by default, will ask for decision of each file if not declared.
GOptWatchOptDesc=(Optional) watch file changes in template folder, hot reload, render template in time (facilitate the development of templates). In watch mode, output always override exists files.
Expand All @@ -32,6 +34,7 @@ GFailedErrorResult=Generate Fail: {0}{1}{2}
GSettingTemplatePathCliPrompt=Path of Template?
GSettingTemplateVariableValueCliPrompt=Set value of {0}
GSettingTemplateVariableValueForJsonFileCliPrompt=Set Json File Path of {0}
GSettingTemplateVariableValueForYamlFileCliPrompt=Set Yaml File Path of {0}
GSettingOutputCliPrompt=Path of Output?

GSettingFileNotFound={0} Not Found! Please run init first!
Expand Down
Binary file modified Localization/Resources/VzLocales.zh-Hans.resources
Binary file not shown.
3 changes: 3 additions & 0 deletions Localization/Resources/VzLocales.zh-Hans.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ GOptTplPathOptDesc=(可选)指定模板文件位置,可以是一个目录
GOptSyntaxOptDesc=指定模板语法,默认为 Liquid, 其他模板引擎待开发。
GOptVarStringOptDesc=(可选)指定变量键值, --var key1=val1 --var key2=val2 可以覆盖配置文件中的默认配置,若未完全覆盖,则会有交互提示输入。
GOptVarJsonFileOptDesc=(可选)指定变量键值来自一个json文件, --var-json-file key1=./path/to/jsonfile --var-json-file key2=./path/to/jsonfile2 可以覆盖配置文件中的默认配置,若未完全覆盖,则会有交互提示输入。
GOptVarYamlFileOptDesc=(可选)指定变量键值来自一个yaml文件, --var-yaml-file key1=./path/to/yamlfile --var-yaml-file key2=./path/to/yamlfile2 可以覆盖配置文件中的默认配置,若未完全覆盖,则会有交互提示输入。
GOptVarYamlFileContentContainsMultiObject=单个 Yaml 文件中不允许包含多个对象(由'---'分隔)!作为变量,每个对象应该有自己的变量名。
GOptOutputOptDesc=(可选)输出结果到指定位置。未指定则按配置文件执行,配置文件中未配置,则默认输出到./output。
GOptOverrideOptDesc=(可选)输出文件如果已存在,是否覆盖。true 全部覆盖;false 全部跳过;默认会逐个提示。
GOptWatchOptDesc=(可选) 是否监视模板文件的变更, 热重载, 及时渲染模板 (促进模板的编写)。在本模式下,输出始终覆盖已存在文件。
Expand All @@ -32,6 +34,7 @@ GFailedErrorResult=生成失败: {0}{1}{2}
GSettingTemplatePathCliPrompt=请输入模板路径
GSettingTemplateVariableValueCliPrompt=请为变量 {0} 赋值
GSettingTemplateVariableValueForJsonFileCliPrompt=请为 Json 变量 {0} 指定路径
GSettingTemplateVariableValueForYamlFileCliPrompt=请为 Yaml 变量 {0} 指定路径
GSettingOutputCliPrompt=请指定输出路径

GSettingFileNotFound={0} 不存在! 请先执行 init 命令进行初始化!
Expand Down
5 changes: 3 additions & 2 deletions Localization/VzLocales.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,18 @@ public static class Keys
public const string GOptSyntaxOptDesc = nameof(GOptSyntaxOptDesc);
public const string GOptVarStringOptDesc = nameof(GOptVarStringOptDesc);
public const string GOptVarJsonFileOptDesc = nameof(GOptVarJsonFileOptDesc);
public const string GOptVarYamlFileOptDesc = nameof(GOptVarYamlFileOptDesc);
public const string GOptVarYamlFileContentContainsMultiObject = nameof(GOptVarYamlFileContentContainsMultiObject);
public const string GOptOutputOptDesc = nameof(GOptOutputOptDesc);
public const string GOptOverrideOptDesc = nameof(GOptOverrideOptDesc);
public const string GOptWatchOptDesc = nameof(GOptWatchOptDesc);



public const string GFailedErrorResult = nameof(GFailedErrorResult);

public const string GSettingTemplatePathCliPrompt = nameof(GSettingTemplatePathCliPrompt);
public const string GSettingTemplateVariableValueCliPrompt = nameof(GSettingTemplateVariableValueCliPrompt);
public const string GSettingTemplateVariableValueForJsonFileCliPrompt = nameof(GSettingTemplateVariableValueForJsonFileCliPrompt);
public const string GSettingTemplateVariableValueForYamlFileCliPrompt = nameof(GSettingTemplateVariableValueForYamlFileCliPrompt);
public const string GSettingOutputCliPrompt = nameof(GSettingOutputCliPrompt);

public const string GSettingFileNotFound = nameof(GSettingFileNotFound);
Expand Down
4 changes: 3 additions & 1 deletion vz-generator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
v0.2.0 g command support -w to watch template folder;
v0.2.1 update readme.md;
v0.2.2 finish sample swagger2api;
v0.2.3 add sample k8s;bugfix:output to folder get access denied;
v0.2.3 add sample k8s;bugfix:output to folder get access denied;
v0.2.4 TemplateVariableType.YamlFile support;
</PackageReleaseNotes>
</PropertyGroup>

Expand All @@ -35,6 +36,7 @@
<PackageReference Include="Scriban" Version="5.7.0" />
<PackageReference Include="Sharprompt" Version="2.4.5" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="YamlDotNet" Version="13.1.1" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 060d80f

Please sign in to comment.