Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Articles
Search: 

How to create a custom script with intelliscript
Lutz Scheffler, June 4, 2004
Custom scripts are different from scripts that are invoked via a command or function. The big plus to command or function is that custom scripts may invoke everywhere in a line, while command can be invoked only as first word and functions need a "(". There are some problems to write a custom scr...
Summary
Custom scripts are different from scripts that are invoked via a command or function. The big plus to command or function is that custom scripts may invoke everywhere in a line, while command can be invoked only as first word and functions need a "(". There are some problems to write a custom script with intellisense. It is even uneasy to duplicate the examples zloc and zdef that ship with VFP8.0 and beyond. This FAQ points to the steps to create a custom script. It will use a IF .. ENDIF statement the automaticaly adds a comment to the ENDIF as example.
Description
0. If you like to browse _foxcode via intellisense manager and like to use LOCATE instade of browsing, note that the you need to change datasession. 1. Enable custom scripting in intellisense manager lAllowCustomDefScripts .T. 2. A new entry in the _FoxCode table. Open it via intellisense manager. Add a new record and fill the fields like type = 'S' abbrev = 'th' cmd = '{}' case = 'M' save = .T. and the data memo with the script below. The script has two main parts. The first part handles the way Intellisense calls this script, the second is the "payload". Please see the comments.
LPARAMETERS;
 toFoxScript

* note the use of toFoxScript what is the parent of the oFoxcode normaly used
* this gives extended access
* the PEMs normaly usedin a script are at toFoxScript.oFoxcode

* To enable this script, make sure that you have the lAllowCustomDefScripts
* custom property set to .T. (you can set this in the IntelliSense Manager).

* This script expandes a IF Statement to
* IF Statement THEN
*
* THEN &&Statement
* keeps indent

*Section needed in all scripts
LOCAL;
 lcFxToolLib AS STRING,;
 lcLastWord  AS STRING,;
 lnWinHdl    AS INTEGER

LOCAL lvReturn_On_Error AS VARAINT

*this is because VFP 7.0 need other retuirn value for wrong
IF VERSION(5)<800 THEN
 lvReturn_On_Error = ''
ELSE &&VERSION(5)<800
 lvReturn_On_Error = .F.
ENDIF &&VERSION(5)<800

IF toFoxScript.oFoxcode.Location=0 THEN &&toFoxScript.oFoxcode ... &&Command Window
 RETURN lvReturn_On_Error
ENDIF

*since all custom scripts in CustomDefaultScripts will be called, we need to check if we are the one to call
*this is by MS and need to be changed
IF VERSION(5)<800 THEN
*this is because VFP 7.0 does not know toFoxScript.cCustomScriptName. VFP 8.0 is generic
 IF !UPPER(toFoxScript.cCMD)='TH'   &&Script = TH
  RETURN lvReturn_On_Error
 ENDIF
ELSE &&VERSION(5)<800
 IF !UPPER(toFoxScript.oFoxcode.UserTyped) == UPPER(toFoxScript.cCustomScriptName)   &&Script = TH
  RETURN .F.
 ENDIF
ENDIF &&VERSION(5)<800

lcFxToolLib = SYS(2004)+"FOXTOOLS.FLL"
IF !FILE(lcFxToolLib)
 RETURN lvReturn_On_Error
ENDIF
SET LIBRARY TO (m.lcFxToolLib) ADDITIVE
*/Section needed in all scripts

*Custom part
LOCAL;
 lcCompiler AS CHARACTER,;
 lcLeft     AS CHARACTER,;
 lcFullLine AS CHARACTER,;
 lcLine     AS CHARACTER,;
 lcMyVa     AS CHARACTER,;
 lnLen      AS INTEGER,;
 lnLeft     AS INTEGER,;
 lnRight    AS INTEGER,;
 lnOr       AS INTEGER,;
 lnAnd      AS INTEGER

lcFullLine = toFoxScript.oFoxcode.FullLine
lcFullLine = LEFT(lcFullLine,LEN(lcFullLine)-LEN(toFoxScript.cCustomScriptName))
lcLine     = LTRIM(lcFullLine)
lcCompiler = IIF(lcLine='#','#','')
lcLeft     = STRTRAN(lcFullLine,lcLine,'')
lnLeft     = AT(' ',lcLine)
lnRight    = RAT(' ',lcLine)
*first 30 signs only.
lcLine     = SUBSTR(ALLTRIM(SUBSTR(lcLine,lnLeft+1,lnRight-lnLeft-1)),1,30)

TEXT TO myvar TEXTMERGE NOSHOW
THEN
<<lcLeft>> ~
<<lcLeft+lcCompiler>>ENDIF &&<<lcline>>
ENDTEXT

*Remove last word, only if neede by the script.
lcLastWord = ALLTRIM(GETWORDNUM(toFoxScript.oFoxcode.FullLine, GETWORDCOUNT(toFoxScript.oFoxcode.FullLine)))
IF VERSION(5)<800 THEN
*this is because VFP 7.0 does not know toFoxScript.cCustomScriptName. VFP 8.0 is generic
 lcLastWord = LEFT(lcLastWord, LEN(lcLastWord) - 2)
ELSE &&VERSION(5)<800
 lcLastWord = LEFT(lcLastWord, LEN(lcLastWord) - LEN(toFoxScript.cCustomScriptName))
ENDIF &&VERSION(5)<800
toFoxScript.ReplaceWord(lcLastWord)
* Handle extra space
IF ASC(RIGHT(toFoxScript.oFoxcode.FullLine,1))=32
 lnWinHdl = _WONTOP()
 _EDSETPOS(lnWinHdl, _EDGETPOS(lnWinHdl) - 1)
ENDIF

*Returnvalue
toFoxScript.oFoxcode.ValueType = "V"
RETURN myvar
*/Custom part
3. to have the script is not enough. We need that add it to a list of scripts available. This in the _FoxCode table. The record you is like
LOCATE FOR TYPE='Z' AND Abbrev='CustomDefaultScripts '
. To the data memo of those record add a line end enther "th" The steps above are needed for each new custom script. Skip the next Step if you use VFP 7.0 4.Since our script ValueType = "V" we need to return the value. The zloc and zdef scripts work, but they are of ValueType = "L" that returns a different way. The problem is, that custom scripts are called by a default script. This script does not return the value (in VFP8.0 and 9.0) so we need to change this. Select the record
LOCATE FOR TYPE='Z' AND EMPTY(Abbrev)
. Alter the data memo to:
* Default script triggered by a space -- used for commands only
LPARAMETER oFoxCode
LOCAL loFoxCodeLoader, lcLine, lcCmd, lnWords, lcLastCmd, lcTalk
LOCAL;
 lvReturn AS VARIANT

IF !FILE(_CODESENSE)
 RETURN ""
ENDIF

lcLine = ALLTRIM(oFoxCode.FullLine)
lcCmd =  UPPER(ALLTRIM(GETWORDNUM(lcLine,1)))
lnWords = GETWORDCOUNT(lcLine)
lcLastCmd = GETWORDNUM(lcLine,lnWords)
IF EMPTY(lcLine) OR LEFT(lcLine,1)="*" OR ;
  ATC("L", _VFP.EDITOROPTIONS)=0 OR ;
  UPPER(lcLastCmd)=="AS"
 RETURN ""
ENDIF

SET PROCEDURE TO (_CODESENSE) ADDITIVE
loFoxCodeLoader = CREATEOBJECT("FoxCodeLoader")
lvReturn = loFoxCodeLoader.START(m.oFoxCode)
loFoxCodeLoader = NULL
IF ATC(_CODESENSE,SET("PROC"))#0
 RELEASE PROCEDURE (_CODESENSE)
ENDIF
*return is Charcter
IF VARTYPE(lvReturn)='C' THEN
 RETURN lvReturn
ENDIF &&VARTYPE(lvReturn)='C'
RETURN ""

DEFINE CLASS FoxCodeLoader AS FoxCodeScript
 PROCEDURE MAIN()
  LOCAL;
   lvReturn AS VARIANT
  lvReturn = THIS.DefaultScript()
  RETURN lvReturn
 ENDPROC
ENDDEFINE
. New is the usage of lvReturn. Now we can enter in a code edit window
IF Test TH
followed by a space and it should expand to
IF Test THEN
 
ENDIF &&Test
The cursor placed in the empty line.
Lutz Scheffler, Lutz Scheffler Software Ingenieurbüro
More articles from this author
Lutz Scheffler, May 8, 2009
When printing, sometimes there is a need to know if a report is printed or not. Since we have no simple way to see if something is realy printed we can at least check if the user send a complete report to the spooler. This article deals with the way to solve this problem with and without object as...
Lutz Scheffler, June 2, 2009
A commonly problem seems to be to run an app with the VFP Version / SP it is compiled. VFP itself gives not much help on this. But some little compiler commands like #IF and #DEFINES will do the trick.