Author's note: the following article was produced from the
previous text-based version of the Commander documentation and task list (commandr.txt) last updated on
1/13/2000. I transformed this
text file mechanically into HTML with minimal editing to put it into a more
useful, legible form. There will be no further revisions of commandr.txt,
as this task list has been superseded by the new Commander
page and its accompanying section in the table of contents, which is handled
with a FrontPage include file for the outline of
tasks. The tasks described in these old
notes will eventually be assimilated into the new system, but this will be
a gradual process.
Preliminary Notes About the Generic Commandr Application
By M. Asherman, 1/13/2000
The Commander (aka Commandr) application is a generic table-driven facility for defining functions. It supports optional user-defined arguments and return values, nested and recursive functions. There is a convenient wrapper function interface, commandr(), plus a pure object-oriented class, Commander, in commandr.vcx. For a quick look at some examples, type the following command from VFP command level:
This will automatically initialize the default meta-file and evaluate the default sample function, which just displays a WAIT WINDOW message. Creation and maintenance of the Commander meta-file can be done via VFP's BROWSE command, and this is made easier by taking advantage of VFP's Browse preferences, e.g. via the BROWSE LAST option. Of course you can also populate the Commander meta-file programmatically, which is a major benefit of the meta-file based design. See the Saver application for an example of totally programmatic meta-file creation and use of the Commander facility.
To clean up after testing commandr() without closing out the current VFP session, use this command:
This will release the default Commander object and close the meta-file. This is mainly useful during development and testing of the Commandr facility itself, to avoid "class is in use" errors.
Currently available documentation:
- annotated examples are in the sample meta-file, commandf.dbf (see the Notes field)
- run commandr() to see the first sample table-driven function
- brief descriptions have been attached to all files in commandr.pjx
- there are DBC-based field comments for all meta-file fields (in
- all programs are liberally commented
- see additional usage notes in comments in commandr.prg and method Commander.DoFunc
- see the commandr.h include file for error codes and hard-wired constants
- note that certain generic mdacomm functions are employed in the sample meta-file
- also see cmdrclon.prg for handy utility to clone entire function definitions
Related outstanding issues and tasks (* indicates it can wait):
- provide an error-trapping mechanism that can work with command-line representation
Use the Commander.Error event method to catch errors during the &cmd expansion in Commander.DoFunc logic, and allow these errors to fail cleanly with a non-zero Commander.ErrorCode. Use the new generic ErrHandler class to support this, along the same lines as changes made to
- use VFP's newobject() function and method where appropriate
To avoid annoying hassles with older SET CLASSLIB + add/createobject() approach.
- introduce a PRIVATE mvar for convenient reference to the Commander object itself
So that a table-driven function can invoke a nested function in the same meta-file, using the same Commander.DoFunc() directly (as opposed to the commandr() UDF interface).
- Commander.AddFuncStep should clear the Notes field when re-using a deleted record
- *- provide additional user/developer documentation of the Commandr facility
- *- support a more flexible way to assign default alias for the meta-file
Currently this is a macro-defined constant, CMDR_ALIAS, defined in the commandr.h include file. A more flexible way to define this would be via a property in the Commander class, which would be initialized by that macro, but should be settable to an alternate value. This would avoid conflicts when multiple Commander objects coexist within a common data session.
- *- allow for functional expression representation, with success flag
I.e. instead of expressing the step as a command line, let it be a functional expression that returns a success flag for the individual step, which would be tested by the Commander.DoFunc loop logic. This should be more efficient than the present reliance on ¯o expanded command lines. However, for most purposes the performance of the present implementation should be entirely satisfactory.
- *- a "goto" mechanism would be handy (but not essential)
This would be especially useful for looping and block coding constructs, which are otherwise awkward to express in individual command lines. The mechanism could be provided by introducing a new PRIVATE mvar, e.g. m.cmdr_next, whose assignment would tell Commander.DoFunc to jump directly to the step with the specified sequence #, for example.
- *- maybe it would be useful to have a parent-level of "procedure" record
But this doesn't seem necessary, except as an annotation and organizational aid. The core Commander class logic should not depend on the existence of this parent meta-file.
- *- form-based meta-file maintenance facility
Should not be initially needed, because Browse + handy UDFs is adequate for basic meta-file manipulations.
- *- conditional return expression syntax: *[expr1]*expr2
Evaluates expr1 and returns eval(expr2) if eval(expr1) = .T. This can be used to construct a concise CASE statement construct as a subfunction, for example.
- *- verify current &-expansion limit by careful tests and #define a macro for this
Preliminary tests indicate this restriction may not be nearly as severe under VFP SP3 as I recall it to have been in the past. There may be many specific types of limits in certain contexts, but evidently not in &-macro expansion itself.
- *- adjust logic in Commander.DoFunc to supprt cmdprg() instead of macro expansion
I.e. automatically use this approach when macro limit would otherwise be exceeded, causing an error. There's no point in messing with this unless clear instances of exceeding the limit show up again. Wait for the problem to resurface.
General guidelines and conventions:
@- maintain consistent usage notes between wrapper function and corresponding method
For this app, that means commandr.prg and corresponding Commander.DoFunc.
@- maintain clean copies of selected files in shared mdacomm directory
For Commander, this includes commandr.app/h/txt/vcx/vct + cmdrtmpl.DBF/FPT/CDX +
@- rebuild dependent apps after changes to shared Commander stuff
@- maintain thorough error and escape-handling provisions
@- all apps should avoid potential name conflicts in case moved into mdacomm
E.g. avoid file names like "notes.txt" in favor of "<appname>.txt".
@- avoid using the same prefix for macro name and anything else (e.g. global mvars)
Remember that VFP is case-insensitive with respect to names, so take care not to accidentally use a macro name unintentionally by sticking to a unique prefix. Unfortunately, I didn't think of this issue when I first coded the Commander application, and my choice of global mvar naming conventions violates this principle. Specifically, the macros use "CMDR_" prefix and global mvars use "cmdr_" prefix, which risks confusion. However none of the current macro names actually conflict with global mvar names, so this is not a serious problem.
990529 added property Commander.quietnofunc to suppress error msg. on functionid not found
990529 new method Commander.DeleteFunc(funcid) for deleting records
990529 new method Commander.AddFuncStep(funcid, seq, cmdline) for appending records
990529 adjust field comments on commandf.modidate: this is no longer optional
990608 revised macro CMDR_CLIB in commandr.h to avoid inclusion of "ADDITIVE" here
990608 support auto-creation of meta-file from bound template
990610 added test case demo08 to demonstrate proper cleanup for default demo mode
990610 don't assume the Commander meta-file necessarily has a "DBF" extension
990611 new property, metafilepath, for holding on to fully-qualified meta-file path/name
990629 extension to support direct string assigments without macros or eval()
Introduce a special syntax for an alternative way of expressing a processing step that reduces to a string assignment statement, instead of the usual (more general) macro-expanded command line interpretation. In this new syntax, distinguished by a reserved prefix, there would be an initial portion giving a variable name expression, followed by a reserved delimiter, followed by the character string to assign to the preceding variable. There would be no surrounding quotes for this type of assignment; just take the rest of the memo field as the value to assign. This allows for a simple, efficient way of handling arbitrary strings values, which could be very long or contain special characters that would be difficult to handle otherwise.
990629 create example, demo09, illustrating new string assignment flavor of cmdline
990629 adjust field notes for cmdline to mention special string assignment syntax
990629 review/adjust Commander-based apps to take advantage of new string assigment syntax
The special string assignment syntax, *=(name expression)=*string value..., is the preferred way to handle literal string assignments. This is both more efficient and more flexible than the usual &-macro expansion technique that Commander uses otherwise. The new syntax can support much longer strings, and there are no restrictions on use of special characters.
990629 test out usage in a private data session
As far as I know, this will work, but it's not yet tested. We may as well wait until a suitable application comes up for this feature, which should happen shortly in the planned implementation of a generic state saving and restoration facility.
990719 create new cmdrclon.prg - stand-alone utility for cloning function definitions
991021 make adjustments for move from M: to D:
This entails the following steps:
- adjust icon for launching VFP to start in dir on D:... and use -cd:... option
- config.fpw should be ok as-is - we already eliminated hard-wired drive/path
- open .pjx and tell dialog OK to move it from M: to D:
- confirm that all files in project have been relocated to D:, as expected
991021 introduce a separate method, cmdrm_open, to perform opening of meta-file
Use this function in Init and other methods that require accessing the meta-file to support automatic re-opening of meta-file if unexpectedly closed.
991021 add new property, cmdrp_funcidlen, containing the functionid length
Since we can't assume the Commander meta-file is directly accessible outside of Commander (caller may be in another data session). Initialize this in method
991022 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\COMMANDR\ & ...MDACOMM\ ****
991116 add new method Commander.cmdrm_seekfunc, which does a lookup for a given functionid
This is helpful for support of Saver's Delete button enablement.
991130 extend cmdrclon.prg to support a separate target meta-file
Also entailed changes to generic clonerec.prg, and I threw in a some cleanups to
991203 **** UPLOADED CHANGES TO BT SERVER'S D:\REDP\APPL\COMMANDR\ & ...MDACOMM\ ****
000111 create new stand-alone UDF, cmdprg.prg, to generate/compile/run/cleanup a PRG
This should be able to serve as a replacement for macro-expansion of command lines, for both greater efficiency and to avoid restrictive macro length limits. Let cmdprg.prg/fxp reside in mdacomm only, since this really is a generic stand-alone utility, not a piece of commander (although it's related).
Copyright © 2000- 2002, SpaceTime Systems