(Updated: 2010.02.06 05:15:56 PM)
| |
Please post interesting/useful/fun custom scripts you've written for Intellisense ... one of
Category 3 Star Topics.
Visual FoxPro's IDE is extensible au max. Take
Intellisense, for example.
Table Of Contents
Example -- MC -> MODIFY COMMAND
DOC -> Produce a DO CASE.. OTHERWISE statement
HTTAB -> Produce a skeleton HTML TABLE
GENUP -> Generate a SQL UPDATE statement
LOCALS -> Create a LOCAL declaration
EXCEL -> Create Excel Automation template
CHG -> Place a Comment noting date changed and by whom
IFE -> Create an IF..ENDIF structure
ERR -> Generate Error Reporting Code
PCHK -> Check the parameters passed to a function
MULTI - Program to Add All VCX classes to Intellisense
CCD -> Place a Comment noting date and time changed and by whom
FACT -> Create a call to object Factory function
SEL -> In the command window, drop down a list of all open tables.
TODO -> Place a TODO comment (for Task list) including Date Placed ( changed [2006.07.11] - edyshor)
UDF - Program to Extract all PROC/FUNC/PARAM statements from a PRG into Intellisense
UDF2 - Enhanced Program to Extract all PROC/FUNC/PARAM statements from a PRG into Intellisense including Inline Parameters
DEFLIST -> Show #DEFINEs in drop-down list
FRMPARAMS -> Show form parameters with DO FORM formname WITH
CLIP - Expand CT to _ClipText
Typos - Automatically correct typos
Header information - Create a header for your files
Function / Procedure bodies - Create a function / procedure body in your prg
Function / Procedure creation -> Create function/proc in your code , with additional features
'Wait window' shortcut - use wwn for "wait window nowait"
SelectAll - Generate a SELECT statement that enumerates all the field names
IntelliSenseCustomScripts_TableFieldList - Table and Field listing in a Program or Method window
|
How-to Create a Custom Script
(so examples don't need to repeat this information)
- Open the Intellisense manager via the menu (Tools | IntelliSense Manger) or programmatically with
DO FOXCODE.
- Select the Custom tab
- Enter the short cut text (such as, DC, in the out-of-the box example)
- Click Add
- Click Script
- Foxcode that is shown below goes in this memo field. Note that it's *just* a memo, it's not a code window.
|
For examples and references other than this page, see the help topics "Customizing
IntelliSense Using Foxcode" and "Foxcode Object Reference"
Background and Example:
You can add a record with a "macro" shortcut that include scripts (in memo fields of this table) that will allow you to do things like:
(you type:
MC) VFP expands that to
MODIFY COMMAND
And the difference between this and CEE (besides being native) is... ?
There is little difference. It is now native and part of the Intellisense table. There is a 'console' to manage this table that makes it easy to handle, besides of coure being able to BROWSE it and edit from the command box. As soon as we study the table's capabilities a little more we'll come up with more ideas and samples that might show some other differences.
Code Templates
Create an IF..ENDIF structure
This is a simple one called IFE to create an IF..ENDIF structure
LPARAMETER oFoxCode
* 0 – Command Window
* 1 – Program
* 8 – Menu Snippet
* 10 – Code Snippet
* 12 – Stored Procedure
IF oFoxcode.Location # 1 and oFoxcode.Location # 10
RETURN "IFE"
ENDIF
oFoxcode.valuetype = "V"
LOCAL lcWhat, lcRetval
lcWhat = INPUTBOX("Enter IF condition","VFP","")
text to lcRetVal textmerge noshow
if < < lcWhat > >
~
else
endif && < < lcWhat > >
endtext
RETURN lcRetVal
--
Alex Feldstein
Produce a DO CASE.. OTHERWISE statement
Fill in the following table fields:
Type = "U"
abbrev = "DOC"
command = {}
In Data Field:
LPARAMETERS oFoxcode
* 0 – Command Window
* 1 – Program
* 8 – Menu Snippet
* 10 – Code Snippet
* 12 – Stored Procedure
IF oFoxcode.Location # 1 and oFoxcode.Location # 10
RETURN "DOC"
ENDIF
oFoxcode.valuetype = "V"
LOCAL lnCases, llOWise, lcRetval
lnCases = VAL(INPUTBOX("Enter number of CASEs","VFP","2"))
IF lnCases < 1
lnCases = 2 && default
ENDIF
llOWise = MESSAGEBOX("Do you want an OTHERWISE?",4,"VFP") = 6
SET TEXT ON NOSHOW
SET TEXTMERGE TO MEMVAR lcRetVal
\DO CASE
\CASE ~
FOR n = 1 TO lnCases - 1
\CASE
ENDFOR
IF llOWise
\OTHERWISE
ENDIF
\ENDCASE
SET TEXTMERGE TO
SET TEXTMERGE OFF
RETURN lcRetVal
and it places the cursor at the beginning in the first CASE ready for you to type. You could even have a dialog first that asks you how many
CASE and if you want an
OTHERWISE!
RETURN oFoxCode.Abbrev instead of
RETURN "DOC" avoids the need for hard coding
Geoff Franklin
Informative header
create a header for your files
Type = U
abbrev = hdr
cmd = {}
Data
LPARAMETERS oFoxcode
LOCAL lcPurpose
IF oFoxcode.Location = 0
RETURN "header"
ENDIF
oFoxcode.valuetype = "V"
TEXT TO lcHeader TEXTMERGE NOSHOW
**********************************************************************
* Program....: < < wtitle(wontop()) > >
* Version....:
* Author.....: YourName here
* Date.......: < < dmy(date()) > >, < < time() > >
* Notice.....: Copyright © < < TRANSFORM(Year(date()) ) > >, CompanyNameHere.
* All Rights Reserved.
* Compiler...: < < version() > >
* Abstract...:
* Changes....: < < Getenv("USERNAME") > >, Created < < dmy(date()) > > / < < time() > >
* Parameters.:
* Called by..:
* Purpose....: ~
**********************************************************************
ENDTEXT
RETURN lcHeader
Create function or procedure body in your prg
to get function bodies filled in for you in prg files
you need two records for this:
record 1:
Type="S"
abbrev="document"
cmd = {}
Data
LPARAMETER oFoxCode
LOCAL lcParam, lcParamDescript, lcType, lnI, lcName, lcDescription, lnParameters, lcRetVal
lcParam = ""
lcParamDescript = ""
* Run everywhere but not in the command window
IF oFoxCode.Location = 0
return "FUN"
ENDIF
* we want to return a value
*
oFoxcode.valuetype = "V"
* read the user field in the record that called this script.
* what do you want to create, a FUN or a PRO.
*
IF oFoxCode.user = "F"
lcType = "FUNCTION"
ELSE
lcType = "PROCEDURE"
ENDIF
* get the name
*
lcName = inputbox(lcType+" Name:", _screen.caption)
* and some descriptive description
*
lcDescription = inputbox(lcType+" Description:",_screen.caption)
* read the number of parameters
*
lnParameters = val( inputbox(lcType+" Number of parameters:",_screen.caption,"1") )
* some code to execute when there are 1 or more parameters
*
IF lnParameters > 0
FOR lnI = 1 to lnParameters
* fill the lcParam variable
*
lcParam = lcParam+inputbox("Parameter "+alltrim(str(lnI))+" Name",_screen.caption)+", "
* some descriptive text for the parameter would be nice for documenting purposes.
*
lcparamDescript = lcparamDescript+"Parameter "+alltrim(str(lnI))+": "+;
inputbox("Parameter "+alltrim(str(lnI))+" Description: ", _screen.caption) +chr(13) +chr(10) +"* "
ENDFOR
* strip off the last ", " from the parameter list
lcParam = substr(lcParam,1, len(lcParam)-2)
ENDIF
* determine the type of return value
*lcParamType =
* make a block of text to return
*
TEXT TO lcRetVal TEXTMERGE NOSHOW
*******************************************
* < < lcType > > < < lcName > >( < < lcparam > > )
* Date : < < DATE() > >, < < time() > >
* author : < < GETENV("USERNAME") > >
* description: < < lcDescription > >
****** PARAMETERS **************
* Parameters : < < alltrim( str(lnParameters)) > >
* < < lcParamDescript > >
*******************************************
< < lcType > > < < lcName > > ( < < lcParam > > )
~code goes here~
END < < substr(lctype,1,4) > >
ENDTEXT
RETURN lcRetVal
The second record
Type = U
abbrev = fun
cmd = {document}
user = F
data
LPARAMETER oFoxCode
For procedures you simply make another record
same as above
make the abbrev = pro
user = P
typing "pro" in your prgfile will give you a full PROCEDURE body then.
Enhanced ability to create functions or procedures in your prg
Like the previous example, the following script allows you to create functions/procedures by prompting you for names and parameters. It also allows you to specify a return value and tries to initialize it based on the second letter of the return variable you specify.
As with the previous example, you'll need to create two records in foxcode:
Record 1:
Type="S"
abbrev="document"
cmd = {}
Data
LPARAMETER oFoxCode
oFoxCode.valuetype = "V"
LOCAL lcParam, lcParamDescript, lcType, lnI, lcName, lcDescription, lnParameters, lcRetVal
LOCAL lnAt, lcTemp, lcThisParmName, lcThisParmDescribe
LOCAL lcRetVar, lcLOCALRetVarString, lcLocalRetVarInitString, lcRETURNstring
* Run everywhere but not in the command window
IF oFoxCode.Location = 0
RETURN "FUN"
ENDIF
* Read the user field in the record that called this script.
* what do you want to create, a FUN or a PRO.
*
IF oFoxCode.USER = "F"
lcType = "FUNCTION"
ELSE
lcType = "PROCEDURE"
ENDIF
lcParam = ""
lcParamDescript = ""
* get the name
*
lcName = INPUTBOX(lcType+" Name:", _SCREEN.CAPTION)
* and some descriptive description
lcDescription = INPUTBOX(lcType+" Description:",_SCREEN.CAPTION)
* read the number of parameters
lnParameters = VAL( INPUTBOX(lcType+" Number of parameters:",_SCREEN.CAPTION,"1") )
* some code to execute when there are 1 or more parameters
*
IF lnParameters > 0
FOR lnI = 1 TO lnParameters
lcTemp = INPUTBOX("Parameter "+ALLTRIM(STR(lnI))+" Name [, Description]",_SCREEN.CAPTION)
lnAt = AT(",",lcTemp)
IF lnAt > 0
lcThisParmName= LEFT(lcTemp,lnAt-1)
lcThisParmDescribe = SUBSTR(lcTemp,lnAt+1)
ELSE
lcThisParmName= ALLTRIM(lcTemp)
lcThisParmDescribe = ""
ENDIF
lcParam = lcParam+lcThisParmName+", "
lcParamDescript = lcParamDescript+CHR(9) + "Parameter "+ALLTRIM(STR(lnI))+": "+ lcThisParmName + " - " ;
+ lcThisParmDescribe +CHR(13) +CHR(10) +"* "
ENDFOR
* strip off the last ", " from the parameter list
lcParam = SUBSTR(lcParam,1, LEN(lcParam)-2)
ENDIF && lnParameters > 0
lcRetVar = INPUTBOX("RETURN varname:",_SCREEN.CAPTION)
lcLOCALRetVarString = IIF(LEN(RTRIM(lcRetVar))>0,"LOCAL " + lcRetVar,"")
lcLocalRetVarInitString = ""
DO CASE
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "C"
lcLocalRetVarInitString = lcRetVar + [ = "" ]
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "D"
lcLocalRetVarInitString = lcRetVar + [ = {} ]
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "T"
lcLocalRetVarInitString = lcRetVar + [ = {:} ]
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "N"
lcLocalRetVarInitString = lcRetVar + [ = 0 ]
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "Y"
lcLocalRetVarInitString = lcRetVar + [ = $0.00 ]
CASE LEN(lcRetVar) >=2 AND UPPER(SUBSTR(lcRetVar,2,1)) = "L"
lcLocalRetVarInitString = lcRetVar + [ = .F. ]
ENDCASE
IF LEN(lcLocalRetVarInitString) > 0
lcLocalRetVarInitString = lcLocalRetVarInitString + [ ] + CHR(38) + CHR(38) + [ Initialize]
ENDIF && LEN(lcLocalRetVarInitString) > 0
lcRETURNstring = IIF(LEN(RTRIM(lcRetVar))>0,"RETURN " + lcRetVar,"RETURN .T.")
*
TEXT TO lcRetVal TEXTMERGE NOSHOW
* Note: < < > > brackets include spaces to avoid wiki parsing
< < lcType > > < < lcName > >
*********************************************************************************************************************************
* Date : < < DATE() > >, < < time() > >
* Author : < < GETENV("USERNAME") > >
* Description: < < lcDescription > >
* Parameters : < < alltrim(str(lnParameters)) > >
* < < lcParamDescript > >
*********************************************************************************************************************************
LPARAMETERS < < lcParam > >
< < lcLOCALRetVarString > >
< < lcLocalRetVarInitString > >
~
< < lcRETURNstring > >
*********************************************************************************************************************************
END< < substr(lctype,1,4) > > < < CHR(38) > >< < CHR(38) > > < < lcName > >
ENDTEXT
RETURN lcRetVal
If you're copying and pasting the above code, remember to get rid of the extra spaces between the brackets, which were inserted
to prevent wiki parsing.
The second record will call the first record you just created, when you type the letters
fun while editing a .prg:
Type = U
abbrev = fun
cmd = {document}
user = F
data
LPARAMETER oFoxCode
For procedures, simply create yet another record, very similar to the one above:
Type = U
abbrev = pro
cmd = {document}
user = F
data
LPARAMETER oFoxCode
Dave Martin
Wait window shortcuts
For a wait window nowait
type = U
abbrev = wwn
cmd = {}
LPARAMETERS oFoxcode
oFoxcode.valuetype = "V"
TEXT TO myvar TEXTMERGE NOSHOW
WAIT WINDOW NOWAIT "~"
ENDTEXT
RETURN myvar
Boudewijn Lutgerink
Generate a SQL UPDATE statement
You can also do this kind of code generation to pump out SQL code:
Fill in the following table fields:
Type = "U"
abbrev = "genup"
command = {}
In Data Field:
***********************************
LPARAMETERS oFoxcode
#DEFINE CRLF chr(13) + chr(10)
IF oFoxcode.Location # 1
RETURN "FC"
ENDIF
oFoxcode.valuetype = "V"
cUpdateStr = "Update " + alias() +" set ;" + CRLF
nfldcount =afields(afldlist)
cfldlist = ""
for idx = 1 to nfldcount
cfldlist = cfldlist + afldlist[idx,1] + ;
" = m." + afldlist[idx,1] + iif(idx != nfldcount, "; " + CRLF,"")
endfor
RETURN cUpdateStr + cfldlist
***************************
This will take the current open table and create a SQL update command using memvars and insert it into the current cursor position in the editor.
--
Harold Chattaway
Create a LOCAL declaration
Creates the 'LOCAL' declaration by scanning a codeblock for variables named using the Hungarian Notation convention.
--
Rhodri C Evans
*!* Intaller - this will install the script into the intellisense table:
DO Add2IntelliSense WITH "locals", "", Locals(), "U"
DO Add2IntelliSense WITH "locals6", "", Locals(), "U"
PROCEDURE Add2IntelliSense( lcAbbr, lcLong, tcCode, tcType )
LOCAL cTAlias, lpdwReserved,lpdwType, z
cTAlias = SYS(2015)
USE (_FOXCODE) ALIAS (cTAlias) AGAIN SHARED
SELECT (cTAlias)
LOCATE FOR UPPER(Abbrev) = UPPER(lcAbbr)
IF EMPTY(tcCode)
IF EOF() THEN
INSERT INTO (cTAlias) (TYPE, Abbrev, expanded, cmd, CASE, SAVE, TIMESTAMP) ;
VALUES ('U',UPPER(lcAbbr), lcLong,'', 'U', .F., DATETIME())
ELSE
UPDATE (cTAlias) SET TYPE = 'U',;
expanded=lcLong,;
cmd = '',;
CASE = 'U',;
SAVE = .F., ;
TIMESTAMP = DATETIME() ;
WHERE UPPER(Abbrev) = UPPER(lcAbbr)
ENDIF
ELSE
IF EOF() THEN
INSERT INTO (cTAlias) (TYPE, Abbrev, expanded, cmd, DATA, CASE, SAVE, TIMESTAMP) ;
VALUES (tcType,UPPER(lcAbbr), lcLong,'{}',tcCode, 'M', tcType#"S", DATETIME())
ELSE
UPDATE (cTAlias) SET TYPE = tcType,;
expanded=lcLong,;
cmd = '{}',;
DATA = tcCode, ;
CASE = 'M',;
SAVE = tcType#"S", ;
TIMESTAMP = DATETIME() ;
WHERE UPPER(Abbrev) = UPPER(lcAbbr)
ENDIF
ENDIF
USE IN (SELECT(cTAlias))
ENDPROC
*!* End Installer
PROCEDURE Locals
LOCAL lcCode
TEXT TO lcCode noshow
*!* Troy Murphy troy@solutionsoft.cc
*!* Summary:
*!* Designed for those that use the Hungarian Notation convention in variable naming.
*!* Creates the 'LOCAL' declaration by scanning a codeblock.
*!* Considers single character variables and variables that use 'l' in hungarian notation as local variables.
*!* Also honors other scoping declarations (local private public).
*!* Constrains itself to current code block (special thanks to Greg Reichert).
*!* It will create the type (as) syntax which will is especially useful on object types since that will give you the intellisense to your own classes.
*!* Runs in VFP8 and above.
*!*
*!* To Use:
*!* Write the code as normal using hungarian notation for variables (lcMyVar, loMyObj).
*!* The first two characters are key.
*!* When you want the local declaration, place the mouse pointer at the line you wish the declaration to go
*!* and type 'locals' or 'locals6' (no quotes) followed by a space to insert the LOCAL declaration.
*!* Please feel free to improve or change behavior to suit your likng.
*!* Of course you should type locals before the variables are initially initialized.
*!* This is a simple script, but I find it very productive.
lparameter oFoxCode
* Create the 'LOCAL' declaration in a code window.
* Requires hungarian notation for variable types. Only supports local types (l).
* Be careful on code that contains multiple procedure files....
* Troy Murphy - 6/21/05 modified to make object types match definition for intellisense.
* Troy Murphy - 6/23/05
* will now treat single character variables as locals.
* Support for 'store .. to ..'
* Support for 'for' and 'for each'
* Support for arrays (dimension statements of la.. arrays are declared [1])
* Troy Murphy - 6/24/05
* Will now support 'into array' and 'scatter name'
* Defaults to sorted (ascending)
* Will now ignore variables already declared in other 'local' directives.
* Greg Reichert - 8/30/2006
* Now supports to exclude variable currently declared as Private, Public, Dimension, and Parameter statements.
* Only see variables in current Procedure block.
* IF LOCALS6 is typed, the Local statement is VFP 6.0 compatible (No AS statement prefixed).
* Greg Reichert - 8/31/2006
* Fixed LOCAL ARRAY declaration
* Fixed when in non-procedure block. search ends at first Procedure or Define class block is encountered.
* Troy Murphy - 8/31/2006
* Support for inline array functions (finds the array parameter and localizes that if necessary).
* Support for 'DO FORM' - will honor 'linked' and 'to' keywords.
* De-Commisioned the 'LOCAL ARRAY Declaration' since arrays appear as: "local loMyArray[1]" which will also initialize the array.
* Removed the ignoring of lines with 'DIMENSION' statements to support the local array convention.
* Rhodri Evans - 1/23/2009
* Support for statements that are split across multiple lines.
* Check no duplicates in output.
* Support for TEXT TO ...
* Support for 'DO FORM' WITH clause
* Additional Array functions
* SYS(2030,1) && Uncomment this line to allow debugging.
local i, lcCurrentLocals as string, lcExpression as string, lcInLineCommentString as string, lcObjClassLib as string, lcObjType as string, lcParse as string, lcResult as string, lcSourceLine as string, lcSuffix as string, lcText as string, lcTmp as string, lcVar as string, lcVartype as string, llSorted as Boolean, lnCnt as number, lnHandle as number, lnLoop as number, lnResult as number, lnResultDim as number, lnSelEnd as number, lnSelStart as number, lnWords as number, loObjTypes as 'collection'
local laText[1], laResult[1], laParameters[1], laEnv[25], llLoop as Boolean, lnDup as Number, lnLoopStart as Number
llSorted=.F. && Do you want the locals list sorted?
lcResult="LOCAL "
set library to (home()+"FoxTools.fll") additive
lnHandle=_wontop()
if vartype(lnHandle)='N'
lcInLineCommentString=replicate(chr(28),2)
lnResult=_EdGetEnv(lnHandle,@laEnv)
lnSelStart=0
lnSelEnd=laEnv[2]
lcText=_EdGetStr(lnHandle,lnSelStart,lnSelEnd-1)
lcResult="LOCAL "
lnResultDim=0
lnCnt=alines(laText,lcText)
lcCurrentLocals=''
loObjTypes=createobject('collection')
*2.00.00.00913-4-----------------------------------
* Locate current position, scan to beginning of procedure
*--------------------------------------------------
LOCAL llAsVersion6
llAsVersion6 = .F.
for lnLoop=1 to alen(laText,1)
* Add SourceLine to previous if continuation line
lcSourceLine=IIF(llLoop,lcSourceLine,'')+ALLTRIM(chrtran(laText[lnLoop],chr(9)+chr(10)+chr(13),""))
IF RIGHT(lcSourceLine,1)=';'
* statement split across multiple lines
lcSourceLine = STUFF(lcSourceLine,LEN(lcSourceLine),1,' ') && remove continuation mark
lnLoopStart = lnLoop
llLoop = .T.
LOOP
ELSE
* Statement finishes on this line
IF !llLoop
lnLoopStart = lnLoop
ENDIF
llLoop = .F.
ENDIF
IF LEFT(ALLTRIM(UPPER(lcSourceLine)),6)=="LOCALS"
llAsVersion6 = (ALLTRIM(UPPER(lcSourceLine))=="LOCALS6") && make compatible with VFP 6.0
*--------------------------------------------------
* find the beginning of the block
*--------------------------------------------------
FOR lnLoop=lnLoop TO 1 STEP -1
* Add SourceLine to previous if continuation line
lcSourceLine=IIF(llLoop,lcSourceLine,'')+ALLTRIM(chrtran(laText[lnLoop],chr(9)+chr(10)+chr(13),""))
IF RIGHT(lcSourceLine,1)=';'
* statement split across multiple lines
lcSourceLine = STUFF(lcSourceLine,LEN(lcSourceLine),1,' ') && remove continuation mark
lnLoopStart = lnLoop
llLoop = .T.
LOOP
ELSE
* Statement finishes on this line
IF !llLoop
lnLoopStart = lnLoop
ENDIF
llLoop = .F.
ENDIF
lcSourceLine = IIF(LOWER(LEFT(lcSourceLine,7))=="hidden ",ALLTRIM(SUBSTR(lcSourceLine,8)), lcSourceLine)
lcSourceLine = IIF(LOWER(LEFT(lcSourceLine,10))=="protected ",ALLTRIM(SUBSTR(lcSourceLine,11)), lcSourceLine)
DO CASE
CASE LOWER(LEFT(lcSourceLine,10))=="procedure "
EXIT
CASE LOWER(LEFT(lcSourceLine,9))=="function "
EXIT
ENDCASE
NEXT
EXIT
ENDIF
NEXT
*--------------------------------------------------
* remember the start end end positions
*--------------------------------------------------
LOCAL lnStartLoop, lnEndLoop
lnStartLoop = MAX(1,lnLoopStart)
lnEndLoop = alen(laText,1)
* Find the existing local declarations
for lnLoop=lnStartLoop to alen(laText,1)
* Add SourceLine to previous if continuation line
lcSourceLine=IIF(llLoop,lcSourceLine,'')+ALLTRIM(chrtran(laText[lnLoop],chr(9)+chr(10)+chr(13),""))
IF RIGHT(lcSourceLine,1)=';'
* statement split across multiple lines
lcSourceLine = STUFF(lcSourceLine,LEN(lcSourceLine),1,' ') && remove continuation mark
llLoop = .T.
LOOP
ELSE
* Statement finishes on this line
llLoop = .F.
ENDIF
lcSourceLine = IIF(LOWER(LEFT(lcSourceLine,7))=="hidden ",ALLTRIM(SUBSTR(lcSourceLine,8)), lcSourceLine)
lcSourceLine = IIF(LOWER(LEFT(lcSourceLine,10))=="protected ",ALLTRIM(SUBSTR(lcSourceLine,11)), lcSourceLine)
*--------------------------------------------------
* GLR 8-29-2006 : add Private, Public, and Dimension to the list of possible declaration statements
*--------------------------------------------------
*-- GLR 8/31/2006 : added 'Define' to list
*-- THM 8/31/2006 : removed 'dimens' from list.
if INLIST(left(lower(lcSourceLine),6),'local ','privat','public', 'parame', 'lparam', ;
'proced', 'functi', 'endpro', 'endfun', 'define')
DO CASE
*--------------------------------------------------
* standard declarations
*--------------------------------------------------
CASE left(lower(lcSourceLine),6)=='local '
lcSourceLine=substr(lcSourceLine,6)
CASE left(lower(lcSourceLine),6)=='public'
lcSourceLine=substr(lcSourceLine,6)
CASE left(lower(lcSourceLine),8)=='private '
lcSourceLine=substr(lcSourceLine,8)
CASE left(lower(lcSourceLine),10)=='dimension '
lcSourceLine=substr(lcSourceLine,10)
CASE left(lower(lcSourceLine),10)=='parameter '
lcSourceLine=substr(lcSourceLine,10)
CASE left(lower(lcSourceLine),11)=='lparameter '
lcSourceLine=substr(lcSourceLine,11)
*--------------------------------------------------
* if the start is th top of the page, then look for start of procedure or class
*--------------------------------------------------
*-- GLR 8/31/2006 : Will stop search when new block in encountered.
CASE left(lower(lcSourceLine),10)=='procedure ' and lnStartLoop==1
lnEndLoop = lnLoop
EXIT
CASE left(lower(lcSourceLine), 9)=='function ' and lnStartLoop==1
lnEndLoop = lnLoop
EXIT
CASE left(lower(lcSourceLine),13)=='define class ' and lnStartLoop==1
lnEndLoop = lnLoop
EXIT
*--------------------------------------------------
* if start procedure, get arguments
*--------------------------------------------------
CASE left(lower(lcSourceLine),10)=='procedure '
IF "("$lcSourceLine
lcSourceLine=STRTRAN(substr(lcSourceLine, AT("(",lcSourceLine)+1),")","")
ELSE
LOOP
ENDIF
CASE left(lower(lcSourceLine),9)=='function '
IF "("$lcSourceLine
lcSourceLine=STRTRAN(substr(lcSourceLine, AT("(",lcSourceLine)+1),")","")
ELSE
LOOP
ENDIF
*--------------------------------------------------
* if End of block, remember and exit loop
*--------------------------------------------------
CASE left(lower(lcSourceLine),7)=='endproc'
*-- end of procedure
lnEndLoop = lnLoop
EXIT
CASE left(lower(lcSourceLine),7)=='endfunc'
*-- end of function
lnEndLoop = lnLoop
EXIT
ENDCASE
*--------------------------------------------------
* Parse declarations
*--------------------------------------------------
for i = 1 to getwordcount(lcSourceLine,',')
lcTmp=alltrim(getwordnum(lcSourceLine,i,','))
if ' as '$lower(lcTmp)
lcTmp=alltrim(left(lcTmp,at(' ',lcTmp)))
endif
if '['$lcTmp
lcTmp=alltrim(left(lcTmp,at('[',lcTmp)-1))
endif
if '('$lcTmp
lcTmp=alltrim(left(lcTmp,at('(',lcTmp)-1))
endif
if !lower(alltrim(lcTmp)+',')$lower(alltrim(lcCurrentLocals)+',')
lcCurrentLocals = lcCurrentLocals + lcTmp +','
endif
endfor
endif
endfor
*--------------------------------------------------
* using start and end points
*--------------------------------------------------
for lnLoop=lnStartLoop to lnEndLoop
* Add SourceLine to previous if continuation line
lcSourceLine=IIF(llLoop,lcSourceLine,'')+ALLTRIM(chrtran(laText[lnLoop],chr(9)+chr(10)+chr(13),""))
IF RIGHT(lcSourceLine,1)=';'
* statement split across multiple lines
lcSourceLine = STUFF(lcSourceLine,LEN(lcSourceLine),1,' ') && remove continuation mark
llLoop = .T.
LOOP
ELSE
* Statement finishes on this line
llLoop = .F.
ENDIF
lcParse=''
do case
case left(lower(lcSourceLine),6)='store ' and ' to '$lower(lcSourceLine)
lcParse=substr(lcSourceLine,rat([ to ],lower(lcSourceLine))+4)
case left(lower(lcSourceLine),10)='dimension '
lcParse=strtran(lcSourceLine,'dimension ','',1,1,3)
if [(]$lcParse
lcParse=left(lcParse,at('(',lcParse)-1)+'[1]'
else
if "["$lcParse
lcParse=left(lcParse,at('[',lcParse)-1)+'[1]'
endif
endif
case 'select '$lower(lcSourceLine) and ' into array '$lower(lcSourceLine)
lcParse=substr(lcSourceLine,rat(' into array ',lower(lcSourceLine))+12)
if lcInLineCommentString $ lcParse
lcParse=left(lcParse,at(lcInLineCommentString,lcParse))
endif
lcParse=lcParse+'[1]'
case lower(left(lcSourceLine,8))='scatter' and ' name '$lower(lcSourceLine)
lcParse=strextract(lcSourceLine,' name ',' ',1,1+2)
case lower(left(lcSourceLine,9))='for each '
lcParse=strextract(lcSourceLine,'for each ',' in ',1,3)
case lower(left(lcSourceLine,4))='for '
lcParse=strextract(lcSourceLine,'for ','=',1,3)
CASE LEFT(LOWER(lcSourceLine),8)='text to '
lcParse=GETWORDNUM(lcSourceLine,3)
case [=]$lcSourceLine
lcParse=getwordnum(lcSourceLine,1,"=")
endcase
if !empty(lcParse)
if lcInLineCommentString$lcParse
lcParse=left(lcParse,at(lcInLineCommentString,lcParse))
endif
lnWords=getwordcount(lcParse)
if lnWords=1 and !inlist(left(lcParse,1),"'",'"','*')
lcExpression=alltrim(substr(lcSourceLine,at("=",lcSourceLine)+1))
lcVar=getwordnum(lcParse,1)
if ascan(laResult,lcVar,-1,-1,-1,7)=0 and atc(".",lcVar)=0 and (atc("[",lcVar)=0 or left(lower(lcVar),2)='la') and (upper(left(lcVar,1))="L" or len(alltrim(lcVar))=1)
lcTmp=lcVar && Search for array declarations
if '['$lcTmp
lcTmp=alltrim(left(lcTmp,at('[',lcTmp)-1))
endif
if '('$lcTmp
lcTmp=alltrim(left(lcTmp,at('(',lcTmp)-1))
ENDIF
if !lower(alltrim(lcTmp)+',')$lower(alltrim(lcCurrentLocals)+',')
IF VARTYPE(laResult[ALEN(laResult,1)])='C'
DIMENSION laResult[ALEN(laResult,1)+1]
ENDIF
laResult[ALEN(laResult,1)]=lcVar
LOCAL llCreateObject
if inlist(lower(left(lcExpression,9)),'newobject','createobj')
llCreateObject = (lower(left(lcExpression,9))=='createobj')
lcExpression=alltrim(strextract(lcExpression,[(]))
if right(lcExpression,1)=[)]
lcExpression=left(lcExpression,len(lcExpression)-1)
endif
lcObjType=getwordnum(lcExpression,1,[,])
lcObjClassLib=getwordnum(lcExpression,2,[,])
if empty(lcObjClassLib) OR llCreateObject
loObjTypes.add(lcObjType,lcVar)
else
loObjTypes.add(lcObjType+[ OF ]+lcObjClassLib,lcVar)
endif
endif
endif
endif
endif
ENDIF
*-- THM 08/31/2006 - Support for inline array functions.
*Support for array functions - lines may contain more than one of these....
*-- RCE 01/23/2009 - respect Current Locals
LOCAL lcArrayParse, lcArrayLine, llContinue, lcArrayFunctions, lcLine, i
lcArrayFunctions='aclass,acopy,adatabases,adbobjects,adir,adel,adlls,adockstate,aelement,aerror,aevents,afields,afont,agetclass,agetfileversion,ains,ainstance,alanguage,alen,alines,amembers,amouseobj,anetresources,aprinters,aprocinfo,ascan,aselobj,asessions,asort,'+'asqlhandles,astackinfo,asubscript,ataginfo,aused,avcxclasses'
lcArrayParse=''
lcArrayLine=CHRTRAN(lcSourceLine,' ','')
if lcInLineCommentString$lcArrayLine
lcArrayLine=left(lcArrayLine,at(lcInLineCommentString,lcArrayLine))
ENDIF
FOR i = 1 TO GETWORDCOUNT(lcArrayFunctions,',')
lcArrayFunc=GETWORDNUM(lcArrayFunctions,i,',')
IF lcArrayFunc+'('$LOWER(lcArrayLine)
lcLine=SUBSTR(lcArrayLine,AT(lcArrayFunc+'(',LOWER(lcArrayLine)))
lcArrayName=STREXTRACT(lcLine,'(',IIF(AT(',',lcLine)=0 or AT(',',lcLine)>AT(')',lcLine),')',','))
IF !EMPTY(lcArrayName) AND !lower(alltrim(lcArrayName)+',')$lower(alltrim(lcCurrentLocals)+',')
IF VARTYPE(laResult[ALEN(laResult,1)])='C'
DIMENSION laResult[ALEN(laResult,1)+1]
ENDIF
laResult[ALEN(laResult,1)]=lcArrayName+'[1]'
ENDIF
ENDIF
ENDFOR
*-- THM 08/31/06 - Support for 'DO FORM'
*-- RCE 01/23/09 - Support for WITH clause; respect Current Locals
if left(lower(lcSourceLine),8)='do form '
lcSourceLine=STRTRAN(lcSourceLine,[ noread],[],-1,-1,1)
lcSourceLine=STRTRAN(lcSourceLine,[ noshow],[],-1,-1,1)
IF ' to '$lower(lcSourceLine)
lcTmp=substr(lcSourceLine,rat([ to ],lower(lcSourceLine))+4)
if !lower(alltrim(lcTmp)+',')$lower(alltrim(lcCurrentLocals)+',')
IF VARTYPE(laResult[ALEN(laResult,1)])='C'
DIMENSION laResult[ALEN(laResult,1)+1]
ENDIF
laResult[ALEN(laResult,1)]=lcTmp
ENDIF
ENDIF
IF ' linked '$LOWER(lcSourceLine)
lcTmp=ALLTRIM(STREXTRACT(LOWER(lcSourceLine),' name ',' linked '))
if !lower(alltrim(lcTmp)+',')$lower(alltrim(lcCurrentLocals)+',')
IF VARTYPE(laResult[ALEN(laResult,1)])='C'
DIMENSION laResult[ALEN(laResult,1)+1]
ENDIF
laResult[ALEN(laResult,1)]=SUBSTR(lcSourceLine,AT(LOWER(lcTmp),LOWER(lcSourceLine)),LEN(lcTmp))+IIF(llAsVersion6,'',[ AS Form])
ENDIF
ENDIF
IF ' with '$LOWER(lcSourceLine)
lcParse=ALLTRIM(STREXTRACT(lcSourceLine,[ with ],[ to ],1,1+2))
FOR i = 1 TO GETWORDCOUNT(lcParse,[,])
lcTmp=ALLTRIM(GETWORDNUM(lcParse,i,[,]))
IF ISALPHA(lcTmp) AND !lower(alltrim(lcTmp)+',')$lower(alltrim(lcCurrentLocals)+',') ;
AND EMPTY(CHRTRAN(LOWER(lcTmp),'abcdefghijklmnopqrstuvwyxz1234567890[]',''))
IF VARTYPE(laResult[ALEN(laResult,1)])='C'
DIMENSION laResult[ALEN(laResult,1)+1]
ENDIF
laResult[ALEN(laResult,1)]=lcTmp
ENDIF
ENDFOR
ENDIF
ENDIF
ENDFOR
if vartype(laResult[1])="C"
if llSorted
=asort(laResult,-1,-1,-1,1)
ENDIF
for lnLoop=1 to alen(laResult,1)
*-- RCE 01/23/09 - No duplicates
IF lnLoop>1
lnDup = ASCAN(laResult,laResult[lnLoop],1,lnLoop-1,1,1+4)
IF lnDup > 0 AND LOWER(GETWORDNUM(laResult[lnLoop],1)) = LOWER(GETWORDNUM(laResult[lnDup],1))
LOOP
ENDIF
ENDIF
IF "."$laResult[lnLoop]
* Properties
LOOP
ENDIF
lcVartype=upper(substr(laResult[lnLoop],2,1))
lcSuffix = ""
do case
CASE llAsVersion6 && no AS clause is added
CASE [ AS ]$UPPER(laResult[lnLoop]) && AS clause alredy present
case lcVartype="N"
lcSuffix = " AS Number"
case lcVartype="I"
lcSuffix = " AS Integer"
case lcVartype="O"
try
if empty(loObjTypes(laResult[lnLoop]))
lcSuffix = " AS Object"
else
lcSuffix = " AS "+loObjTypes(laResult[lnLoop])
endif
catch
lcSuffix = " AS Object"
endtry
case lcVartype="L"
lcSuffix = " AS Boolean"
case lcVartype="C"
lcSuffix = " AS String"
case lcVartype="U"
lcSuffix = " AS Variant"
case lcVartype="D"
lcSuffix = " AS Date"
case lcVartype="T"
lcSuffix = " AS DateTime"
case lcVartype="Y"
lcSuffix = " AS Currency"
otherwise
lcSuffix = ""
ENDCASE
if lnLoop>1
lcResult=lcResult+", "
ENDIF
lcResult=lcResult+laResult[lnLoop]+lcSuffix
endfor
else
lcResult=""
endif
oFoxCode.valuetype="V"
endif
return lcResult
ENDTEXT
RETURN lcCode
ENDPROC
Commenting
Place a Comment noting date and time changed and by whom
Like
Dan Jurden's example, the following script inserts a comment in the format I like to use with the big difference that I fill in the date and time. Also, I often comment a line of code that I'm about to change. If I type the shortcut (CCD, in my case) at the beginning of a line of code, it will be commented. Next thing I'll do is write a command that copies the line, since I'm often modifying the line.
LPARAMETERS oFoxcode
IF oFoxcode.Location = 0
RETURN "CCD"
ENDIF
oFoxcode.valuetype = "V"
LOCAL myVar
TEXT TO myVar TEXTMERGE NOSHOW
*!* < < DATETIME() > > nf 2: ~
*!*
ENDTEXT
RETURN myvar
Note. Do not included the extra spaces around the angle brackets in the DATETIME() call.
--
Nancy Folsom
Place a Comment noting date changed and by whom
I have added two new custom commands to my Intellisense table: COM and CHG.
COM expands to "* DJ
"
CHG expands to "* Changed by DJ on "
This can be accomplished by adding a custom entry on the Custom tab and entering something like this in the script window (foxcode.data):
LPARAMETER oFoxCode
local lcRetVal, lcDate
oFoxcode.valuetype = "V"
lcDate = dtos(date())
lcDate = left(lcDate, 4) + '/' + substr(lcDate,5,2) + '/' + right(lcDate,2)
lcRetVal = "* DJ " + lcDate + " "
return lcRetVal
-- Dan Jurden
Place a TODO comment (for Task list) including Date Placed
Since tasks are associated with a file (PRG) and line number, I find having comments in my code that I can parse to helpful in addition to using the tasks list. So, my "ToDo" script does the following:LPARAMETERS oFoxcode
IF oFoxcode.Location = 0
RETURN "TODO"
ENDIF
oFoxcode.valuetype = "V"
LOCAL myVar
KEYBOARD "{ALT+F2}" && <- i think you want it here
TEXT TO myVar TEXTMERGE NOSHOW
KEYBOARD "{ALT+F2}"
*!* < < DATE() > > nf TODO: ~
ENDTEXT
RETURN myvar -- Nancy Folsom
Code Generation
Generate Error Reporting Code
I use this entry to facilitate genereating error messages:
Command: ERR
Script:
LPARAMETER oFoxCode
LOCAL lsAns as String
oFoxCode.ValueType = 'V'
lsAns = INPUTBOX("Enter Error Message")
IF EMPTY(lsAns)
RETURN ""
ELSE
lsAns = 'MESSAGEBOX("ERROR: ' + lsAns + '", 16, "Error")' + CHR(13) + "~"
RETURN lsAns
ENDIF
Check the parameters passed to a function
And this one to check parameters to a function
Command: pchk
Script:
LPARAMETER oFoxCode
oFoxCode.ValueType = 'V'
lcAns = INPUTBOX("Parameter To Check", "Parameter Check")
IF EMPTY(lcAns)
RETURN .F.
ENDIF
lcType = INPUTBOX("Proper Type", "Parameter Check")
IF EMPTY(lcType)
RETURN .F.
ENDIF
lcRet = "IF VARTYPE(" + lcAns + ") != '" + lcType + "'"
IF lcType == 'C'
lcRet = lcRet + " OR EMPTY(" + lcAns + ")"
ENDIF
lcRet = lcRet + Chr(13)
lcRet = lcRet + ' MESSAGEBOX(' +;
'"ERROR: Invalid Parameter Type for parameter ' + lcAns + '" + CHR(13) +;' + Chr(13) +;
' " Expected Type: ' + lcType + '" + CHR(13) + ;' + CHR(13) + ;
' " Type Received: " + VarType(' + lcAns + ') + CHR(13) ;' + CHR(13) +;
' , 16, "Error")'
lcRet = lcRet + Chr(13)
lcRet = lcRet + " RETURN .F."
lcRet = lcRet + Chr(13)
lcRet = lcRet + "ENDIF"
lcRet = lcRet + Chr(13)
RETURN lcRet
-- Louis Zelus
Create Excel Automation template
Here's one to create an Excel Automation template to get your code started
Fill in the following table fields:
Type = "U"
abbrev = "excel"
command = {}
In Data Field:
***********************************
LPARAMETERS oFoxcode
* 0 – Command Window
* 1 – Program
* 8 – Menu Snippet
* 10 – Code Snippet
* 12 – Stored Procedure
oFoxcode.valuetype = "V"
IF oFoxcode.Location = 0
* if in command window
RETURN [loExcel = CREATEOBJECT("Excel.Application")]
ENDIF
IF oFoxcode.Location # 1 and oFoxcode.Location # 10
* if not in a PRG or a Method
RETURN "Excel"
ENDIF
#define CRLF CHR(13)+CHR(10)
LOCAL lcRetVal
lcRetVal = ;
[LOCAL loExcel, loWorkBook, loRange] + CRLF + ;
[loExcel = CREATEOBJECT("Excel.Application")] + CRLF + ;
[loExcel.SheetsInNewWorkbook = 1] + CRLF + ;
[loExcel.DisplayAlerts = .F.] + CRLF + ;
[loWorkBook = loExcel.Workbooks.Add()] + CRLF + ;
[loExcel.Visible = .t.] + CRLF + ;
[*loRange = loExcel.Range("A1:A5")] + CRLF + ;
[*] + CRLF + ;
[*loWorkBook.SaveAs(cFilename)] + CRLF + ;
[*loExcel.Quit]
RETURN lcRetVal
-- Alex Feldstein
Produce a skeleton HTML TABLE
or you could run a script to create an HTML TABLE (if you do web code) that has a dialog asking you how many rows and columns, and whatever other properties you can dream of that creates something like:
* (brackets include spaces to avoid wiki parsing)
Response.Write([< TABLE WIDTH="100%" align="LEFT" >] + CRLF)
Response.Write([< TR >] + CRLF)
Response.Write([< TD >] + CRLF)
Response.Write([< /TD >] + CRLF)
Response.Write([< TD >] + CRLF)
Response.Write([< /TD >] + CRLF)
Response.Write([< /TR >] + CRLF)
Response.Write([< /TABLE >] + CRLF)
and other cool time-savers.
-- Alex Feldstein
Intellisense Metadata Batch Updaters
Program to Add All VCX classes to Intellisense
Does any one else find it annoying that you can only add classes one at a time via the Intellisense manager? (No? Oh well, just me then.)
This code will add all the classes in all the class libraries in the current project. -- Rhodri CEvans
NB This isn't a custom script, it's a stand alone program! (Hey, I didn't put it on this page somebody moved it here.)
I refactored this page from a jumble of issues in the various Intellisense topics. So, if it doesn't really belong under intellisense, and I can see the point, what would be a better way to organize it? Feel free. *g* -- Nancy Folsom
* add the Microsoft [[Visual FoxPro]] 7.0 Type Library (manually, why isn't it in there anyway?)
Local o As VisualFoxpro.IFoxPrjFile
Use (_Foxcode) Alias Foxcode Shared In 0
* loop thru project's files
For Each o In _vfp.Projects(1).Files
If Lower(Justext(o.Name))='vcx'
* class library
Use (Alltrim(o.Name)) Alias _vcx In 0
* get classes
Select 'T' As Type, Padr(objname+[ OF "]+Alltrim(o.Name)+["],100) As Data, ;
.T. As Save, Datetime() As Timestamp ;
FROM _vcx ;
INTO Cursor Query ;
WHERE Empty(Parent) And !Empty(Class) And !Deleted()
Use In _vcx
Scan
Select Foxcode
* check we haven't already got it
Locate For Data = Query.Data
If !Found()
Insert Into Foxcode (Type, Data, Save, Timestamp) ;
VALUES (Query.Type, Query.Data, Query.Save, Query.Timestamp)
Endif
Select Query
Endscan
Endif
Endfor
Use In Foxcode
Create a call to object Factory function
If you use a data-driven Factory() function to create your objects, you can add that function to the IntelliSense Manager and a script that lists the available classes. The script might look something like:
LPARAMETER oFoxCode
oFoxCode.Valuetype = "L"
Select FacName, FacDesc from Factory where ISense = .t. into array oFoxCode.Items
Use in Factory
Return AllTrim(oFoxcode.Expanded)+'("~")'
When you type Factory(, you'll be presented with a list of class names. Once selected that name will automatically be surrounded with quotes. You could do something similar with various Strategy types as well. -- Joel Leach
In VS.Net, a 'TODO comment automatically shows up in the task list. If you want to do something similar in VFP, add a "TODO" command, replace with "*TODO:" (or whatever you want), and use the following simple script:
LPARAMETER oFoxCode
oFoxCode.ValueType="V"
KEYBOARD "{ALT+F2}"
Return AllTrim(oFoxCode.Expanded)
Of course, you could always just press Alt + F2. :o) -- Joel Leach
Extract all PROC/FUNC/PARAM statements into Intellisense
This is another stand alone program. This will read a specified prg file and extract the procedure and parameter information to the IntelliSense foxcode table. NB It doesn't work on prg's without a procedure / function statment.
LPARAMETERS tcPrg
LOCAL laProcInfo, lcPrgStr, laLines, lnCount, lcLine, lcParams, llContinuation
DIMENSION laProcInfo(1), laLines(1)
IF VARTYPE(tcPrg)#'C' OR !FILE(tcPrg)
RETURN
ENDIF
USE (_FOXCODE) SHARED ALIAS foxcode
APROCINFO(laProcInfo,tcPrg)
lcPrgStr = STRTRAN(FILETOSTR(tcPrg),CHR(9))
ALINES(laLines,lcPrgStr)
lnCount = ALEN(laProcInfo,1)
FOR i = 1 TO lnCount
IF laProcInfo(i,3)='Procedure' AND !'.'$laProcInfo(i,1)
lcParams = ''
llContinuation = .F.
* Stand alone procedure, not part of a class
FOR j = laProcInfo[i,2]+1 TO IIF(i!=lnCount,laProcInfo[i+1,2]-1,ALEN(laLines,1))
lcLine = ALLTRIM(laLines(j))
* remove inline comments
IF '&'+'&'$lcLine
lcLine = RTRIM(LEFT(lcLine,AT('&'+'&',lcLine)-1))
ENDIF
DO CASE
CASE LEFT(lcLine,1)='*' OR EMPTY(lcLine)
* comment line
LOOP
CASE 'param'$LOWER(lcLine)
* line contains 'param'
lcParams = SUBSTR(lcLine,AT(' ',lcLine)+1) && remove parameter keyword
CASE llContinuation
* continuation
lcParams = lcParams + lcLine
OTHERWISE
* other code reached - parameters are always before other code, so exit loop
EXIT
ENDCASE
IF RIGHT(lcLine,1)#';'
* no continuation mark - exit loop
EXIT
ELSE
* strip out continuation mark
lcParams = SUBSTR(lcParams,1,LEN(lcParams)-1)
* set continuation flag
llContinuation = .T.
ENDIF
ENDFOR
LOCATE FOR ALLTRIM(expanded) == ALLTRIM(laProcInfo(i,1)) AND type = 'F'
IF FOUND()
REPLACE expanded WITH laProcInfo(i,1), tip WITH lcParams, timestamp WITH DATETIME()
ELSE
INSERT INTO foxcode (type,expanded,tip,case,timestamp) VALUES ('F',laProcInfo(i,1),lcParams,'M',DATETIME())
ENDIF
ENDIF
ENDFOR
USE IN foxcode
-- Rhodri CEvans
Extract all PROC/FUNC/PARAM statements into Intellisense including Inline Parameters
With gratitude to Mr. Evans for his elegant and well written solution above, I have enhanced it to handle in-line parameters like
FUNCTION FuncName(tcParam1, tnParam2, tlParam3)
LPARAMETERS tcPrg
LOCAL laProcInfo, lcPrgStr, laLines, lnCount, lcLine, lcParams, llContinuation
DIMENSION laProcInfo(1), laLines(1)
IF VARTYPE(tcPrg)#'C' OR !FILE(tcPrg)
RETURN
ENDIF
USE (_FOXCODE) SHARED ALIAS FOXCODE
APROCINFO(laProcInfo,tcPrg)
lcPrgStr = STRTRAN(FILETOSTR(tcPrg),CHR(9))
ALINES(laLines,lcPrgStr)
lnCount = ALEN(laProcInfo,1)
FOR i = 1 TO lnCount
IF laProcInfo(i,3)='Procedure' AND !'.'$laProcInfo(i,1)
lcParams = ''
llContinuation = .F.
* Stand alone procedure, not part of a class
lcLine = ALLTRIM(laLines[laProcinfo[i,2]])
lcProcName = ALLTRIM(laProcInfo[i,1])
IF '(' $ lcLine && In line parameters.
lcParams = SUBSTR(lcLine,AT('(',lcLine) + 1) && Get all text after the open parens.
IF RIGHT(lcParams,1) = ')' && Strip off the close parens, if present.
lcParams = LEFT(lcParams,LEN(lcParams) - 1)
ENDIF
IF RIGHT(lcParams,1) $ ';' && Oops, we have a continuation line
* strip out continuation mark
lcParams = SUBSTR(lcParams,1,LEN(lcParams) - 1)
lcLine = ALLTRIM(laLines[laProcInfo[i,2] + 1]) && Get the continuation line.
lcParams = lcParams + lcLine
IF ')' $ lcParams && Strip of close parens, if present.
lcParams = LEFT(lcParams,LEN(lcParams) - 1)
ENDIF
* Now, if you have additional continuation lines of parameters you'll have to modify this code here. And you may want to
* rethink your career choice.
ENDIF
ELSE
FOR j = laProcInfo[i,2] + 1 TO IIF(i!=lnCount,laProcInfo[i + 1,2]-1,ALEN(laLines,1))
lcLine = ALLTRIM(laLines(j))
* remove inline comments
IF '&'+'&'$lcLine
lcLine = RTRIM(LEFT(lcLine,AT('&'+'&',lcLine)-1))
ENDIF
DO CASE
CASE LEFT(lcLine,1)='*' OR EMPTY(lcLine)
* comment line
LOOP
CASE 'param'$LOWER(lcLine)
* line contains 'param'
lcParams = SUBSTR(lcLine,AT(' ',lcLine)+1) && remove parameter keyword
CASE llContinuation
* continuation
lcParams = lcParams + lcLine
OTHERWISE
* other code reached - parameters are always before other code, so exit loop
EXIT
ENDCASE
IF RIGHT(lcLine,1)#';'
* no continuation mark - exit loop
EXIT
ELSE
* strip out continuation mark
lcParams = SUBSTR(lcParams,1,LEN(lcParams)-1)
* set continuation flag
llContinuation = .T.
ENDIF
ENDFOR
ENDIF
LOCATE FOR ALLTRIM(expanded) == ALLTRIM(laProcInfo(i,1)) AND TYPE = 'F'
IF FOUND()
REPLACE expanded WITH lcProcName, tip WITH lcParams, TIMESTAMP WITH DATETIME()
ELSE
INSERT INTO FOXCODE (TYPE,expanded,tip,CASE,TIMESTAMP) VALUES ('F',lcProcName,lcParams,'M',DATETIME())
ENDIF
ENDIF
ENDFOR
USE IN FOXCODE
-- Ray Kirk
Show #DEFINEs in drop-down list
Here's one you might find useful. Like a good little programmer, I use defined constants in my programs. But, there are so many, I constantly (pun intended) have to look them up in the header file. The prg and script below will put the contents of a header file in a drop-down list.
First of all, save the code below to Deflist.prg somewhere in your path. This program parses the header file into an IntelliSense compatible array.
* Converts list of defined constants into an array
Lparameters lcHeaderFile, laConstantArray
Local lnFileHandle, lcLine, lnArraySize, lcConstant, lcValue, lnValueStart, lcComment
lnArraySize = 1
Dimension laConstantArray[lnArraySize,2]
laConstantArray = ""
* Open header file
lnFileHandle = Fopen(FullPath(lcHeaderFile))
If lnFileHandle < 0
MessageBox("Cannot open header file "+FullPath(lcHeaderFile),16,"Error")
Return laConstantArray
EndIf
Fseek(lnFileHandle,0,0) && go to top of file
DO while not Feof(lnFileHandle)
lcLine = Alltrim(Fgets(lnFileHandle,8192))
* Add #DEFINEs to array
If Upper(lcLine) = "#DEFINE"
Dimension laConstantArray[lnArraySize,2]
lcConstant = Alltrim(Strtran(lcLine, "#DEFINE", "",1,1,1)) && remove #DEFINE
lcConstant = Alltrim(Strtran(lcConstant,Chr(9)," ")) && convert TABs to SPACEs
lnValueStart = At(" ",lcConstant)
lcValue = Alltrim(Substr(lcConstant,lnValueStart))
lcConstant = Alltrim(Left(lcConstant,lnValueStart))
laConstantArray[lnArraySize,1] = lcConstant
laConstantArray[lnArraySize,2] = lcValue
lnArraySize = lnArraySize + 1
EndIf
* Add comments to array. Customize to your own preference.
* If you don't want all comments, start comment with a custom string (ie. *DEFLIST) and change code below
If Upper(lcLine) = "*"
Dimension laConstantArray[lnArraySize,2]
lcComment = Alltrim(Strtran(lcLine, "*", "",1,1,1)) && remove asterisks
lcComment = "--- " + lcComment + " ---"
laConstantArray[lnArraySize,1] = lcComment
laConstantArray[lnArraySize,2] = ""
lnArraySize = lnArraySize + 1
EndIf
EndDo
Fclose(lnFileHandle)
Return @laConstantArray
Next, add the following code to a script in the IntelliSense Manager. Add the entry as a Function, because a Command will not fire in the middle of a statement.
* Set up as Function in IntelliSense. Command will not work in the middle of a statement.
LPARAMETER oFoxCode
oFoxCode.Valuetype = "L" && drop-down list
oFoxCode.ItemSort = .f. && do not sort
* Could not pass oFoxCode.Items by reference, so setting up temporary array
Dimension laArray[1,2]
DefList(Home()+"Foxpro.h",@laArray) && populate array with header info
* Resize oFoxCode.Items and copy contents from temporary array
Dimension oFoxCode.Items[ALen(laArray,1),2]
=ACopy(laArray,oFoxCode.Items,1,-1,1)
Return "~" && removes function name
The script above references the standard foxpro header file. You can set up scripts to multiple header files by simply changing the first parameter to Deflist(). For example, I type DL( for my application header and FDL( for Foxpro.h. Enjoy. -- Joel Leach
Show form parameters with DO FORM formname WITH
This code will bring back a form's parameters when you type DO FORM whatever WITH .... as long as the form is not in use anywhere.
In Intellisense Manager, Custom tab create a new script called "frmForm" and put the code below in the script.
Next, on the General tab, click browse and find the entry for "Do Form". Type {frmForm} (including curly brackets) into the Cmd field.
-- Rhodri CEvans
LPARAMETER oFoxcode
IF FILE(_CODESENSE)
LOCAL eRetVal, loFoxCodeLoader
SET PROCEDURE TO (_CODESENSE) ADDITIVE
loFoxCodeLoader = CreateObject("FoxCodeLoader")
eRetVal = loFoxCodeLoader.Start(m.oFoxCode)
loFoxCodeLoader = NULL
IF ATC(_CODESENSE,SET("PROC"))#0
RELEASE PROCEDURE (_CODESENSE)
ENDIF
RETURN m.eRetVal
ENDIF
DEFINE CLASS FoxCodeLoader as FoxCodeScript
PROCEDURE Main()
IF 'WITH'$UPPER(this.oFoxCode.FullLine)
LOCAL lcPath, lcTip
lcPath = GetWordNum(this.cLine,3)
Do CASE
Case Left(lcPath,1)=["]
* double quotes
lcPath = Substr(this.cLine,At(["],this.cLine)+1,At(["],this.cLine,2)-At(["],this.cLine)-1)
Case Left(lcPath,1)=[']
* single quotes
lcPath = Substr(this.cLine,At(['],this.cLine)+1,At(['],this.cLine,2)-At(['],this.cLine)-1)
Case Left(lcPath,1)="["
* square brackets
lcPath = Substr(this.cLine,At("[",this.cLine)+1,At("]",this.cLine)-At("[",this.cLine)-1)
EndCase
IF Empty(JustExt(lcPath))
* add extention
lcPath = lcPath+'.SCX'
EndIf
lcTip = this.GetFormParams(lcPath)+' [TO VarName][NOREAD] [NOSHOW]'
this.DisplayTip(lcTip)
Else
THIS.DisplayTip("DO FORM FormName | ? [NAME VarName [LINKED]][WITH cParameterList][TO VarName][NOREAD] [NOSHOW]")
EndIf
ENDPROC
Function GetFormParams
Lparameters tcFname, tcObjName
Local laLines(1),lnLine, lcRetVal, i, llCont
* hide errors while we try to use file
llError = THIS.lHideScriptErrors
THIS.lHideScriptErrors = .T.
Select 0
Use (tcFname) again shared
THIS.lHideScriptErrors = llError
IF !Empty(Alias())
* file used successfully
If Upper(JustExt(tcFname))='SCX'
locate for baseclass = 'form' and empty(parent) and !Deleted()
Else
Locate for objname = tcObjName and empty(parent) and !Deleted()
EndIf
If Found()
ALines(laLines,methods)
lnLine = ascan(laLines,'PROCEDURE Init')
DO Case
Case lnLine > 0
lcRetVal = ''
FOR i = lnLine+1 to ASCAN(laLines,'ENDPROC',lnLine+1)
* Remove inline comments
laLines(i) = Iif('&'+'&'$laLines(i),strtran(laLines(i),Substr(laLines(i),Rat('&'+'&',laLines(i)))),laLines(i))
Do CASE
Case Empty(laLines(i)) or Left(Alltrim(laLines(i)),1)='*'
* Empty or comment line
LOOP
Case 'param'$Lower(laLines(i)) or llCont
* PARAMETER statement or continuation line
IF 'param'$Lower(laLines(i)) and !llCont
laLines(i) = strtran(lalines(i),GetWordNum(lalines(i),1))
EndIf
lcRetVal = lcRetVal + strtran(Alltrim(laLines(i)),Chr(9))
EndCase
IF Right(Alltrim(laLines(i)),1)#';'
* no continuation mark
Exit
Else
* continuation
lcRetVal = Left(lcRetVal,Len(lcRetVal)-1)
llCont = .T.
EndIf
EndFor
use
Case !Empty(class) and !Empty(classloc)
* no Init code, check parent class
Scatter fields like class* memo memvar
Use
lcPath = JustPath(tcFname)
Do Case
Case '..\'$m.classloc
Do while Left(m.classloc,3)='..\'
m.classloc = Substr(m.classloc,4)
lcPath = Left(lcPath,Rat('\',lcPath)-1)
EndDo
m.classloc = lcPath+'\'+m.classloc
Case !'\'$m.classloc
m.classloc = lcPath+'\'+m.classloc
EndCase
lcRetVal = this.GetFormParams(m.classloc,m.class)
EndCase
EndIf
Else
lcRetVal = ''
EndIf
Return lcRetVal
EndFunc
ENDDEFINE
Expand CT to _ClipText
This sounds like MF->Modify Form, but that is a command and so will only expand if it is the first word.
IntelliSense Manager, Browse, find Abbrev = 'CustomDefaultScripts' (near bottem), add CT to list in Data field, Save.
IntelliSense Manager, Custom, Add, Name="ct" Type="Script", Script:
LPARAMETER oFoxScript
IF !UPPER(oFoxScript.oFoxcode.UserTyped) == UPPER(oFoxScript.cCustomScriptName)
RETURN .F.
ENDIF
if oFoxScript.nwords = 1
oFoxScript.ReplaceWord("_ClipText =")
else
oFoxScript.ReplaceWord( StrTran( oFoxScript.cLastWord, 'ct' ) + "_ClipText" )
endif
RETURN "~"
Save, Replace and give it a shot. "ct ct " should give you "_ClipText = _ClipText " (notice that it figures out if you need the "=" or not.
Hmm, small issue: "_ClipText = Strtran(ct," doesn't expand the 2nd ct. This does work: "_ClipText = Strtran( ct " so life isn't too bad.
Note: this may increase the amount of time a SPACE responds, due to # of scripts it will need to traverse, so get a faster machine.
Thanks to Tracy Pearson for figuring this out for me. - cfk
Drop down list of open tables
This will save you tons of time when working in the command window
Type = U
Cmd={OpenTables}
Type = S
Abbrev = Open Tables
Data =
LPARAMETER oFoxCode
LOCAL X, cReturn, nUsed
* Create array of open tables
nUsed =AUSED(aTables)
IF nUsed = 0
* Return a value
oFoxCode.valueType = 'V'
cReturn = 'USE ~'
ELSE
* Tell IntelliSense that you want a dropdown list to appear
oFoxCode.valueType = 'L'
* Build the list using oFoxCode's built in properties
DIMENSION oFoxcode.Items[m.nUsed,2]
FOR i = 1 TO m.nUsed
oFoxcode.Items[m.i,1] = aTables[i, 1]
oFoxcode.Items[m.i,2] = ""
ENDFOR
* Return the prefix for the results of the list
cReturn = "SELECT"
ENDIF
* Return either USE or SELECT
RETURN cReturn
Correct typos
Some simple ideas to prevent typos
Type = U
Abbrev = retrun
Expanded = RETURN
Case = U
Type = U
Abbrev = ednif
Expanded = ENDIF
Case = U
Use (_Foxcode) In 0 Shared Again Alias 'UdpFoxCode'
Delete From UdpFoxCode Where Type = 'U' And Lower( ABBREV ) == 'retrun'
Insert Into UdpFoxCode (Type, ABBREV, Expanded, Case ) Values ( 'U', 'retrun', 'return', 'U' )
Delete From UdpFoxCode Where Type = 'U' And Lower( ABBREV ) == 'ednif'
Insert Into UdpFoxCode (Type, ABBREV, Expanded, Case ) Values ( 'U', 'ednif', 'endif', 'U' )
Use In Select( 'UdpFoxCode' )
See also: IntelliSense FAQ
Category IntelliSense Category VFP IDE Category Code Samples
Particularly for those using Megafox and the InLineGetLocVars script.
In VFP8 the values to return from a script linked in via CustomDefScripts are opposite.
1) Where in VFP7 you RETURN, you now RETURN .F. in VFP8
2) Where in VFP7 you RETURN .F. you now RETURN in VFP8
THEREFORE all script examples that work in VFP7 need to be changed for VFP8.
If you don't do that, then you'll break other parts of IntelliSense, like the expansion of keywords.
-- Paul Maskens