Wire up TO FILE for both LIST and DISPLAY: __dbList grows a 9th
parameter cFile, opens it (truncating any prior content) when non-
empty, and writes the formatted rows there via fmt.Fprintln. Default
behavior (no TO FILE) still goes to stdout.
std.ch gets two new rules placed *before* the regular LIST/DISPLAY
patterns so they win when TO FILE is present:
LIST [<v,...>] TO FILE <(f)> [OFF] [FOR] [WHILE] [NEXT] ...
DISPLAY [<v,...>] TO FILE <(f)> [OFF] [FOR] [WHILE] [NEXT] ...
Open failure raises a clear *HbError ("LIST/DISPLAY TO FILE: cannot
create <path> — <syscall reason>") so callers know exactly what went
wrong instead of getting partial-or-empty output.
TO PRINTER stays rejected via __dbNotImpl — Five doesn't drive a
printer port. Test coverage: tests/std_ch/test_list_to_file.prg
exercises four shapes (full LIST, single-row DISPLAY, OFF + FOR with
explicit fields, and confirms TO PRINTER still raises). Wired into
the std.ch runner so the regression suite now stands at 14/14.
Gates green:
go test ./... : PASS
FiveSql2 SQL:1999 : 43/43
Harbour compat : 56/56
std.ch suite : 14/14
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
74 lines
1.7 KiB
Plaintext
74 lines
1.7 KiB
Plaintext
/* LIST / DISPLAY TO FILE — text output redirected to a file. */
|
|
|
|
PROCEDURE Main()
|
|
LOCAL aStruct, cBuf, e
|
|
|
|
FErase("p.dbf")
|
|
FErase("out.txt")
|
|
|
|
aStruct := { ;
|
|
{ "ID", "N", 4, 0 }, ;
|
|
{ "NAME", "C", 10, 0 }, ;
|
|
{ "AGE", "N", 3, 0 } }
|
|
dbCreate("p.dbf", aStruct)
|
|
USE p.dbf NEW EXCLUSIVE ALIAS p
|
|
dbAppend(); FieldPut(1,1); FieldPut(2,"Alice"); FieldPut(3,18)
|
|
dbAppend(); FieldPut(1,2); FieldPut(2,"Bob"); FieldPut(3,25)
|
|
dbAppend(); FieldPut(1,3); FieldPut(2,"Carol"); FieldPut(3,30)
|
|
dbCommit()
|
|
|
|
/* 1. LIST TO FILE — full table */
|
|
dbGoTop()
|
|
LIST TO FILE out.txt
|
|
|
|
cBuf := MemoRead("out.txt")
|
|
? "1. file size:", Len(cBuf), "bytes (expect > 0)"
|
|
IF Len(cBuf) == 0
|
|
? "FAIL: empty output file"
|
|
RETURN
|
|
ENDIF
|
|
? "1. file content:"
|
|
? cBuf
|
|
|
|
/* 2. DISPLAY TO FILE — single record */
|
|
FErase("out.txt")
|
|
dbGoto(2)
|
|
DISPLAY TO FILE out.txt
|
|
|
|
cBuf := MemoRead("out.txt")
|
|
? "2. DISPLAY single-row file:"
|
|
? cBuf
|
|
IF !("Bob" $ cBuf)
|
|
? "FAIL: Bob row missing"
|
|
RETURN
|
|
ENDIF
|
|
|
|
/* 3. LIST TO FILE with OFF + FOR — std.ch pattern order is
|
|
`[<off:OFF>] [FOR <for>]`, same as Harbour. */
|
|
FErase("out.txt")
|
|
dbGoTop()
|
|
LIST p->id, p->name TO FILE out.txt OFF FOR p->age >= 25
|
|
|
|
cBuf := MemoRead("out.txt")
|
|
? "3. selective+OFF file:"
|
|
? cBuf
|
|
IF "Alice" $ cBuf
|
|
? "FAIL: Alice (age 18) shouldn't be in FOR age>=25 output"
|
|
RETURN
|
|
ENDIF
|
|
|
|
/* 4. TO PRINTER — should still reject */
|
|
e := .F.
|
|
BEGIN SEQUENCE
|
|
LIST TO PRINTER
|
|
RECOVER
|
|
e := .T.
|
|
END SEQUENCE
|
|
? "4. TO PRINTER rejected:", e, "(expect .T.)"
|
|
|
|
dbCloseArea()
|
|
FErase("p.dbf")
|
|
FErase("out.txt")
|
|
? "DONE"
|
|
RETURN
|