diff options
| author | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-13 13:22:20 +1000 |
|---|---|---|
| committer | Melodi <62381002+Melodi17@users.noreply.github.com> | 2026-09-13 13:22:20 +1000 |
| commit | df0737e55afeb5c01eb39909605970d1d3a73ffc (patch) | |
| tree | 09823eaa310c60eefd2420dc305acae45c81900f /src/marlin.core/util/VariableExpander.cs | |
| parent | ee69ce25b2fba871920260028bb10c2d6b62b26f (diff) | |
refactor: cleanup; feat: connection to agent
Diffstat (limited to 'src/marlin.core/util/VariableExpander.cs')
| -rw-r--r-- | src/marlin.core/util/VariableExpander.cs | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/marlin.core/util/VariableExpander.cs b/src/marlin.core/util/VariableExpander.cs new file mode 100644 index 0000000..3c3636e --- /dev/null +++ b/src/marlin.core/util/VariableExpander.cs @@ -0,0 +1,140 @@ +namespace marlin.core.util; + +using System.Text; +using System.Text.RegularExpressions; + +public class VariableExpander +{ + public static string Expand(string format, Dictionary<string, string> variables) + { + StringBuilder output = new(); + + for (int i = 0; i < format.Length; i++) + { + char c = format[i]; + if (c == '{') + { + if (i + 1 >= format.Length) + throw new UnmatchedBraceException("Trailing expression '{'", i, format[i..]); + + if (format[i + 1] == '{') + { + output.Append('{'); + i++; + } + else + { + string expr = GetExpression(format, ref i); + string value = EvaluateExpression(expr, variables); + output.Append(value); + } + } + else if (c == '}') + { + if (i + 1 >= format.Length) + throw new UnmatchedBraceException("Uninitiated expression at '}'", i, format[i..]); + + if (format[i + 1] == '}') + { + output.Append('}'); + i++; + } + else + { + throw new UnmatchedBraceException("Uninitiated expression at '}'", i, format[i..]); + } + } + else + output.Append(c); + } + + string result = output.ToString(); + + // Clean up extra spaces: collapse multiple consecutive spaces (but preserve other whitespace) + result = Regex.Replace(result, @" {2,}", " "); + result = result.Trim(); + + return result; + } + + private static string GetExpression(string format, ref int pos) + { + StringBuilder part = new(); + + if (format[pos] != '{') + throw new InvalidExpressionException(format[pos..], "Expected '{' at start of expression"); + + pos++; + + for (; pos < format.Length; pos++) + { + if (format[pos] == '}') + break; + + part.Append(format[pos]); + } + + if (pos >= format.Length || format[pos] != '}') + throw new UnmatchedBraceException($"Trailing expression {format[pos..]}", pos, format[pos..]); + + return part.ToString(); + } + + private static string EvaluateExpression(string expr, Dictionary<string, string> variables) + { + Match match; + + const string identifier = "[a-zA-Z0-9-_.]+"; + + // Variable value + match = Regex.Match(expr, $"^{identifier}$"); + if (match.Success) + return GetVariableOrThrow(expr, variables); + + // Conditional argument: only included if variable is set. + // --hello var + match = Regex.Match(expr, $"^(--?{identifier})\\s+({identifier})$"); + if (match.Success) + { + if (variables.TryGetValue(match.Groups[2].Value, out var value)) + return $"{match.Groups[1].Value} {value}"; + + else + return ""; + } + + // Default value, if value is unset, uses default + match = Regex.Match(expr, $@"^({identifier})\s*=\s*(.*)$"); + if (match.Success) + { + if (variables.TryGetValue(match.Groups[1].Value, out var value)) + return value; + else + return match.Groups[2].Value; + } + + // Use value if set + match = Regex.Match(expr, $@"^({identifier})\?\s*(.*)$"); + if (match.Success) + { + if (variables.TryGetValue(match.Groups[1].Value, out var value)) + { + if (string.IsNullOrEmpty(value) || value == "null" || value == "false") + return ""; + + return match.Groups[2].Value; + } + else + return ""; + } + + throw new InvalidExpressionException(expr); + } + + private static string GetVariableOrThrow(string variable, Dictionary<string, string> variables) + { + return variables.TryGetValue(variable, out var value) + ? value + : throw new VariableNotFoundException(variable); + } +}
\ No newline at end of file |
