|
9 | 9 |
|
10 | 10 | namespace PoshCode.Pansies.Commands |
11 | 11 | { |
12 | | - |
13 | | - |
14 | | - [Cmdlet("Expand","Variable")] |
| 12 | + [Cmdlet("Expand", "Variable", DefaultParameterSetName = "Content")] |
15 | 13 | public class ExpandVariableCommand : PSCmdlet |
16 | 14 | { |
17 | | - [Parameter(Mandatory = true, Position = 0)] |
| 15 | + [Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true, ParameterSetName = "Path")] |
| 16 | + [Alias("PSPath")] |
18 | 17 | public string Path { get; set; } |
19 | 18 |
|
| 19 | + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = "Content")] |
| 20 | + public string Content { get; set; } |
| 21 | + |
20 | 22 | [Parameter()] |
21 | 23 | public SwitchParameter Unescaped { get; set; } |
22 | 24 |
|
23 | 25 | [Parameter()] |
24 | 26 | public string[] Drive { get; set; } = ["bg", "emoji", "esc", "extra", "fg", "nf"]; |
25 | 27 |
|
26 | | - [Parameter()] |
| 28 | + [Parameter(ParameterSetName = "Path")] |
27 | 29 | public SwitchParameter InPlace { get; set; } |
28 | 30 |
|
29 | | - protected override void EndProcessing() |
| 31 | + [Parameter(ParameterSetName = "Path")] |
| 32 | + public SwitchParameter Passthru { get; set; } |
| 33 | + |
| 34 | + protected override void ProcessRecord() |
30 | 35 | { |
| 36 | + if (ParameterSetName == "Content") |
| 37 | + { |
| 38 | + var result = ExpandVariable(Content, "Content"); |
| 39 | + WriteObject(result); |
| 40 | + return; |
| 41 | + } |
| 42 | + |
31 | 43 | var resolvedProviderPath = GetResolvedProviderPathFromPSPath(Path, out ProviderInfo provider); |
32 | | - foreach (var file in resolvedProviderPath) { |
33 | | - var result = new StringBuilder(); |
34 | | - var replacements = new List<TextReplacement>(); |
35 | | - Ast ast = null; |
36 | | - string code; |
| 44 | + foreach (var file in resolvedProviderPath) |
| 45 | + { |
37 | 46 | string fullName = file; |
38 | 47 | if (provider.Name != "Variable" && provider.Name != "FileSystem" && !fullName.Contains(":")) |
39 | 48 | { |
40 | 49 | fullName = $"{provider.Name}:{file}"; |
41 | 50 | } |
42 | | - code = GetVariableValue(fullName).ToString(); |
43 | | - ast = Parser.ParseInput(code, fullName, out var tokens, out var parseErrors); |
44 | | - if (parseErrors.Length > 0) { |
45 | | - WriteError(new ErrorRecord(new Exception($"{parseErrors.Length} Parse Errors in {fullName}, cannot expand."), "ParseErrors", ErrorCategory.InvalidOperation, fullName)); |
46 | | - continue; |
47 | | - } |
48 | | - result.AppendLine(code); |
49 | | - |
50 | | - var variables = ast.FindAll(a => a is VariableExpressionAst, true). |
51 | | - Cast<VariableExpressionAst>(). |
52 | | - Where(v => (!v.VariablePath.IsUnqualified || // variable:foo is IsUnqualified = False and IsVariable = True |
53 | | - v.VariablePath.IsDriveQualified) && // fg:red is IsDriveQualified = True and IsVariable = False |
54 | | - Drive.Contains(v.VariablePath.DriveName ?? "variable", StringComparer.OrdinalIgnoreCase)); |
| 51 | + string code = GetVariableValue(fullName).ToString(); |
| 52 | + var result = ExpandVariable(code, fullName); |
55 | 53 |
|
56 | | - foreach (var variable in variables) |
| 54 | + if (result != null) |
57 | 55 | { |
58 | | - try |
| 56 | + if (InPlace) |
59 | 57 | { |
60 | | - var replacement = GetVariableValue(variable.VariablePath.UserPath).ToString(); |
61 | | - if (!Unescaped) |
62 | | - { |
63 | | - replacement = replacement.ToPsEscapedString(); |
64 | | - } |
65 | | - if (variable.Parent is ExpandableStringExpressionAst) |
| 58 | + SessionState.PSVariable.Set(fullName, result); |
| 59 | + if (Passthru) |
66 | 60 | { |
67 | | - replacements.Add(new TextReplacement(replacement, variable.Extent)); |
68 | | - } |
69 | | - else |
70 | | - { |
71 | | - replacements.Add(new TextReplacement('"' + replacement + '"', variable.Extent)); |
| 61 | + WriteObject(SessionState.InvokeProvider.Item.Get(fullName), true); |
72 | 62 | } |
73 | 63 | } |
74 | | - catch |
| 64 | + else |
75 | 65 | { |
76 | | - WriteWarning($"VariableNotFound: '{variable.VariablePath.UserPath}' at {fullName}:{variable.Extent.StartLineNumber}:{variable.Extent.StartColumnNumber}"); |
77 | | - continue; |
| 66 | + WriteObject(result); |
78 | 67 | } |
79 | 68 | } |
| 69 | + } |
| 70 | + } |
80 | 71 |
|
81 | | - foreach (var replacement in replacements.OrderByDescending(r => r.StartOffset)) |
82 | | - { |
83 | | - result.Remove(replacement.StartOffset, replacement.Length).Insert(replacement.StartOffset, replacement.Text); |
84 | | - } |
| 72 | + private string ExpandVariable(string code, string fullName = null) |
| 73 | + { |
| 74 | + var builder = new StringBuilder(code); |
| 75 | + var replacements = new List<TextReplacement>(); |
| 76 | + Ast ast = null; |
| 77 | + ast = Parser.ParseInput(code, fullName, out var tokens, out var parseErrors); |
| 78 | + if (parseErrors.Length > 0) |
| 79 | + { |
| 80 | + WriteError(new ErrorRecord(new Exception($"{parseErrors.Length} Parse Errors in {fullName}, cannot expand."), "ParseErrors", ErrorCategory.InvalidOperation, fullName)); |
| 81 | + return null; |
| 82 | + } |
| 83 | + |
| 84 | + var variables = ast.FindAll(a => a is VariableExpressionAst, true). |
| 85 | + Cast<VariableExpressionAst>(). |
| 86 | + Where(v => (!v.VariablePath.IsUnqualified || // variable:foo is IsUnqualified = False and IsVariable = True |
| 87 | + v.VariablePath.IsDriveQualified) && // fg:red is IsDriveQualified = True and IsVariable = False |
| 88 | + Drive.Contains(v.VariablePath.DriveName ?? "variable", StringComparer.OrdinalIgnoreCase)); |
85 | 89 |
|
86 | | - if (InPlace) |
| 90 | + foreach (var variable in variables) |
| 91 | + { |
| 92 | + try |
87 | 93 | { |
88 | | - SessionState.PSVariable.Set(fullName, result.ToString()); |
| 94 | + var replacement = GetVariableValue(variable.VariablePath.UserPath).ToString(); |
| 95 | + if (!Unescaped) |
| 96 | + { |
| 97 | + replacement = replacement.ToPsEscapedString(); |
| 98 | + } |
| 99 | + if (variable.Parent is ExpandableStringExpressionAst) |
| 100 | + { |
| 101 | + replacements.Add(new TextReplacement(replacement, variable.Extent)); |
| 102 | + } |
| 103 | + else |
| 104 | + { |
| 105 | + replacements.Add(new TextReplacement('"' + replacement + '"', variable.Extent)); |
| 106 | + } |
89 | 107 | } |
90 | | - else |
| 108 | + catch |
91 | 109 | { |
92 | | - WriteObject(result.ToString()); |
| 110 | + WriteWarning($"VariableNotFound: '{variable.VariablePath.UserPath}' at {fullName}:{variable.Extent.StartLineNumber}:{variable.Extent.StartColumnNumber}"); |
| 111 | + continue; |
93 | 112 | } |
94 | | - |
95 | 113 | } |
96 | 114 |
|
| 115 | + foreach (var replacement in replacements.OrderByDescending(r => r.StartOffset)) |
| 116 | + { |
| 117 | + builder.Remove(replacement.StartOffset, replacement.Length).Insert(replacement.StartOffset, replacement.Text); |
| 118 | + } |
| 119 | + return builder.ToString(); |
97 | 120 | } |
98 | 121 |
|
99 | 122 | private class TextReplacement(string text, IScriptExtent extent) |
|
0 commit comments