agentleFS
GSG-DevsGSG-Devs/claude-vfp-skills/skills/vfp-conventions/SKILL.md

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.

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
  1. Distinctive:

    Close cursors explicitly: - don't rely on scope cleanup

    line 162
  2. Distinctive:

    Use TABLEUPDATE(): after modifying buffered cursors

    line 163

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

VFP Coding Conventions

Naming Conventions

Database Field Prefixes (CRITICAL!)

PrefixSQL TypeVFP TypeExample
id*INT IDENTITY/INTIntegeridperson, idclient
d*DATEDatedbirthdate, ddeadline
t*DATETIMEDateTimetlogon, tcreated
n*NUMERICNumericnpercent, nprice
c*VARCHAR/CHARCharactercname, ccode
l*BITLogicallactive, lbillable

Variable Prefixes

PrefixScopeExample
gl_*Global (PUBLIC)gl_nSQLHandle, gl_cUser
gll_*Global saved to .mem filegll_cExportPath
m.*Memory variables (Scatter)m.cname, m.ddate
lc*Local CharacterlcSQL, lcWhere
ln*Local NumericlnTotal, lnCount
ld*Local DateldStart, ldEnd
ll*Local LogicalllSuccess, llFound
la*Local ArraylaResults, laFiles
lo*Local ObjectloForm, loException

Function Prefixes

PrefixPurposeExample
sql_*SQL Server helperssql_exec(), sql_update()
log_*Logging functionslog_error(), log_info()
get_*Data retrievalget_client(), get_settings()
set_*Data modificationset_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.
ENDIF

2. 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"
ENDIF

5. 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")
ENDTRY

7. 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.Property

Common Errors

ErrorCauseSolution
"Unrecognized command verb"Used ELSEIFReplace with DO CASE
"Operator/operand mismatch"NULL comparisonUse VARTYPE() first
"Variable not found"Missing m. prefixUse m.varname with Scatter
"Property is read-only"Modifying .NameSome properties can't change at runtime

Best Practices

  1. Always use m. prefix with SCATTER MEMVAR variables
  2. Prefer local variables (lc*, ln*) over public (gl_*)
  3. Close cursors explicitly - don't rely on scope cleanup
  4. Use TABLEUPDATE() after modifying buffered cursors
  5. Handle NULL values explicitly in comparisons
  6. Use TRY/CATCH for operations that might fail
  7. 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 array

Resources

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.