vfp-conventions
Skill4 starsChanged 29 days agoMITView on GitHub
Visual FoxPro coding conventions and patterns. Use when writing or reviewing VFP code, understanding naming conventions, variable prefixes, or VFP-specific patterns.
In this repository3 other files it gives its agents.
- debug-helperSkill
- form-editorSkill
- sql-helperSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 2 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 162
Close cursors explicitly: - don't rely on scope cleanup
- Distinctive: line 163
Use TABLEUPDATE(): after modifying buffered cursors
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
VFP Coding Conventions
Naming Conventions
Database Field Prefixes (CRITICAL!)
| Prefix | SQL Type | VFP Type | Example |
id* | INT IDENTITY/INT | Integer | idperson, idclient |
d* | DATE | Date | dbirthdate, ddeadline |
t* | DATETIME | DateTime | tlogon, tcreated |
n* | NUMERIC | Numeric | npercent, nprice |
c* | VARCHAR/CHAR | Character | cname, ccode |
l* | BIT | Logical | lactive, lbillable |
Variable Prefixes
| Prefix | Scope | Example |
gl_* | Global (PUBLIC) | gl_nSQLHandle, gl_cUser |
gll_* | Global saved to .mem file | gll_cExportPath |
m.* | Memory variables (Scatter) | m.cname, m.ddate |
lc* | Local Character | lcSQL, lcWhere |
ln* | Local Numeric | lnTotal, lnCount |
ld* | Local Date | ldStart, ldEnd |
ll* | Local Logical | llSuccess, llFound |
la* | Local Array | laResults, laFiles |
lo* | Local Object | loForm, loException |
Function Prefixes
| Prefix | Purpose | Example |
sql_* | SQL Server helpers | sql_exec(), sql_update() |
log_* | Logging functions | log_error(), log_info() |
get_* | Data retrieval | get_client(), get_settings() |
set_* | Data modification | set_status(), set_config() |
Code Patterns
1. VFP Does NOT Have ELSEIF!
*-- CORRECT - Use DO CASE
DO CASE
CASE nResult > 0
RETURN .T.
CASE nResult = 0
RETURN .T.
OTHERWISE
RETURN .F.
ENDCASE
*-- WRONG - VFP has no ELSEIF!
IF nResult > 0
RETURN .T.
ELSEIF nResult = 0 && COMPILE ERROR!
RETURN .T.
ENDIF2. SCATTER for Read, REPLACE for Write (NOT GATHER!)
*-- CORRECT - Scatter to read, REPLACE to write specific fields
SELECT clients
Scatter Memvar
m.cname = "New Name"
REPLACE cname WITH m.cname
TABLEUPDATE(.T.)
*-- WRONG - Gather sends ALL fields (risky!)
Scatter Memvar
m.cname = "New Name"
Gather Memvar && May overwrite fields you didn't intend to change!3. File Operations - Use STRTOFILE
*-- CORRECT - STRTOFILE for append
=STRTOFILE(lcText + CHR(13)+CHR(10), lcFile, .T.)
*-- WRONG - Fopen/Fputs/Fclose is fragile
lnHandle = Fopen(lcFile)
=Fputs(lnHandle, lcText)
=Fclose(lnHandle)4. NULL Handling
*-- CORRECT - Check type before comparison
IF VARTYPE(ddeadline) = 'D' AND ddeadline < DATE()
lcStatus = "Overdue"
ENDIF
*-- WRONG - Will crash if field is NULL
IF ddeadline < DATE() && Error if NULL!
lcStatus = "Overdue"
ENDIF5. Date Comparisons for "Overdue"
*-- CORRECT - < for strictly overdue (excludes today)
IIF(ddeadline < DATE(), "OVERDUE", "OK")
*-- WRONG - <= includes today (not overdue yet!)
IIF(ddeadline <= DATE(), "OVERDUE", "OK")6. Error Handling with TRY/CATCH
TRY
*-- Risky operation
USE sometable EXCLUSIVE
*-- Process data
CATCH TO loEx
*-- Handle error
log_error(loEx.Message + " in " + loEx.Procedure)
MESSAGEBOX("Error: " + loEx.Message, 16, "Error")
FINALLY
*-- Cleanup (always runs)
USE IN SELECT("sometable")
ENDTRY7. Safe Object Property Access
*-- CORRECT - Check object exists first
IF VARTYPE(loObject) = 'O' AND !ISNULL(loObject)
lcValue = loObject.Property
ENDIF
*-- WRONG - Will crash if object is NULL or doesn't exist
lcValue = loObject.PropertyCommon Errors
| Error | Cause | Solution |
| "Unrecognized command verb" | Used ELSEIF | Replace with DO CASE |
| "Operator/operand mismatch" | NULL comparison | Use VARTYPE() first |
| "Variable not found" | Missing m. prefix | Use m.varname with Scatter |
| "Property is read-only" | Modifying .Name | Some properties can't change at runtime |
Best Practices
- Always use m. prefix with SCATTER MEMVAR variables
- Prefer local variables (lc*, ln*) over public (gl_*)
- Close cursors explicitly - don't rely on scope cleanup
- Use TABLEUPDATE() after modifying buffered cursors
- Handle NULL values explicitly in comparisons
- Use TRY/CATCH for operations that might fail
- Log errors to help with debugging
Quick Reference
*-- String functions
ALLTRIM(string) && Remove leading/trailing spaces
UPPER(string) && Convert to uppercase
SUBSTR(string,n,m) && Extract substring
AT(search, string) && Find position
*-- Date functions
DATE() && Current date
DATETIME() && Current datetime
DTOC(date) && Date to character
CTOD(string) && Character to date
DTOS(date) && Date to string (YYYYMMDD)
*-- Type checking
VARTYPE(var) && Returns type letter (C,N,D,L,O,U,X)
TYPE("var") && Returns type (evaluates expression)
ISNULL(var) && Check if NULL
EMPTY(var) && Check if empty
*-- Array functions
ALINES(array, string, .T., CHR(13)+CHR(10)) && Split string to array
ALEN(array, 1) && Number of rows
ASCAN(array, value) && Find value in arrayResources
- VFPX Community
- VFP Language Reference
- FoxBin2Prg - Version control for VFP
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

