Created
January 26, 2026 13:06
-
-
Save dfinke/0ffeeee010f6cf2058c85b7c7ae52a9e to your computer and use it in GitHub Desktop.
Reads and parses ISPF panel syntax from ISPFPanel.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ParseISPF.ps1 - Reads and parses ISPF panel syntax from ISPFPanel.txt | |
| # Then generates a PowerShell script that creates a WinForm based on the layout | |
| $panelFile = "ISPFPanel.txt" | |
| $content = Get-Content $panelFile -Raw | |
| # Split into sections | |
| $sections = @{} | |
| $currentSection = $null | |
| $lines = $content -split "`n" | |
| foreach ($line in $lines) { | |
| $line = $line.Trim() | |
| $match = $line | Select-String '^\)(\w+)' | |
| if ($match) { | |
| $currentSection = $match.Matches[0].Groups[1].Value | |
| $sections[$currentSection] = @() | |
| } | |
| elseif ($currentSection -and $line) { | |
| $sections[$currentSection] += $line | |
| } | |
| } | |
| # Parse ATTR section | |
| $attrs = @{} | |
| if ($sections.ContainsKey('ATTR')) { | |
| foreach ($line in $sections['ATTR']) { | |
| $match = $line | Select-String '^\s*(\w)\s+(.+)' | |
| if ($match) { | |
| $char = $match.Matches[0].Groups[1].Value | |
| $attrStr = $match.Matches[0].Groups[2].Value | |
| $attrs[$char] = @{} | |
| # Parse attributes like TYPE(INPUT) CAPS(OFF) | |
| $attrParts = $attrStr -split '\s+' | |
| foreach ($part in $attrParts) { | |
| $match = $part | Select-String '(\w+)\(([^)]*)\)' | |
| if ($match) { | |
| $key = $match.Matches[0].Groups[1].Value | |
| $value = $match.Matches[0].Groups[2].Value | |
| $attrs[$char][$key] = $value | |
| } | |
| } | |
| } | |
| } | |
| } | |
| # Parse BODY section | |
| $bodyLines = @() | |
| if ($sections.ContainsKey('BODY')) { | |
| foreach ($line in $sections['BODY']) { | |
| if ($line -notmatch '^WINDOW') { | |
| $bodyLines += $line | |
| } | |
| } | |
| } | |
| # Collect all variables from BODY | |
| $variables = @() | |
| foreach ($line in $bodyLines) { | |
| $varMatches = [regex]::Matches($line, '&(\w+)') | |
| foreach ($match in $varMatches) { | |
| $var = $match.Groups[1].Value | |
| if ($var -notin $variables) { | |
| $variables += $var | |
| } | |
| } | |
| } | |
| # Generate WinForm script | |
| $winFormScript = @" | |
| Add-Type -AssemblyName System.Windows.Forms | |
| Add-Type -AssemblyName System.Drawing | |
| `$form = New-Object System.Windows.Forms.Form | |
| `$form.Text = 'ISPF Panel Simulation' | |
| `$form.Size = New-Object System.Drawing.Size(500, 400) | |
| `$form.StartPosition = 'CenterScreen' | |
| `$y = 20 | |
| `$x = 20 | |
| "@ | |
| # Calculate a shared input column based on max label width | |
| $maxLabelWidth = 0 | |
| foreach ($line in $bodyLines) { | |
| $match = $line | Select-String '^\s*(.)(.*)' | |
| if ($match) { | |
| $text = $match.Matches[0].Groups[2].Value | |
| $labelText = [regex]::Replace($text, '&\w+', '') | |
| $labelText = $labelText.TrimEnd() | |
| if ($labelText.Length -gt $maxLabelWidth) { | |
| $maxLabelWidth = $labelText.Length | |
| } | |
| } | |
| } | |
| $inputColumnX = 20 + ($maxLabelWidth * 8) + 20 | |
| foreach ($line in $bodyLines) { | |
| $match = $line | Select-String '^\s*(.)(.*)' | |
| if ($match) { | |
| $attrChar = $match.Matches[0].Groups[1].Value | |
| $text = $match.Matches[0].Groups[2].Value | |
| # Split the line into parts: text and &variables | |
| $parts = @() | |
| $regex = [regex]'(&\w+)|([^&]+)' | |
| $regexMatches = $regex.Matches($text) | |
| foreach ($match in $regexMatches) { | |
| if ($match.Groups[1].Success) { | |
| $parts += $match.Groups[1].Value | |
| } | |
| elseif ($match.Groups[2].Success) { | |
| $parts += $match.Groups[2].Value | |
| } | |
| } | |
| $lineX = 20 | |
| foreach ($part in $parts) { | |
| $partMatch = [regex]::Match($part, '^&(\w+)') | |
| if ($partMatch.Success) { | |
| $var = $partMatch.Groups[1].Value | |
| # Create TextBox for input | |
| $winFormScript += @" | |
| `$textBox$var = New-Object System.Windows.Forms.TextBox | |
| `$textBox$var.Location = New-Object System.Drawing.Point($inputColumnX, `$y) | |
| `$textBox$var.Size = New-Object System.Drawing.Size(150, 20) | |
| `$form.Controls.Add(`$textBox$var) | |
| "@ | |
| $winFormScript += "`n" | |
| $lineX = $inputColumnX + 160 | |
| } | |
| elseif ($part.Trim()) { | |
| # Create Label for text | |
| $escapedPart = $part -replace "'", "''" | |
| $winFormScript += @" | |
| `$label = New-Object System.Windows.Forms.Label | |
| `$label.Text = '$escapedPart' | |
| `$label.Location = New-Object System.Drawing.Point($lineX, `$y) | |
| `$label.AutoSize = `$true | |
| `$form.Controls.Add(`$label) | |
| "@ | |
| $winFormScript += "`n" | |
| $lineX += ($part.Length * 8) # Rough estimate for width | |
| } | |
| } | |
| $winFormScript += "`n`$y += 30`n" | |
| } | |
| } | |
| # Add OK button | |
| $winFormScript += @" | |
| `$okButton = New-Object System.Windows.Forms.Button | |
| `$okButton.Text = 'OK' | |
| `$okButton.Location = New-Object System.Drawing.Point(200, `$y) | |
| `$okButton.Size = New-Object System.Drawing.Size(75, 23) | |
| `$okButton.Add_Click({ | |
| `$result = @{} | |
| "@ | |
| $winFormScript += "`n" | |
| foreach ($var in $variables) { | |
| $winFormScript += " `$result['$var'] = `$textBox$var.Text`n" | |
| } | |
| $winFormScript += @" | |
| Write-Host "Captured Data:" | |
| `$result.GetEnumerator() | ForEach-Object { Write-Host ("{0}: {1}" -f `$_.Key, `$_.Value) } | |
| `$form.DialogResult = [System.Windows.Forms.DialogResult]::OK | |
| `$form.Close() | |
| }) | |
| `$form.Controls.Add(`$okButton) | |
| `$form.ShowDialog() | |
| "@ | |
| # Output the generated script to a file | |
| $outputFile = "GeneratedWinForm.ps1" | |
| Set-Content -Path $outputFile -Value $winFormScript -Encoding UTF8 | |
| Write-Host "Generated WinForm script: $outputFile" |
Author
dfinke
commented
Jan 26, 2026
Author
GeneratedWinForm.ps1
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'ISPF Panel Simulation'
$form.Size = New-Object System.Drawing.Size(500, 400)
$form.StartPosition = 'CenterScreen'
$y = 20
$x = 20
$label = New-Object System.Windows.Forms.Label
$label.Text = 'First Name: '
$label.Location = New-Object System.Drawing.Point(20, $y)
$label.AutoSize = $true
$form.Controls.Add($label)
$textBoxFIRST = New-Object System.Windows.Forms.TextBox
$textBoxFIRST.Location = New-Object System.Drawing.Point(128, $y)
$textBoxFIRST.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($textBoxFIRST)
$y += 30
$label = New-Object System.Windows.Forms.Label
$label.Text = 'Last Name: '
$label.Location = New-Object System.Drawing.Point(20, $y)
$label.AutoSize = $true
$form.Controls.Add($label)
$textBoxLAST = New-Object System.Windows.Forms.TextBox
$textBoxLAST.Location = New-Object System.Drawing.Point(128, $y)
$textBoxLAST.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($textBoxLAST)
$y += 30
$label = New-Object System.Windows.Forms.Label
$label.Text = 'City: '
$label.Location = New-Object System.Drawing.Point(20, $y)
$label.AutoSize = $true
$form.Controls.Add($label)
$textBoxCITY = New-Object System.Windows.Forms.TextBox
$textBoxCITY.Location = New-Object System.Drawing.Point(128, $y)
$textBoxCITY.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($textBoxCITY)
$y += 30
$label = New-Object System.Windows.Forms.Label
$label.Text = 'State: '
$label.Location = New-Object System.Drawing.Point(20, $y)
$label.AutoSize = $true
$form.Controls.Add($label)
$textBoxSTATE = New-Object System.Windows.Forms.TextBox
$textBoxSTATE.Location = New-Object System.Drawing.Point(128, $y)
$textBoxSTATE.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($textBoxSTATE)
$y += 30
$label = New-Object System.Windows.Forms.Label
$label.Text = 'Zip: '
$label.Location = New-Object System.Drawing.Point(20, $y)
$label.AutoSize = $true
$form.Controls.Add($label)
$textBoxZIP = New-Object System.Windows.Forms.TextBox
$textBoxZIP.Location = New-Object System.Drawing.Point(128, $y)
$textBoxZIP.Size = New-Object System.Drawing.Size(150, 20)
$form.Controls.Add($textBoxZIP)
$y += 30
$okButton = New-Object System.Windows.Forms.Button
$okButton.Text = 'OK'
$okButton.Location = New-Object System.Drawing.Point(200, $y)
$okButton.Size = New-Object System.Drawing.Size(75, 23)
$okButton.Add_Click({
$result = @{}
$result['FIRST'] = $textBoxFIRST.Text
$result['LAST'] = $textBoxLAST.Text
$result['CITY'] = $textBoxCITY.Text
$result['STATE'] = $textBoxSTATE.Text
$result['ZIP'] = $textBoxZIP.Text
Write-Host "Captured Data:"
$result.GetEnumerator() | ForEach-Object { Write-Host ("{0}: {1}" -f $_.Key, $_.Value) }
$form.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.Close()
})
$form.Controls.Add($okButton)
$form.ShowDialog()
```
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment