Skip to content

Commit 2dd67d0

Browse files
committed
docs: document cli-fp-gen and add Windows codegen verification
1 parent 4602cf2 commit 2dd67d0

4 files changed

Lines changed: 188 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- `cli-fp-gen` project scaffolding workflow is now documented from the main README, including a direct link to the dedicated generator guide.
13+
14+
### Testing
15+
16+
- Added a Windows PowerShell verification path for `cli-fp-gen` in `tests/codegen/run_all_tests.ps1`.
17+
- Code generator documentation now includes both the Bash test scripts and the PowerShell verification command.
18+
1019
## [1.1.6] - 2026-02-21
1120

1221
### Added

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Combines Free Pascal's speed and reliability with professional-grade features. T
1717
- [📑 Table of Contents](#-table-of-contents)
1818
- [✨ Features](#-features)
1919
- [🚀 Quick Start](#-quick-start)
20+
- [🧩 Project Generator](#-project-generator)
2021
- [🎯 Parameter Types and Validation](#-parameter-types-and-validation)
2122
- [Basic Types](#basic-types)
2223
- [Boolean and Flags](#boolean-and-flags)
@@ -180,6 +181,21 @@ Options:
180181
A runtime-only Lazarus package is provided in `packages/lazarus/cli_fp.lpk`.
181182
To use it, open the `.lpk` file in Lazarus, click “Compile,” then click “Add” to add it to your project’s required packages.
182183

184+
## 🧩 Project Generator
185+
186+
This repository also includes `cli-fp-gen`, a scaffold generator for new `cli-fp` applications.
187+
188+
Typical workflow:
189+
190+
```powershell
191+
fpc -Futools\cli-fp-gen\src .\tools\cli-fp-gen\cli_fp_gen.lpr
192+
.\tools\cli-fp-gen\cli_fp_gen.exe init .\build-temp\myapp --name myapp
193+
.\tools\cli-fp-gen\cli_fp_gen.exe add command greet --project .\build-temp\myapp --description "Say hello"
194+
.\tools\cli-fp-gen\cli_fp_gen.exe generate --project .\build-temp\myapp
195+
```
196+
197+
Full generator documentation, project layout details, and `clifp.json` reference are in [docs/codegen.md](docs/codegen.md).
198+
183199
### Progress Indicator Captions (v1.1.6)
184200

185201
Progress indicators now support inline status text via:
@@ -322,6 +338,7 @@ Each parameter type has built-in validation:
322338
- [User Manual](docs/user-manual.md): Complete guide for using the framework, *including a cheat sheet*
323339
- [API Reference](docs/api-reference.md): Detailed API reference for the framework
324340
- [Technical Documentation](docs/technical-docs.md): Architecture and implementation details
341+
- [Code Generator](docs/codegen.md): `cli-fp-gen` usage, generated layout, and verification notes
325342
- [Examples](examples/): Working example applications
326343
- [Changelog](CHANGELOG.md): Version history and updates
327344

docs/codegen.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ fpc "-Fu..\..\src" "-Fu.\src" "-Fu.\src\generated" "-Fu.\src\commands" .\src\MyA
101101

102102
Adjust the `..\..\src` path to point at the `cli-fp` framework `src/` directory.
103103

104+
## Verification
105+
106+
### Linux/macOS (Bash)
107+
108+
The repository includes focused codegen checks under `tests/codegen/`:
109+
110+
- `run_golden_test.sh`
111+
- `run_compile_smoke.sh`
112+
- `run_ops_test.sh`
113+
114+
### Windows (PowerShell)
115+
116+
Use the Windows-native verification script from the repository root:
117+
118+
```powershell
119+
powershell -ExecutionPolicy Bypass -File .\tests\codegen\run_all_tests.ps1
120+
```
121+
122+
This script compiles `cli-fp-gen`, verifies golden output, compiles a generated app, and checks `init` / `generate` / `add command` / `remove command` behavior plus the path validation guard.
123+
104124
## Notes
105125

106126
- Commands are defined in a flat list with `parent` paths (slash-delimited, e.g. `repo/remote`).

tests/codegen/run_all_tests.ps1

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
$ErrorActionPreference = 'Stop'
2+
3+
function New-TempDir {
4+
$path = Join-Path ([System.IO.Path]::GetTempPath()) ("cli-fp-codegen-" + [System.Guid]::NewGuid().ToString("N"))
5+
New-Item -ItemType Directory -Path $path | Out-Null
6+
return $path
7+
}
8+
9+
function Normalize-Content([string]$Path) {
10+
return (Get-Content -Raw $Path) -replace "`r`n", "`n"
11+
}
12+
13+
function Assert-True([bool]$Condition, [string]$Message) {
14+
if (-not $Condition) {
15+
throw $Message
16+
}
17+
}
18+
19+
function Write-JsonFile([string]$Path, $Object) {
20+
$Object | ConvertTo-Json -Depth 20 | Set-Content -Path $Path
21+
}
22+
23+
$RootDir = (Resolve-Path (Join-Path $PSScriptRoot "..\..")).Path
24+
$GenSrc = Join-Path $RootDir "tools\cli-fp-gen\cli_fp_gen.lpr"
25+
$GenExe = Join-Path $RootDir "tools\cli-fp-gen\cli_fp_gen.exe"
26+
$FixtureDir = Join-Path $RootDir "tests\codegen-fixtures\golden-basic"
27+
$GoldenDir = Join-Path $RootDir "tests\codegen-golden\golden-basic"
28+
$TmpDir = New-TempDir
29+
30+
try {
31+
fpc "-Fu$RootDir\tools\cli-fp-gen\src" $GenSrc | Out-Null
32+
33+
# Golden output check
34+
$GoldenProject = Join-Path $TmpDir "golden"
35+
New-Item -ItemType Directory -Force -Path $GoldenProject | Out-Null
36+
Copy-Item -Force (Join-Path $FixtureDir "clifp.json") (Join-Path $GoldenProject "clifp.json")
37+
& $GenExe generate --project $GoldenProject | Out-Null
38+
39+
$GoldenFiles = @(
40+
"src\GoldenDemo.lpr",
41+
"src\generated\GoldenDemo_CommandRegistry_Generated.pas",
42+
"src\generated\.clifp-manifest.json",
43+
"src\commands\GoldenDemo_Command_Greet.pas",
44+
"src\commands\GoldenDemo_Command_Repo.pas",
45+
"src\commands\GoldenDemo_Command_RepoClone.pas",
46+
"src\commands\GoldenDemo_Command_Types.pas"
47+
)
48+
49+
foreach ($RelativePath in $GoldenFiles) {
50+
$Expected = Normalize-Content (Join-Path $GoldenDir $RelativePath)
51+
$Actual = Normalize-Content (Join-Path $GoldenProject $RelativePath)
52+
Assert-True ($Expected -eq $Actual) "Golden mismatch: $RelativePath"
53+
}
54+
55+
Write-Host "Golden test passed"
56+
57+
# Compile smoke check
58+
fpc `
59+
"-Fu$RootDir\src" `
60+
"-Fu$GoldenProject\src" `
61+
"-Fu$GoldenProject\src\generated" `
62+
"-Fu$GoldenProject\src\commands" `
63+
(Join-Path $GoldenProject "src\GoldenDemo.lpr") | Out-Null
64+
65+
& (Join-Path $GoldenProject "src\GoldenDemo.exe") --help | Out-Null
66+
& (Join-Path $GoldenProject "src\GoldenDemo.exe") repo | Out-Null
67+
68+
Write-Host "Compile smoke test passed"
69+
70+
# Operations and path guard check
71+
$DemoProject = Join-Path $TmpDir "demo"
72+
& $GenExe init $DemoProject --force | Out-Null
73+
74+
$DryRunOutput = (& $GenExe add command repo --project $DemoProject --description "Repo tools" --dry-run) | Out-String
75+
Assert-True ($DryRunOutput -match "Demo_Command_Repo\.pas") "Dry-run add did not preview the new command stub"
76+
Assert-True (-not ((Get-Content -Raw (Join-Path $DemoProject "clifp.json")) -match '"name"\s*:\s*"repo"')) "Dry-run add modified clifp.json"
77+
Assert-True (-not (Test-Path (Join-Path $DemoProject "src\commands\Demo_Command_Repo.pas"))) "Dry-run add created a command stub"
78+
79+
& $GenExe add command repo --project $DemoProject --description "Repo tools" | Out-Null
80+
& $GenExe add command clone --parent repo --project $DemoProject --description "Clone repo" | Out-Null
81+
82+
$null = (& $GenExe remove command repo --project $DemoProject 2>&1 | Out-String)
83+
Assert-True ($LASTEXITCODE -ne 0) "Expected remove command without --cascade to fail"
84+
85+
& $GenExe remove command repo --cascade --project $DemoProject | Out-Null
86+
Assert-True (-not ((Get-Content -Raw (Join-Path $DemoProject "clifp.json")) -match '"name"\s*:\s*"repo"')) "repo command still present after cascade remove"
87+
88+
$DemoSpec = Get-Content -Raw (Join-Path $DemoProject "clifp.json") | ConvertFrom-Json
89+
$OldProgramPath = Join-Path $DemoProject $DemoSpec.app.programFile
90+
Assert-True (Test-Path $OldProgramPath) "Expected original program file to exist after init"
91+
92+
$DemoSpec.app.programFile = "src/DemoRenamed.lpr"
93+
Write-JsonFile (Join-Path $DemoProject "clifp.json") $DemoSpec
94+
& $GenExe generate --project $DemoProject | Out-Null
95+
96+
Assert-True (Test-Path (Join-Path $DemoProject "src\DemoRenamed.lpr")) "Renamed program file was not generated"
97+
Assert-True (-not (Test-Path $OldProgramPath)) "Old generated program file was not removed by manifest cleanup"
98+
Assert-True ((Get-Content -Raw (Join-Path $DemoProject "src\generated\.clifp-manifest.json")) -match "src/DemoRenamed\.lpr") "Manifest did not track renamed program file"
99+
100+
$DescriptionsProject = Join-Path $TmpDir "descriptions"
101+
& $GenExe init $DescriptionsProject --force | Out-Null
102+
& $GenExe add command repo --project $DescriptionsProject --description "Owner's tools" | Out-Null
103+
104+
$DescriptionsSpec = Get-Content -Raw (Join-Path $DescriptionsProject "clifp.json") | ConvertFrom-Json
105+
foreach ($Command in $DescriptionsSpec.commands) {
106+
if ($Command.name -eq "repo") {
107+
$Command.description = "Repo team's tools"
108+
}
109+
}
110+
Write-JsonFile (Join-Path $DescriptionsProject "clifp.json") $DescriptionsSpec
111+
& $GenExe generate --project $DescriptionsProject | Out-Null
112+
113+
$ProgramPath = Join-Path $DescriptionsProject $DescriptionsSpec.app.programFile
114+
fpc `
115+
"-Fu$RootDir\src" `
116+
"-Fu$DescriptionsProject\src" `
117+
"-Fu$DescriptionsProject\src\generated" `
118+
"-Fu$DescriptionsProject\src\commands" `
119+
$ProgramPath | Out-Null
120+
121+
$ExePath = [System.IO.Path]::ChangeExtension($ProgramPath, ".exe")
122+
$HelpOutput = (& $ExePath repo --help) | Out-String
123+
Assert-True ($HelpOutput -match "Repo team's tools") "Regenerated command description did not update runtime help"
124+
125+
$PathGuardProject = Join-Path $TmpDir "path-guard"
126+
& $GenExe init $PathGuardProject --force | Out-Null
127+
128+
$PathGuardSpec = Get-Content -Raw (Join-Path $PathGuardProject "clifp.json") | ConvertFrom-Json
129+
$PathGuardSpec.app.programFile = "../outside/Escape.lpr"
130+
Write-JsonFile (Join-Path $PathGuardProject "clifp.json") $PathGuardSpec
131+
132+
$null = (& $GenExe generate --project $PathGuardProject 2>&1 | Out-String)
133+
Assert-True ($LASTEXITCODE -ne 0) "Expected invalid programFile path to fail validation"
134+
Assert-True (-not (Test-Path (Join-Path $TmpDir "outside\Escape.lpr"))) "Generator wrote a program file outside the project directory"
135+
136+
Write-Host "Ops test passed"
137+
}
138+
finally {
139+
if (Test-Path $TmpDir) {
140+
Remove-Item -Recurse -Force $TmpDir
141+
}
142+
}

0 commit comments

Comments
 (0)