Adaugari locale ROA: vcx2txt.ps1 (cautare cod in binare VFP), prompturi si CLAUDE.md
This commit is contained in:
93
CLAUDE.md
Normal file
93
CLAUDE.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## What this is
|
||||
|
||||
A local shared copy of **FoxBin2Prg** (the VFPX tool by Fernando D. Bozzo, maintained by Lutz Scheffler): a Visual FoxPro 9 program that converts VFP binary files to PRG-style text and back. Supported conversions: `PJX↔PJ2`, `SCX↔SC2`, `VCX↔VC2`, `FRX↔FR2`, `LBX↔LB2`, `DBC↔DC2`, `DBF↔DB2`, `MNX↔MN2`.
|
||||
|
||||
This directory is a git clone of `https://github.com/fdbozzo/foxbin2prg.git` (`master` tracks `origin/master`; the pre-update local state is kept on branch `local-snapshot-v1.21.04`). Local-only files (`vcx2txt.ps1`, `_textcache_*`, compiled binaries) are ignored via the upstream `.gitignore` plus `.git/info/exclude`. After a `git pull`, the binaries/EXE must be regenerated in VFP9 with `DO ReCreate_FoxBin2Prg.prg`. It serves two purposes:
|
||||
|
||||
1. Upstream tool source (for occasional patches to FoxBin2Prg itself).
|
||||
2. A **shared search tool for the ROA VFP projects** (`D:\ROA\ROAGEST`, `D:\ROA\ROAIMOB`, `D:\ROA\ROAACNPRO`, …) via the local additions below.
|
||||
|
||||
## Local additions (ROA-specific, not part of upstream)
|
||||
|
||||
- **`vcx2txt.ps1`** — PowerShell script that converts the VFP binaries of a project (read from its `.pjx`) into text under a cache folder, so the code inside `.vcx/.scx/.frx/.mnx/.dbc` binaries becomes greppable. Incremental (skips up-to-date files), does not need the VFP IDE open (uses the compiled `FoxBin2Prg.EXE`).
|
||||
- **`_textcache_*` folders** (`_textcache`, `_textcache_roagest`, `_textcache_roaimob`) — per-project regenerable text caches. Safe to delete; never version them.
|
||||
- **`PROMPT_cautare_vfp.md`** — reusable prompt (Romanian) explaining how to set up this search flow in any VFP project. Read it before working on VFP code search.
|
||||
|
||||
**Golden rule:** the generated text cache is **read-only, for searching only**. Code changes to a VFP project are made in the VFP IDE on the binary files (`.vcx/.scx/...`), never by editing the cached text.
|
||||
|
||||
```powershell
|
||||
# Populate/refresh a project's text cache (incremental)
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project 'D:\ROA\ROAGEST\roagest.pjx' -ProjectRoot 'D:\ROA\ROAGEST' -CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_roagest'
|
||||
|
||||
# Include reports/menus too: -Types vcx,scx,frx,mnx
|
||||
# One-off conversion of a file/folder not in the project: -Source 'path\to\lib.vcx'
|
||||
# Other flags: -Force (reconvert all), -Clean (wipe cache first)
|
||||
```
|
||||
|
||||
Then search the cache with Grep (e.g. `PROCEDURE do_salvare`), citing `file:line` from the cache.
|
||||
|
||||
## Commands
|
||||
|
||||
All FoxBin2Prg commands run inside VFP 9 (or via the compiled `FoxBin2Prg.EXE`).
|
||||
|
||||
```foxpro
|
||||
* After clone/pull: regenerate all binaries from text and compile the EXEs.
|
||||
* NEVER run foxbin2prg.prg directly for this — it uses a special config.
|
||||
DO ReCreate_FoxBin2Prg.prg
|
||||
|
||||
* Convert a single file (direction inferred from extension)
|
||||
DO FOXBIN2PRG.PRG WITH "<path>\file.scx" && binary -> text (.sc2)
|
||||
DO FOXBIN2PRG.PRG WITH "<path>\file.sc2" && text -> binary (.scx)
|
||||
|
||||
* Convert a whole directory
|
||||
DO FOXBIN2PRG.PRG WITH "<path>","Bin2Prg"
|
||||
DO FOXBIN2PRG.PRG WITH "<path>","Prg2Bin"
|
||||
|
||||
* Config templates
|
||||
DO FOXBIN2PRG.PRG WITH "-c","template.cfg" && default settings
|
||||
DO FOXBIN2PRG.PRG WITH "-C","config.cfg" && active settings
|
||||
DO FOXBIN2PRG.PRG WITH "-t","table.dbf.cfg" && per-table template
|
||||
|
||||
* Interactive help / option list
|
||||
DO FOXBIN2PRG.PRG WITH "?"
|
||||
```
|
||||
|
||||
### Tests
|
||||
|
||||
Unit tests live in `TESTS/` and use **FoxUnit** (path configured in `TESTS/foxunit_path.txt`). Files: `ut__foxbin2prg__<class>__<method>.prg` (unit) and `ft__foxbin2prg__<class>.prg` (functional). Run them from VFP via FoxUnit; test fixtures live in `TESTS/DATOS_READONLY/`.
|
||||
|
||||
## Architecture
|
||||
|
||||
Nearly everything is in one ~34,000-line file: **`foxbin2prg.prg`**. Key class hierarchy inside it:
|
||||
|
||||
- **`c_foxbin2prg` (As Session)** — entry point / public API. Parameter parsing, config resolution (`evaluateConfiguration`), file dispatch, progress UI, error logging. Also usable as COM-ish object (`CREATEOBJECT('c_foxbin2prg')`, `.execute(...)`), which is how the `.vbs` helpers and SCM integrations drive it.
|
||||
- **`c_conversor_base`** — shared conversion logic (backup handling, timestamps, comment/property parsing, exclusion blocks).
|
||||
- **`c_conversor_bin_a_prg`** and per-type subclasses (`c_conversor_vcx_a_prg`, `c_conversor_scx_a_prg`, `c_conversor_pjx_a_prg`, `c_conversor_dbf_a_prg`, …) — binary → text.
|
||||
- **`c_conversor_prg_a_bin`** and per-type subclasses — text → binary.
|
||||
- **`CL_*` model classes** (`CL_CLASE`, `CL_PROJECT`, `CL_DBC*`, `CL_DBF_*`, `CL_MENU*`, …) — object model the text files are parsed into / generated from.
|
||||
- **`CL_CFG` / `CL_DBF_CFG`** — config file handling (`FOXBIN2PRG.CFG` with directory inheritance, per-table `.dbf.cfg`).
|
||||
- **`CL_LANG`** — localization (EN/ES/FR/DE), auto-selected.
|
||||
|
||||
Supporting files: `foxbin2prg_keywords.dbf/.cdx` (VFP keyword table used during generation — has its own `.db2` text form), `props_*.txt` (per-control default property lists used to suppress default values in output), `Create_FoxBin2Prg.cfg` (the special self-conversion config), `Fb2P_Diff/` and `FileName_Caps/` (companion sub-projects, built by `ReCreate_FoxBin2Prg.prg`), `BuildProcess/` (VFPXDeployment build hooks), `ThorUpdater/` (Thor/VFPX release plumbing).
|
||||
|
||||
**Text format is position-sensitive:** the generated `.??2` files look like PRG/XML but are parsed line by line; structure and line layout must be preserved when editing them. Properties/methods are emitted alphabetically sorted.
|
||||
|
||||
## Upstream contribution conventions (from `.github/CONTRIBUTING.md`)
|
||||
|
||||
If patching FoxBin2Prg itself:
|
||||
|
||||
- Two version constants at the top of `foxbin2prg.prg`: bump only the minor part of `DC_FB2PRG_VERSION_REAL` (e.g. `'1.21.04'`); do **not** change `DN_FB2PRG_VERSION` (`1.21`) — it's written into every text file and forces mass recommits.
|
||||
- Add the change to the history section at the top of `foxbin2prg.prg` and to `docs/ChangeLog.md`; update the version in `README.md`.
|
||||
- Style: mixed-case keywords, tab indentation, spaces around operators and after list items; do not run BeautifyX with mDots insertion.
|
||||
- After changes, regenerate text with `DO Create_FoxBin2Prg.prg` and compile in **VFP9 SP2**.
|
||||
|
||||
## Documentation
|
||||
|
||||
- `docs/FoxBin2Prg_Internals.md` — settings reference and internals (ZOrder, timestamps, class-per-file, DBF export hooks, API).
|
||||
- `docs/FoxBin2Prg_Run.md` — full command-line/parameter reference.
|
||||
- `docs/FoxBin2Prg_git.md`, `docs/FoxBin2Prg_SCM.md` — SCM integration.
|
||||
- Spanish docs in `Documentacion/` are unmaintained.
|
||||
83
PROMPT_cautare_vfp.md
Normal file
83
PROMPT_cautare_vfp.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# Prompt: căutare în cod VFP (foxbin2prg) — reutilizabil în orice proiect Visual FoxPro
|
||||
|
||||
Acest fișier conține un **prompt gata de copiat** pentru Claude Code (sau alt agent), care
|
||||
configurează și folosește sistemul `foxbin2prg` ca să poată căuta cod-sursă aflat **în interiorul
|
||||
fișierelor binare VFP** (`.vcx/.vct`, `.scx/.sct`, `.frx/.frt`, `.mnx/.mnt`, `.dbc/.dct`) într-un
|
||||
proiect nou.
|
||||
|
||||
Unealta e partajată și stă la `D:\ROA\UTIL\foxbin2prg\` — nu trebuie copiată per proiect. Doar
|
||||
spui agentului care e proiectul curent (folderul + fișierul `.pjx`).
|
||||
|
||||
---
|
||||
|
||||
## Cum se folosește
|
||||
|
||||
1. Deschide proiectul VFP în Claude Code.
|
||||
2. Copiază blocul de mai jos în prompt.
|
||||
3. Înlocuiește cele **2 valori** marcate `<<...>>` cu datele proiectului tău:
|
||||
- `<<RADACINA_PROIECT>>` = folderul rădăcină al proiectului (ex. `D:\ROA\ROAGEST`)
|
||||
- `<<FISIER_PJX>>` = calea către `.pjx` (ex. `D:\ROA\ROAGEST\roagest.pjx`)
|
||||
|
||||
---
|
||||
|
||||
## ▼▼▼ PROMPT DE COPIAT ▼▼▼
|
||||
|
||||
```
|
||||
Acest proiect este o aplicație Visual FoxPro 9. O mare parte din cod (proceduri, metode,
|
||||
parametri) NU stă în fișiere .prg, ci în interiorul fișierelor binare VFP: librării de clase
|
||||
(.vcx+.vct), forme (.scx+.sct), rapoarte (.frx+.frt), meniuri (.mnx+.mnt). Un grep direct pe
|
||||
acestea nu e lizibil (sunt tabele DBF cu memo binar).
|
||||
|
||||
Ca să poți căuta în acel cod, folosește unealta partajată foxbin2prg, care convertește binarele
|
||||
în reprezentarea lor TEXT (.vc2/.sc2/.fr2/.mn2/.dc2) într-un cache, și apoi caută în cache.
|
||||
|
||||
PARAMETRII PROIECTULUI CURENT:
|
||||
- Rădăcină proiect: <<RADACINA_PROIECT>>
|
||||
- Fișier proiect (.pjx): <<FISIER_PJX>>
|
||||
|
||||
REGULA DE AUR: textul generat e DOAR pentru citire/căutare. Orice modificare de cod se face în
|
||||
IDE-ul VFP, în fișierul binar (.vcx/.scx/...), niciodată în text.
|
||||
|
||||
PAS 1 — populează cache-ul text (la începutul sesiunii, sau după ce s-a modificat ceva în IDE).
|
||||
Rulează în PowerShell (e incremental — sare peste ce e deja la zi):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Project '<<FISIER_PJX>>' -ProjectRoot '<<RADACINA_PROIECT>>' -CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<<NUME_PROIECT>>'
|
||||
|
||||
(Folosește un -CacheRoot distinct per proiect ca să nu amesteci cache-urile. Implicit scriptul
|
||||
convertește doar .vcx și .scx; pentru a include și rapoarte/meniuri adaugă: -Types vcx,scx,frx,mnx)
|
||||
|
||||
Dacă scriptul se plânge că lipsește FoxBin2Prg.EXE, trebuie compilat o singură dată: deschide
|
||||
'D:\ROA\UTIL\foxbin2prg\foxbin2prg.pj2' în VFP 9 și Build > Build Executable. Anunță-mă să fac asta.
|
||||
|
||||
PAS 2 — caută în cache cu unealta Grep (NU în binarele originale):
|
||||
|
||||
Grep pe folderul '_textcache_<<NUME_PROIECT>>' pentru numele de metodă/procedură/variabilă căutat.
|
||||
Ex.: caută "PROCEDURE do_salvare" sau numele tabelei/cursorului implicat.
|
||||
|
||||
CONVERSIE PUNCTUALĂ (un fișier sau folder care NU e în proiect, ex. o librărie din COMUN):
|
||||
|
||||
& 'D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1' -Source 'CALE\catre\librarie.vcx' -CacheRoot 'D:\ROA\UTIL\foxbin2prg\_textcache_<<NUME_PROIECT>>'
|
||||
|
||||
ALTE OPȚIUNI: -Force (reconvertește tot), -Clean (șterge cache-ul întâi).
|
||||
|
||||
FLUX TIPIC: la prima sesiune rulează PAS 1 o dată, apoi caută cu Grep în cache (PAS 2). La
|
||||
sesiunile următoare rescrie doar ce s-a schimbat. Când citești codul unei metode, dă referințe
|
||||
fișier:linie din cache, dar reține: editarea efectivă se face în IDE-ul VFP pe binar.
|
||||
```
|
||||
|
||||
## ▲▲▲ SFÂRȘIT PROMPT ▲▲▲
|
||||
|
||||
---
|
||||
|
||||
## Note pentru adaptare
|
||||
|
||||
- `<<NUME_PROIECT>>` îl poți pune orice etichetă scurtă (ex. `roagest`), doar ca numele
|
||||
folderului de cache să fie unic per proiect.
|
||||
- Scriptul citește lista de fișiere direct din `.pjx`, deci convertește **doar** ce folosește
|
||||
efectiv proiectul (rapid), nu tot `COMUN\`.
|
||||
- Cache-ul (`_textcache_*`) e regenerabil și e în afara arborelui de versionare al proiectului —
|
||||
poate fi șters oricând.
|
||||
- Conversia NU necesită IDE-ul VFP deschis (folosește `FoxBin2Prg.EXE` compilat).
|
||||
- Ghid complet (varianta ROAACNPRO, cu exemple): `D:\ROA\ROAACNPRO\docs\cautare_vcx_vct.md`.
|
||||
- Tabel corespondență binar → text: `.vcx`→`.vc2`, `.scx`→`.sc2`, `.frx`→`.fr2`, `.mnx`→`.mn2`,
|
||||
`.dbc`→`.dc2`, `.lbx`→`.lb2`.
|
||||
86
git_svn_parallel_init_prompt.md
Normal file
86
git_svn_parallel_init_prompt.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Prompt: init git in paralel cu SVN pentru un proiect ROA
|
||||
|
||||
Foloseste acest prompt intr-o sesiune Claude Code noua, deschisa in radacina proiectului
|
||||
tinta (ex. `D:\ROA\ROAIMOB`). Functioneaza generic pentru orice proiect VFP din `D:\ROA\`
|
||||
care are structura ROAACNPRO (proiect + subfolder COMUN\ partajat, ambele in SVN).
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
Vreau sa initializezi git pentru proiectul VFP din directorul curent, in paralel cu SVN-ul
|
||||
existent (nu atinge SVN, nu rula comenzi svn, doar adauga .svn/ in .gitignore).
|
||||
|
||||
Structura e identica cu D:\ROA\ROAACNPRO: acest folder e propriul proiect VFP (are un .PJX
|
||||
al lui), si contine un subfolder COMUN\ care e framework-ul PARTAJAT intre toate aplicatiile
|
||||
ROA, versionat separat prin SVN (are propriul .svn\).
|
||||
|
||||
Fa exact ce s-a facut deja pentru ROAACNPRO (poti citi acolo ca referinta/sablon):
|
||||
- D:\ROA\ROAACNPRO\.gitignore (sablon pentru .gitignore-ul proiectului principal)
|
||||
- D:\ROA\ROAACNPRO\COMUN\.gitignore (sablon pentru .gitignore-ul din COMUN)
|
||||
- D:\ROA\ROAACNPRO\CLAUDE.md (conventii proiect) si docs\cautare_vcx_vct.md (cum se cauta
|
||||
cod in interiorul .vcx/.scx binare, via D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1)
|
||||
|
||||
Pasi:
|
||||
|
||||
1. Verifica intai ce exista deja: `git status`/`.git` in radacina si in COMUN\, si
|
||||
`git remote -v` daca exista deja vreun remote configurat gresit (asa cum a fost cazul la
|
||||
ROAACNPRO, unde originul proiectului principal pointa gresit catre repo-ul comun.git).
|
||||
|
||||
2. REPO PRINCIPAL (radacina acestui folder):
|
||||
- Daca nu exista .git, `git init -b main`.
|
||||
- Creeaza/adapteaza .gitignore dupa modelul ROAACNPRO/.gitignore (artefacte VFP compilate:
|
||||
*.fxp, *.mpx, *.bak, *.mpr, *.err, log.txt, *.tmp, *.dct, *.exe, cruft Windows), plus
|
||||
obligatoriu `COMUN/` (COMUN e gestionat de git-ul lui separat, nu de-al acestui repo)
|
||||
si `.svn/`.
|
||||
- Deduce numele repo-ului gitea dupa conventia romfast/<nume-folder-lowercase>.git
|
||||
(ex. romfast/roaimob.git). INAINTE sa creezi/pushezi orice, verifica cu
|
||||
`git ls-remote git@gitea.romfast.ro:romfast/<nume>.git` daca exista deja si ce contine
|
||||
(clone --depth 1 intr-un folder temporar din scratchpad daca ai dubii). Daca exista deja
|
||||
cu istoric care nu se potriveste cu ce ai local, OPRESTE-TE si intreaba-ma inainte sa
|
||||
faci push sau orice suprascriere.
|
||||
- Daca remote-ul e gol/nou: add -A, commit "Initial commit — sursa <PROIECT>", adauga
|
||||
origin, push normal (fara --force).
|
||||
|
||||
3. COMUN\ (subfolder-ul partajat):
|
||||
- Initializeaza un git SEPARAT, propriu, in interiorul COMUN\ (COMUN are propriul .git,
|
||||
nu e tracked de repo-ul principal — de-asta l-am exclus mai sus).
|
||||
- .gitignore propriu in COMUN\ dupa modelul ROAACNPRO/COMUN/.gitignore (artefacte VFP +
|
||||
`.svn/` + `bash.exe.stackdump`).
|
||||
- Origin-ul din COMUN\ trebuie sa fie EXACT acelasi repo pentru toate proiectele ROA:
|
||||
git@gitea.romfast.ro:romfast/comun.git — repo-ul asta e deja populat (din COMUN-ul lui
|
||||
ROAACNPRO). NU face commit+push orbeste peste el.
|
||||
- Fa intai `git fetch origin`, compara continutul de pe origin/main cu fisierele locale
|
||||
din acest COMUN\ (diff pe folder, nu doar pe nume). Daca sunt identice sau diferentele
|
||||
sunt neglijabile, seteaza pur si simplu branch-ul local sa urmareasca origin/main (fara
|
||||
sa strici fisierele din working copy SVN). Daca sunt diferente reale intre COMUN-ul
|
||||
acestui proiect si cel deja impins pe gitea, arata-mi un rezumat al diferentelor si
|
||||
intreaba-ma explicit cum procedez (nu face force-push fara aprobarea mea explicita —
|
||||
ar sterge ireversibil istoricul comun tuturor proiectelor ROA).
|
||||
|
||||
4. Cautare in cod VFP binar (.vcx/.scx) pentru acest proiect:
|
||||
- Foloseste acelasi vcx2txt.ps1, dar parametrizat pentru proiectul curent (nu ROAACNPRO):
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 `
|
||||
-Project D:\ROA\<PROIECT>\<proiect>.PJX -ProjectRoot D:\ROA\<PROIECT> `
|
||||
-CacheRoot D:\ROA\UTIL\foxbin2prg\_textcache_<proiect>
|
||||
- Cache separat per proiect (nu-l amesteca cu _textcache al ROAACNPRO). Grep in cache-ul
|
||||
respectiv, la fel ca in docs\cautare_vcx_vct.md.
|
||||
|
||||
5. La final, adauga/actualizeaza CLAUDE.md al acestui proiect cu o sectiune scurta: git ruleaza
|
||||
in paralel cu SVN legacy (SVN ramane sursa "vie" pentru COMUN, sincronizat manual catre git);
|
||||
COMUN e partajat intre toate aplicatiile ROA prin acelasi git@gitea.romfast.ro:romfast/comun.git;
|
||||
cautarile in .vcx/.scx se fac cu vcx2txt.ps1 parametrizat pentru acest proiect (vezi mai sus).
|
||||
|
||||
Inainte de orice `push --force` sau orice operatie care ar suprascrie istoric remote deja
|
||||
existent (mai ales pe romfast/comun.git, care e comun mai multor proiecte), opreste-te si
|
||||
intreaba-ma explicit — nu decide singur.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Note
|
||||
|
||||
- Cel mai sensibil pas e COMUN\: daca versiunea de COMUN a noului proiect difera de cea deja
|
||||
impinsa pe `comun.git` (din ROAACNPRO), Claude trebuie sa se opreasca si sa intrebe cum se
|
||||
reconciliaza, nu sa faca force-push automat.
|
||||
- Daca `romfast/<proiect>.git` nu exista inca pe gitea, trebuie creat gol acolo inainte de push
|
||||
(manual sau prin API) — altfel push-ul esueaza cu "repository not found".
|
||||
153
vcx2txt.ps1
Normal file
153
vcx2txt.ps1
Normal file
@@ -0,0 +1,153 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Converteste in TEXT (.vc2/.sc2/.fr2/.mn2/.dc2/.lb2) librariile/formele VFP binare,
|
||||
ca sa poata fi cautat codul din proceduri/metode cu grep.
|
||||
|
||||
.DESCRIPTION
|
||||
Implicit ("project mode"), converteste DOAR fisierele incluse in proiect (citite din .pjx),
|
||||
nu tot folderul COMUN (care contine multe librarii nefolosite in ROAACNPRO).
|
||||
|
||||
Pentru fiecare fisier copiaza binarul + memo-ul (.vct/.sct/...) intr-un folder de cache care
|
||||
oglindeste structura proiectului (ca sa NU murdareasca arborele SVN), ruleaza FoxBin2Prg.exe
|
||||
acolo, si pastreaza doar fisierul TEXT. Incremental: sare peste ce e deja la zi.
|
||||
|
||||
NU e nevoie de IDE-ul VFP deschis (se foloseste FoxBin2Prg.exe compilat).
|
||||
|
||||
.PARAMETER Source
|
||||
Optional. Daca e dat, ignora proiectul si converteste exact: un fisier .vcx/.scx/... SAU un
|
||||
folder (recursiv). Folosit pentru conversii punctuale.
|
||||
|
||||
.PARAMETER Project
|
||||
Fisierul .pjx din care se citeste lista de fisiere (implicit roaacnpro.PJX).
|
||||
|
||||
.PARAMETER Types
|
||||
Ce extensii sa includa in project mode (implicit vcx,scx = cod). Ex: -Types vcx,scx,frx,mnx
|
||||
|
||||
.PARAMETER ProjectRoot
|
||||
Radacina proiectului (implicit D:\ROA\ROAACNPRO). Caile din .pjx sunt relative la ea.
|
||||
|
||||
.PARAMETER CacheRoot
|
||||
Unde se scrie textul (implicit D:\ROA\UTIL\foxbin2prg\_textcache).
|
||||
|
||||
.PARAMETER Clean
|
||||
Sterge tot cache-ul inainte de conversie (util dupa ce s-au convertit accidental fisiere extra).
|
||||
|
||||
.PARAMETER Force
|
||||
Reconverteste chiar daca textul exista si e mai nou decat sursa.
|
||||
|
||||
.EXAMPLE
|
||||
# doar fisierele proiectului (recomandat, rapid)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1
|
||||
|
||||
.EXAMPLE
|
||||
# include si rapoartele si meniurile
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Types vcx,scx,frx,mnx
|
||||
|
||||
.EXAMPLE
|
||||
# conversie punctuala a unei librarii (chiar daca nu e in proiect)
|
||||
powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source D:\ROA\ROAACNPRO\COMUN\clase\caut.vcx
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[string]$Source,
|
||||
[string]$Project = 'D:\ROA\ROAACNPRO\roaacnpro.PJX',
|
||||
[string[]]$Types = @('vcx','scx'),
|
||||
[string]$ProjectRoot = 'D:\ROA\ROAACNPRO',
|
||||
[string]$CacheRoot = 'D:\ROA\UTIL\foxbin2prg\_textcache',
|
||||
[switch]$Clean,
|
||||
[switch]$Force
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$exe = 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE'
|
||||
if (-not (Test-Path $exe)) {
|
||||
throw "Nu gasesc $exe. Compileaza intai FoxBin2Prg (deschide foxbin2prg.pj2 in VFP si Build)."
|
||||
}
|
||||
|
||||
# binar -> (memo, extensie text)
|
||||
$map = @{
|
||||
'.vcx' = @('.vct', '.vc2'); '.scx' = @('.sct', '.sc2'); '.frx' = @('.frt', '.fr2')
|
||||
'.lbx' = @('.lbt', '.lb2'); '.mnx' = @('.mnt', '.mn2'); '.dbc' = @('.dct', '.dc2')
|
||||
}
|
||||
|
||||
function Convert-One($fullPath) {
|
||||
$f = Get-Item -LiteralPath $fullPath
|
||||
$ext = $f.Extension.ToLower()
|
||||
if (-not $map.ContainsKey($ext)) { return 'skip' }
|
||||
$memoX = $map[$ext][0]; $txtX = $map[$ext][1]
|
||||
$memo = [IO.Path]::ChangeExtension($f.FullName, $memoX)
|
||||
|
||||
$rel = $f.FullName
|
||||
if ($rel.ToLower().StartsWith($ProjectRoot.ToLower())) {
|
||||
$rel = $rel.Substring($ProjectRoot.Length).TrimStart('\')
|
||||
} else { $rel = $f.Name }
|
||||
$relDir = Split-Path $rel -Parent
|
||||
$workDir = if ($relDir) { Join-Path $CacheRoot $relDir } else { $CacheRoot }
|
||||
$txtOut = Join-Path $workDir ([IO.Path]::GetFileNameWithoutExtension($f.Name) + $txtX)
|
||||
|
||||
if (-not $Force -and (Test-Path $txtOut) -and ((Get-Item $txtOut).LastWriteTime -ge $f.LastWriteTime)) {
|
||||
return 'uptodate'
|
||||
}
|
||||
if (-not (Test-Path $workDir)) { New-Item -ItemType Directory -Force -Path $workDir | Out-Null }
|
||||
|
||||
$binCopy = Join-Path $workDir $f.Name
|
||||
Copy-Item -LiteralPath $f.FullName -Destination $binCopy -Force
|
||||
if (Test-Path $memo) { Copy-Item -LiteralPath $memo -Destination (Join-Path $workDir (Split-Path $memo -Leaf)) -Force }
|
||||
|
||||
& $exe $binCopy '' '' '' '1' '0' '1' | Out-Null
|
||||
|
||||
Remove-Item -LiteralPath $binCopy -Force -ErrorAction SilentlyContinue
|
||||
$memoCopy = Join-Path $workDir (Split-Path $memo -Leaf)
|
||||
if (Test-Path $memoCopy) { Remove-Item -LiteralPath $memoCopy -Force -ErrorAction SilentlyContinue }
|
||||
|
||||
if (Test-Path $txtOut) { return 'ok' } else { return 'fail' }
|
||||
}
|
||||
|
||||
# --- Construieste lista de fisiere ---
|
||||
$list = @()
|
||||
if (-not [string]::IsNullOrWhiteSpace($Source)) {
|
||||
if (Test-Path $Source -PathType Leaf) { $list = @((Get-Item -LiteralPath $Source).FullName) }
|
||||
elseif (Test-Path $Source -PathType Container) {
|
||||
$list = Get-ChildItem -LiteralPath $Source -Recurse -File |
|
||||
Where-Object { $map.ContainsKey($_.Extension.ToLower()) } |
|
||||
ForEach-Object { $_.FullName }
|
||||
} else { throw "Sursa nu exista: $Source" }
|
||||
} else {
|
||||
# PROJECT MODE: citeste .pjx -> pj2 si extrage fisierele
|
||||
if (-not (Test-Path $Project)) { throw "Nu gasesc proiectul: $Project" }
|
||||
$tmp = Join-Path $env:TEMP ('pjx_' + [IO.Path]::GetFileNameWithoutExtension($Project))
|
||||
New-Item -ItemType Directory -Force -Path $tmp | Out-Null
|
||||
$pjxName = [IO.Path]::GetFileName($Project)
|
||||
Copy-Item -LiteralPath $Project -Destination (Join-Path $tmp $pjxName) -Force
|
||||
$pjt = [IO.Path]::ChangeExtension($Project, '.pjt')
|
||||
if (Test-Path $pjt) { Copy-Item -LiteralPath $pjt -Destination (Join-Path $tmp ([IO.Path]::GetFileName($pjt))) -Force }
|
||||
& $exe (Join-Path $tmp $pjxName) '' '' '' '1' '0' '1' | Out-Null
|
||||
$pj2 = Join-Path $tmp ([IO.Path]::GetFileNameWithoutExtension($Project) + '.pj2')
|
||||
if (-not (Test-Path $pj2)) { throw "Conversia .pjx a esuat: $pj2" }
|
||||
|
||||
$extPat = ($Types | ForEach-Object { [regex]::Escape($_) }) -join '|'
|
||||
$rx = [regex]("(?i)\.ADD\('([^']*\.(?:$extPat))'\)")
|
||||
foreach ($m in $rx.Matches((Get-Content -Raw $pj2))) {
|
||||
$relp = $m.Groups[1].Value
|
||||
$abs = Join-Path $ProjectRoot $relp
|
||||
if (Test-Path $abs) { $list += (Get-Item -LiteralPath $abs).FullName }
|
||||
else { Write-Warning "lipsa: $relp" }
|
||||
}
|
||||
$list = $list | Sort-Object -Unique
|
||||
}
|
||||
|
||||
if ($Clean -and (Test-Path $CacheRoot)) { Remove-Item -Recurse -Force $CacheRoot }
|
||||
if (-not $list) { Write-Host 'Nimic de convertit.'; return }
|
||||
|
||||
$ok=0;$up=0;$fail=0
|
||||
foreach ($p in $list) {
|
||||
switch (Convert-One $p) {
|
||||
'ok' { $ok++; $r = $p; if ($r.ToLower().StartsWith($ProjectRoot.ToLower())) { $r = $r.Substring($ProjectRoot.Length).TrimStart('\') }; Write-Host "OK $r" }
|
||||
'uptodate' { $up++ }
|
||||
'fail' { $fail++; Write-Warning "ESEC $p" }
|
||||
}
|
||||
}
|
||||
Write-Host ''
|
||||
Write-Host "Gata. Convertite: $ok Sarite(la zi): $up Esuate: $fail (tipuri: $($Types -join ','))"
|
||||
Write-Host "Text in: $CacheRoot"
|
||||
Write-Host "Cauta cu: grep -rn 'expresie' `"$CacheRoot`""
|
||||
Reference in New Issue
Block a user