Skip to content

Commit aa93270

Browse files
Merge pull request #283 from StartAutomating/PipeScriptUpdates
PipeScript 0.1.9
2 parents 017971d + 6cf25d8 commit aa93270

File tree

112 files changed

+998
-328
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

112 files changed

+998
-328
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## 0.1.9:
2+
* Protocol Transpilers
3+
* Adding JSONSchema transpiler (Fixes #274)
4+
* HTTP Protocol: Only allowing HTTP Methods (Fixes #275)
5+
* Keyword improvements:
6+
* all scripts in $directory (Fixes #277)
7+
* 'new' keyword recursively transpiles constructor arguments (Fixes #271)
8+
* Core improvements:
9+
* Core Transpiler stops transpilation of an item after any output (Fixes #280)
10+
* [CommandAst].AsSentence now maps singleton values correctly (Fixes #279)
11+
* PipeScript now handles CommandNotFound, enabling interactive use (Fixes #281)
12+
13+
---
14+
115
## 0.1.8:
216
* Improvements to 'all' keyword (#264 #263 #260 #253)
317
* Keywords can now be run interactively (#263)

Invoke-PipeScript.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
if ($PotentialCommand -is [string]) { return $true }
3939
if ($PotentialCommand -is [Management.Automation.CommandInfo]) { return $true }
4040
if ($PotentialCommand.GetType().Namespace -eq 'System.Management.Automation.Language' -and
41-
$PotentialCommand.GetType().Name -in 'AttributeAST', 'TypeExpressionAST','InvokeMemberExpressionAst') {
41+
$PotentialCommand.GetType().Name -in 'AttributeAST', 'TypeConstraintAst','TypeExpressionAST','InvokeMemberExpressionAst') {
4242
return $true
4343
}
4444

ListOfTranspilers.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ These are all of the transpilers currently included in PipeScript:
5959
|[Inline.TypeScript](Transpilers/Inline/Inline.TypeScript.psx.ps1) |TypeScript Inline PipeScript Transpiler. |
6060
|[Inline.XML](Transpilers/Inline/Inline.XML.psx.ps1) |XML Inline PipeScript Transpiler. |
6161
|[Inline.YAML](Transpilers/Inline/Inline.YAML.psx.ps1) |Yaml File Transpiler. |
62+
|[JSONSchema.Protocol](Transpilers/Protocols/JSONSchema.Protocol.psx.ps1) |json schema protocol |
6263
|[ModuleExports](Transpilers/Modules/ModuleExports.psx.ps1) |Gets Module Exports |
6364
|[ModuleRelationship](Transpilers/Modules/ModuleRelationship.psx.ps1) |Gets Module Relationships |
6465
|[New](Transpilers/Keywords/New.psx.ps1) |'new' keyword |

PipeScript.ps1.psm1

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,91 @@ $MyModule = $MyInvocation.MyCommand.ScriptBlock.Module
1919
$aliasList +=
2020
[GetExports("Alias")]$MyModule
2121

22-
Export-ModuleMember -Function * -Alias $aliasList
22+
Export-ModuleMember -Function * -Alias $aliasList
23+
24+
$global:ExecutionContext.SessionState.InvokeCommand.CommandNotFoundAction = {
25+
param($sender, $eventArgs)
26+
27+
# Rather than be the only thing that can handle command not found, we start by broadcasting an event.
28+
New-Event -SourceIdentifier "PowerShell.CommandNotFound" -MessageData $notFoundArgs -Sender $global:ExecutionContext -EventArguments $notFoundArgs
29+
30+
# Then, we do a bit of callstack peeking
31+
$callstack = @(Get-PSCallStack)
32+
$callstackPeek = $callstack[-1]
33+
# When peeking in on a dynamic script block, the offsets may lie.
34+
$column = [Math]::Max($callstackPeek.InvocationInfo.OffsetInLine, 1)
35+
$line = [Math]::Max($callstackPeek.InvocationInfo.ScriptLineNumber, 1)
36+
$callingScriptBlock = $callstackPeek.InvocationInfo.MyCommand.ScriptBlock
37+
# Now find all of the AST elements at this location.
38+
$astFound = @($callingScriptBlock.Ast.FindAll({
39+
param($ast)
40+
$ast.Extent.StartLineNumber -eq $line -and
41+
$ast.Extent.StartColumnNumber -eq $column
42+
}, $true))
43+
if (-not $script:LastCommandNotFoundScript) {
44+
$script:LastCommandNotFoundScript = $callingScriptBlock
45+
} elseif ($script:LastCommandNotFoundScript -eq $callingScriptBlock) {
46+
return
47+
} else {
48+
$script:LastCommandNotFoundScript = $callingScriptBlock
49+
}
50+
51+
if (-not $callingScriptBlock) {
52+
return
53+
}
54+
55+
56+
$transpiledScriptBlock =
57+
try {
58+
$callingScriptBlock.Transpile()
59+
} catch {
60+
Write-Error $_
61+
return
62+
}
63+
if ($transpiledScriptBlock -and
64+
($transpiledScriptBlock.ToString().Length -ne $callingScriptBlock.ToString().Length)) {
65+
66+
$endStatements = $transpiledScriptBlock.Ast.EndBlock.Statements
67+
$FirstExpression =
68+
if ($endStatements -and (
69+
$endStatements[0] -is
70+
[Management.Automation.Language.PipelineAst]
71+
) -and (
72+
$endStatements[0].PipelineElements[0] -is
73+
[Management.Automation.Language.CommandExpressionAst]
74+
)
75+
) {
76+
$endStatements[0].PipelineElements[0].Expression
77+
} else { $null }
78+
79+
if ($astFound -and
80+
$astFound[-1].Parent -is [Management.Automation.Language.AssignmentStatementAst] -and
81+
(
82+
$FirstExpression -is [Management.Automation.Language.BinaryExpressionAst] -or
83+
$FirstExpression -is [Management.Automation.Language.ParenExpressionAst]
84+
)
85+
) {
86+
Write-Error "
87+
Will not interactively transpile {$callingScriptBlock} ( because it would overwrite $($astFound[-1].Parent.Left.Extent) )"
88+
return
89+
}
90+
91+
if ($astFound -and
92+
$astFound[-1].Parent -is [Management.Automation.Language.AssignmentStatementAst] -and
93+
$endStatements -and
94+
$endStatements[0] -is [Management.Automation.Language.AssignmentStatementAst] -and
95+
$astFound[-1].Parent.Left.ToString() -eq $endStatements[0].Left.ToString()) {
96+
$eventArgs.CommandScriptBlock = [ScriptBlock]::Create($endStatements[0].Right.ToString())
97+
$eventArgs.StopSearch = $true
98+
} else {
99+
$eventArgs.CommandScriptBlock = $transpiledScriptBlock
100+
$eventArgs.StopSearch = $true
101+
}
102+
}
103+
104+
return
105+
}
106+
107+
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
108+
$global:ExecutionContext.SessionState.InvokeCommand.CommandNotFoundAction = $null
109+
}

PipeScript.psd1

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@{
2-
ModuleVersion = '0.1.8'
2+
ModuleVersion = '0.1.9'
33
Description = 'An Extensible Transpiler for PowerShell (and anything else)'
44
RootModule = 'PipeScript.psm1'
55
PowerShellVersion = '4.0'
@@ -19,14 +19,18 @@
1919
BuildModule = @('EZOut','Piecemeal','PipeScript','HelpOut', 'PSDevOps')
2020
Tags = 'PipeScript','PowerShell', 'Transpilation', 'Compiler'
2121
ReleaseNotes = @'
22-
## 0.1.8:
23-
* Improvements to 'all' keyword (#264 #263 #260 #253)
24-
* Keywords can now be run interactively (#263)
25-
* New keyword can be piped to (#265)
26-
* Sentences can now map multi-word aliases (#260)
27-
* New [CommandAST] properties: .IsPipedTo .IsPipedFrom
28-
* Added Inline HAXE and Inline Racket support (#259 #262)
29-
22+
## 0.1.9:
23+
* Protocol Transpilers
24+
* Adding JSONSchema transpiler (Fixes #274)
25+
* HTTP Protocol: Only allowing HTTP Methods (Fixes #275)
26+
* Keyword improvements:
27+
* all scripts in $directory (Fixes #277)
28+
* 'new' keyword recursively transpiles constructor arguments (Fixes #271)
29+
* Core improvements:
30+
* Core Transpiler stops transpilation of an item after any output (Fixes #280)
31+
* [CommandAst].AsSentence now maps singleton values correctly (Fixes #279)
32+
* PipeScript now handles CommandNotFound, enabling interactive use (Fixes #281)
33+
3034
Additional history in [CHANGELOG](https://pipescript.start-automating.com/CHANGELOG)
3135
'@
3236
}

PipeScript.psm1

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,90 @@ $aliasList +=
5959

6060

6161
Export-ModuleMember -Function * -Alias $aliasList
62+
63+
$global:ExecutionContext.SessionState.InvokeCommand.CommandNotFoundAction = {
64+
param($sender, $eventArgs)
65+
66+
# Rather than be the only thing that can handle command not found, we start by broadcasting an event.
67+
New-Event -SourceIdentifier "PowerShell.CommandNotFound" -MessageData $notFoundArgs -Sender $global:ExecutionContext -EventArguments $notFoundArgs
68+
69+
# Then, we do a bit of callstack peeking
70+
$callstack = @(Get-PSCallStack)
71+
$callstackPeek = $callstack[-1]
72+
# When peeking in on a dynamic script block, the offsets may lie.
73+
$column = [Math]::Max($callstackPeek.InvocationInfo.OffsetInLine, 1)
74+
$line = [Math]::Max($callstackPeek.InvocationInfo.ScriptLineNumber, 1)
75+
$callingScriptBlock = $callstackPeek.InvocationInfo.MyCommand.ScriptBlock
76+
# Now find all of the AST elements at this location.
77+
$astFound = @($callingScriptBlock.Ast.FindAll({
78+
param($ast)
79+
$ast.Extent.StartLineNumber -eq $line -and
80+
$ast.Extent.StartColumnNumber -eq $column
81+
}, $true))
82+
if (-not $script:LastCommandNotFoundScript) {
83+
$script:LastCommandNotFoundScript = $callingScriptBlock
84+
} elseif ($script:LastCommandNotFoundScript -eq $callingScriptBlock) {
85+
return
86+
} else {
87+
$script:LastCommandNotFoundScript = $callingScriptBlock
88+
}
89+
90+
if (-not $callingScriptBlock) {
91+
return
92+
}
93+
94+
95+
$transpiledScriptBlock =
96+
try {
97+
$callingScriptBlock.Transpile()
98+
} catch {
99+
Write-Error $_
100+
return
101+
}
102+
if ($transpiledScriptBlock -and
103+
($transpiledScriptBlock.ToString().Length -ne $callingScriptBlock.ToString().Length)) {
104+
105+
$endStatements = $transpiledScriptBlock.Ast.EndBlock.Statements
106+
$FirstExpression =
107+
if ($endStatements -and (
108+
$endStatements[0] -is
109+
[Management.Automation.Language.PipelineAst]
110+
) -and (
111+
$endStatements[0].PipelineElements[0] -is
112+
[Management.Automation.Language.CommandExpressionAst]
113+
)
114+
) {
115+
$endStatements[0].PipelineElements[0].Expression
116+
} else { $null }
117+
118+
if ($astFound -and
119+
$astFound[-1].Parent -is [Management.Automation.Language.AssignmentStatementAst] -and
120+
(
121+
$FirstExpression -is [Management.Automation.Language.BinaryExpressionAst] -or
122+
$FirstExpression -is [Management.Automation.Language.ParenExpressionAst]
123+
)
124+
) {
125+
Write-Error "
126+
Will not interactively transpile {$callingScriptBlock} ( because it would overwrite $($astFound[-1].Parent.Left.Extent) )"
127+
return
128+
}
129+
130+
if ($astFound -and
131+
$astFound[-1].Parent -is [Management.Automation.Language.AssignmentStatementAst] -and
132+
$endStatements -and
133+
$endStatements[0] -is [Management.Automation.Language.AssignmentStatementAst] -and
134+
$astFound[-1].Parent.Left.ToString() -eq $endStatements[0].Left.ToString()) {
135+
$eventArgs.CommandScriptBlock = [ScriptBlock]::Create($endStatements[0].Right.ToString())
136+
$eventArgs.StopSearch = $true
137+
} else {
138+
$eventArgs.CommandScriptBlock = $transpiledScriptBlock
139+
$eventArgs.StopSearch = $true
140+
}
141+
}
142+
143+
return
144+
}
145+
146+
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
147+
$global:ExecutionContext.SessionState.InvokeCommand.CommandNotFoundAction = $null
148+
}

PipeScript.types.ps1xml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,10 @@ if ($IsRightToLeft) {
349349
}
350350

351351

352-
if ($SpecificCommands) {
353-
$potentialCommandNames = $specificCommandNames
352+
$sentences = @()
353+
if ($SpecificCommands) {
354354
$potentialCommands = $SpecificCommands
355+
$potentialCommandNames = @($SpecificCommands | Select-Object -ExpandProperty Name)
355356
} else {
356357

357358
# The first command element should be the name of the command.
@@ -611,7 +612,24 @@ foreach ($potentialCommand in $potentialCommands) {
611612
$commandElementIndex--
612613
continue
613614
}
614-
615+
elseif ($currentParameter) {
616+
if ($mappedParameters.Contains($currentParameter) -and
617+
$currentParameter.ParameterType -isnot [Collections.IList] -and
618+
$currentParameter.ParameterType -isnot [PSObject]
619+
) {
620+
$clauses += [PSCustomObject][Ordered]@{
621+
PSTypeName = 'PipeScript.Sentence.Clause'
622+
Name = if ($currentParameter) { $currentParameter} else { '' }
623+
ParameterName = if ($currentParameterMetadata) { $currentParameterMetadata.Name } else { '' }
624+
Words = $currentClause
625+
}
626+
$currentParameter = $null
627+
$currentParameterMetadata = $null
628+
$currentClause = @()
629+
$commandElementIndex--
630+
continue
631+
}
632+
}
615633

616634
# Refersh our $commandElement, as the index may have changed.
617635
$commandElement = $CommandElements[$commandElementIndex]
@@ -626,7 +644,10 @@ foreach ($potentialCommand in $potentialCommands) {
626644

627645
# If we have a current parameter
628646
if ($currentParameter) {
647+
629648
# Map the current element to this parameter.
649+
650+
630651
$mappedParameters[$currentParameter] =
631652
if ($mappedParameters[$currentParameter]) {
632653
@($mappedParameters[$currentParameter]) + @($commandElement)
@@ -642,6 +663,8 @@ foreach ($potentialCommand in $potentialCommands) {
642663
}
643664
}
644665
$currentClause += $commandElement
666+
667+
645668
} else {
646669
# otherwise add the command element to our unbound parameters.
647670
$unboundParameters +=
@@ -665,9 +688,11 @@ foreach ($potentialCommand in $potentialCommands) {
665688
Name = if ($currentParameter) { $currentParameter} else { '' }
666689
ParameterName = if ($currentParameterMetadata) { $currentParameterMetadata.Name } else { '' }
667690
Words = $currentClause
668-
}
691+
}
669692
}
670693

694+
695+
671696
if ($potentialCommand -isnot [Management.Automation.ApplicationInfo] -and
672697
@($mappedParameters.Keys) -match '^[-/]') {
673698
$keyIndex = -1
@@ -698,9 +723,8 @@ foreach ($potentialCommand in $potentialCommands) {
698723
Parameters = $mappedParameters
699724
Arguments = $unboundParameters
700725
}
701-
702-
$sentence
703-
726+
$sentences+= $sentence
727+
$sentence
704728
}
705729
</Script>
706730
</ScriptMethod>

Transpilers/Core/PipeScript.Protocol.psx.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ process {
9090
}
9191

9292
$foundTranspiler =
93-
Get-Transpiler -CouldPipe $commandUri -ValidateInput $CommandAst -CouldRun -Parameter $commandAstSplat
93+
@(Get-Transpiler -CouldPipe $commandUri -ValidateInput $CommandAst -CouldRun -Parameter $commandAstSplat)
9494

95-
if (-not $foundTranspiler) {
95+
if (-not $foundTranspiler -and -not $CommandMethod) {
9696
Write-Error "Could not find a transpiler for $commandAst"
9797
return
9898
}

Transpilers/Core/Pipescript.psx.ps1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ process {
258258
$AstReplacements[$item] = $pso # and store the replacement.
259259
}
260260
}
261+
# If the transpiler had output, do not process any more transpilers.
262+
if ($pipeScriptOutput) { break }
261263
}
262264
}
263265
}

0 commit comments

Comments
 (0)