I use this tool for quite a while now. VariSense it is called. So what it does is simple but increases your productivity a lot.
When starting VFP it does start the prg as a typical "on key label" thing.
I personally use ctrl+SPACE for this.
So, here is a sample.
Any further in the code I type "lc" and then press ctrl+SPACE. VariSense then immediately fills the string up to lcString (common denominator for both variables), pressing CTRL+SPACE again brings up a small popup that has both variables in it. navigating to either one and pressing enter does bring up the right name (even in the case you declared it.)
In the codesnippet I type "some" and press CTRL+SPACE.
varisense fills that up to somevar, typing ctrl+space again brings up a list of DEFINE'd variables from which you can take a pick;
********************************************************************************
* Title: VariSense 1.2
* Author: Derek J. Kalweit(dkalweit@sensiblesoftware.com)
* Description: This program belongs under an "ON KEY LABEL" in your development
* environment. When triggered, it will automatically consult your declared
* variables and determine what it can do to complete it for you if possible.
* This can lead to a huge savings in typing, particularly if you routinely use
* long, clear variables with very unique names. This is the functionality
* available with a CTRL+SPACEBAR key combination in VC++, though VC++ is smart
* enough to do this with member variables and functions as well(which this is
* not).
* Terms of use: Freeware. Feel free to use and modify for your needs. Send me
* any useful/interesting enhancements so that I may include them in the main
* version, if appropriate.
********************************************************************************
* Version History:
* 1.2(Released 2003-2-28):
* o Adds support for "DIMENSION" arrays
* o Adds support for function parameters defined in parenthesis versus LPARAMETERS statement
* 1.1(Released 2002-10-18):
* o Added drop-down menu to pick ambigious variables
* 1.0(Released 2002-10-8):
* o Original release
********************************************************************************
* Special Thanks to:
* Ed leafe(ed@leafe.com):
* Contributed code to add drop-down menu for ambiguous variables
* Bo Durban(wdurban@datascantech.com):
* Contributed EditPos() function to get cursor position for drop-down menu
********************************************************************************
SET ECHO OFF
#
DEFINE VARIABLE_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTYUVWXYZ0123456789_"
SET LIBRARY TO
(SYS(2004) + "FoxTools.fll") && foxtools is always in the foxpro dir, right?
DECLARE INTEGER
Beep IN KERNEL32 AS Beep INTEGER nFrequecy, INTEGER nDuration
LOCAL
hwndCode, laEnv[25]
LOCAL
cVariables
LOCAL
cProgText, iLastLine, aProgText[1], iLine, cLine
LOCAL
liStartParen, liEndParen
LOCAL
iOffset
LOCAL
aVars[1], y
LOCAL
cDeclaredVar
LOCAL
cNewVar
LOCAL
cChoice, nRow, nCol, iMatch, cOnSelect
hwndCode
= _WonTop()
IF
1 == _EdGetEnv(hwndCode, @laEnv) Then
IF
0 == laEnv[12] && AND INLIST(laEnv[25], 0, 1, 8, 10, 12) Then
LOCAL iPos, cVar, aMatches[1], iMatches
iMatches
= 0
iPos = laEnv[17]
cVar = GetVariable(@hwndCode, @iPos)
IF NOT EMPTY(cVar) then
*-- get all code from the beginning to our current cursor position, as we care about nothing more.
cProgText = _EdGetStr(hwndCode, 0, iPos)
iLastLine = ALINES(aProgText, cProgText)
FOR iLine = iLastLine TO 1 STEP -1
cVariables = ""
cLine = WSTRIM(aProgText[iLine])
DO CASE
CASE
"LOCAL " == UPPER(LEFT(cLine, 6)) AND "ARRAY " == SUBSTR( UPPER(cLine),7,6)
cVariables = WSTRIM(SUBSTR(cLine, 13))
CASE "LOCAL " == UPPER(LEFT(cLine, 6))
cVariables = WSTRIM(SUBSTR(cLine, 7))
CASE "PROC" == UPPER(LEFT(cLine, 4))
EXIT
CASE
"FUNCTION " == UPPER(LEFT(cLine, 9))
liStartParen = AT("(", cLine)
liEndParen = AT(")", cLine)
IF liStartParen > 0 AND liEndParen > liStartParen Then
cVariables = WSTRIM(SUBSTR(cLine, liStartParen+1, liEndParen-liStartParen-1))
iLine = 0 && This forces the loop to exit after it does the dirty work...
ELSE
EXIT
ENDIF
CASE
"LPARAMETERS " == UPPER(LEFT(cLine, 12))
cVariables = WSTRIM(SUBSTR(cLine, 13))
CASE "PARAMETERS " == UPPER(LEFT(cLine, 11))
cVariables = WSTRIM(SUBSTR(cLine, 12))
CASE "PRIVATE " == UPPER(LEFT(cLine, 8))
cVariables = WSTRIM(SUBSTR(cLine, 9))
CASE "PUBLIC " == UPPER(LEFT(cLine, 7)) AND UPPER(GETWORDNUM(cLine,2)) <> "ARRAY"
cVariables = WSTRIM(GETWORDNUM(cLine, 2))
CASE "PUBLIC " == UPPER(LEFT(cLine, 7)) AND UPPER(GETWORDNUM(cLine,2)) == "ARRAY"
cVariables = WSTRIM(GETWORDNUM(cLine, 3))
CASE "DIMENSION " == UPPER(LEFT(cLine, 10))
cVariables = WSTRIM(SUBSTR(cLine, 11))
CASE "#DEFINE " == UPPER(LEFT(cLine, 8))
cVariables = ReadDefines(cLine)
CASE "DECLARE " == UPPER(LEFT(cLine, 8))
IF INLIST( UPPER(GETWORDNUM(cLine,2)), "SHORT", "INTEGER", "SINGLE", "LONG", "STRING", "OBJECT")
cVariables = WSTRIM(GETWORDNUM(cLine, 3))
ELSE
cVariables = WSTRIM(GETWORDNUM(cLine, 2))
ENDIF
CASE
"#INCLUDE " == UPPER(LEFT(cLine, 9))
**** Code for ReadInclude taken away here
lcFile2open = GETWORDNUM(cLine,2)
IF FILE( (lcFile2Open) )
ALINES( laINCL, FILETOSTR( lcFile2Open),.T.,CHR(13)+CHR(10))
FOR lnItemsInArray = 1 TO ALEN( laINCL,1)
cVariables = WSTRIM( GETWORDNUM( laINCL[lnItemsInArray], 2))
IF UPPER(cVar) == SUBSTR(UPPER(cVariables), 1, LEN(cVar)) Then
* Add Match to list
iMatches = iMatches + 1
DIMENSION aMatches[iMatches]
aMatches[iMatches] = cVariables
ENDIF
ENDFOR
ENDIF
ENDCASE
* addToArray(@cVariables, @aMatches, @avars, cVar)
* Let's handle multi-line definitions...
iOffset = 0
DO WHILE ";" == RIGHT(cVariables, 1)
iOffset = iOffset + 1
cVariables = LEFT(cVariables, LEN(cVariables)-1) + WSTRIM(aProgText[iLine+iOffset])
ENDDO
FOR
y = 1 TO ASPLIT(@aVars, cVariables, ",")
cDeclaredVar = WSTRIM(aVars
)
IF " " $ cDeclaredVar Then && Don't include anything beyond the space; Strong-typing comes to mind
cDeclaredVar = LEFT(cDeclaredVar, AT(" ", cDeclaredVar)-1)
ENDIF
IF CHR
(9) $ cDeclaredVar Then && Don't include anything beyond the tab
cDeclaredVar = LEFT(cDeclaredVar, AT(CHR(9), cDeclaredVar)-1)
ENDIF
IF
"[" $ cDeclaredVar Then && Don't include anything beyond the array subscript; We could set this up to include the array subscript, as it will be used most places...
cDeclaredVar = LEFT(cDeclaredVar, AT("[", cDeclaredVar)-1)
ENDIF
IF
"(" $ cDeclaredVar Then && Don't include anything beyond the array subscript(some people use these parentheses for arrays!!!)
cDeclaredVar = LEFT(cDeclaredVar, AT("(", cDeclaredVar)-1)
ENDIF
IF UPPER
(cVar) == SUBSTR(UPPER(cDeclaredVar), 1, LEN(cVar)) Then
* Add Match to list
iMatches = iMatches + 1
DIMENSION aMatches[iMatches]
aMatches[iMatches] = cDeclaredVar
ENDIF
NEXT
NEXT
* Now we go to the head of the prg to look at the #defined vars in the file and in the #includes
* cProgText = _EdGetStr(hwndCode, 0, iPos)
* iLastLine = ALINES(aProgText, cProgText)
* Need to solve this problem
* BL * FOR lnI = 1 TO ALEN( aProgText,1)
* BL * lcLine = aProgText[ lnI ]
* BL *
* BL * DO CASE
* BL * CASE "#DEFINE " == UPPER(LEFT(lcLine, 8))
* BL * cVariables = ReadDefines(lcLine)
* BL * CASE "#INCLUDE " == UPPER(LEFT(lcLine, 9))
* BL * ReadInclude( lcLine, cVar, @cVariables )
* BL * CASE ("FUNC" $ UPPER(lcLine) OR "PROC" $ UPPER(lcLine)) AND ;
* BL * LEFT( lcLine, 1) <> "*"
* BL * EXIT
* BL * ENDCASE
* BL * ENDFOR
* BL * addToArray(@cVariables, @aMatches, @avars, cVar)
iMatches = ACleanUp( @amatches )
IF iMatches > 0 AND VARTYPE( aMatches[1]) <> "L" Then && we have at least one match!
cNewVar = GetBestMatch(@aMatches, cVar)
IF UPPER(cVar) == UPPER(cNewVar) THEN
IF
iMatches > 1 Then
cChoice = ""
nRow = 0
nCol = 0
EditPos(@nRow, @nCol, @laEnv)
DEFINE POPUP shortcut shortcut && RELATIVE FROM MROW(),MCOL()
FOR iMatch = 1 TO iMatches
DEFINE BAR iMatch OF shortcut PROMPT aMatches[iMatch]
cOnSelect = [ON SELECTION BAR iMatch OF shortcut cChoice = "] + aMatches[iMatch] + ["]
&cOnSelect
ENDFOR
ACTIVATE POPUP shortcut AT
nRow, nCol
cNewVar
= cChoice
ENDIF
ENDIF
ChangeText(@hwndCode, laEnv[17], cVar, cNewVar)
ELSE
* If there's no match, BEEP!!!
??CHR(7)
ENDIF
ENDIF
ENDIF
ENDIF
RETURN
.T.
FUNCTION
GetBestMatch
LPARAMETERS
taMatches, cVar
LOCAL
cMatch, iMatches, i
cMatch
= ""
iMatches
= ALEN(taMatches)
ASORT
(taMatches)
FOR
i = 1 TO LEN(taMatches[1]) && size of shortest var
LOCAL cChar, cOldChar, j
cOldChar
= ""
FOR j = 1 TO iMatches
cChar
= SUBSTR(taMatches[j], i, 1)
IF NOT EMPTY(cOldChar)
IF UPPER(cChar) != UPPER(cOldChar) Then
RETURN
cMatch
ENDIF
ENDIF
cOldChar = cChar
NEXT
cMatch = cMatch + cChar
NEXT
RETURN
cMatch
FUNCTION
WSTRIM
LPARAMETERS
tcText
LOCAL
lcText
lcText
= ALLTRIM(CHRTRAN(tcText, CHR(13) + CHR(10), ""))
DO WHILE CHR
(9) == LEFT(lcText, 1) OR " " == LEFT(lcText, 1)
lcText = SUBSTR(lcText, 2)
ENDDO
DO WHILE CHR
(9) == RIGHT(lcText, 1) OR " " == RIGHT(lcText, 1)
lcText = LEFT(lcText, LEN(lcText)-1)
ENDDO
RETURN
lcText
FUNCTION
ASPLIT
LPARAMETERS
taArray, tcText, tcSplitChar
LOCAL
iElements, x, iOld, iNext
iElements
= OCCURS(tcSplitChar, tcText)+1
DIMENSION
taArray[iElements]
iOld
= 1
FOR
x = 1 TO iElements
iNext
= AT(tcSplitChar, tcText, x)
IF iNext = 0 THEN
taArray[x] = SUBSTR(tcText, iOld)
ELSE
taArray[x] = SUBSTR(tcText, iOld, iNext-iOld)
ENDIF
iOld = iNext+1
NEXT
RETURN
iElements
FUNCTION
ChangeText
LPARAMETERS
thWnd, tiPos, tcOldVar, tcNewVar
_EdSelect
(thWnd, tiPos-LEN(tcOldVar), tiPos)
_EdDelete
(thWnd)
_EdInsert
(thWnd, tcNewVar, LEN(tcNewVar))
RETURN
.T.
FUNCTION
GetVariable
LPARAMETERS
thWnd, tiPos
LOCAL
cVar, cChar, iCnt
cVar
= ""
iCnt
= tiPos - 1
cChar
= _EdGetChar(thWnd, iCnt)
DO WHILE
cChar $ VARIABLE_CHARS
cVar
= cChar + cVar
iCnt
= iCnt - 1
cChar = _EdGetChar(thWnd, iCnt)
ENDDO
RETURN
cVar
FUNCTION
EditPos (nRow, nCol, taEnv)
LOCAL
cPoint, cLeft, cTop, nLeft, nTop
#
DEFINE EDENV_KIND 25
#
DEFINE EDSNIP 10
nRow
= 0
nCol
= 0
DECLARE Long
GetCaretPos in Win32API String@
DECLARE
memcpy IN msvcrt AS memcpy_s2l Long@, String@, Long
** Get the caret point
cPoint
= REPLICATE(CHR(0), 8)
GetCaretPos
(@cPoint)
** Convert the point to top and left
cLeft
= SUBSTR(cPoint, 1, 4)
cTop
= SUBSTR(cPoint, 5, 4)
nLeft
= 0
nTop
= 0
memcpy_s2l
(@nLeft, @cLeft, 4)
memcpy_s2l
(@nTop, @cTop, 4)
** Add window border dimensions
nTop
= nTop + SYSMETRIC(4)+SYSMETRIC(9)
nLeft
= nLeft + SYSMETRIC(3)
** If this is a snippet screen add more space for the combos
IF INLIST
(taEnv[EDENV_KIND], EDSNIP)
nTop = nTop + 38
ENDIF
** Get edit window corner
nRow
= WLROW(WONTOP())
nCol
= WLCOL(WONTOP())
** Add caret position
** (add 1 to the height for the height of the caret)
*! ToDo: 1 is close, but we need to calculate the caret height
*! based on the current font dimensions
nRow
= nRow + (nTop/FONTMETRIC(1)) + 1
nCol
= nCol + (nLeft/FONTMETRIC(6))
RETURN
.T.
FUNCTION
ACleanUp( taArray )
EXTERNAL ARRAY
taArray
LOCAL
i
FOR
i = ALEN( taArray,1) TO 1 STEP -1
IF i > 1
IF VARTYPE( taArray
) == VARTYPE( taArray[i-1] )
IF taArray
== taArray[i-1]
ADEL( taArray,i)
DIMENSION taArray[ ALEN(taArray,1)-1]
ENDIF
ENDIF
ENDIF
ENDFOR
RETURN ALEN
( taArray,1)
FUNCTION
ReadDefines( tcLine )
RETURN WSTRIM( GETWORDNUM( tcLine, 2) )
ENDFUNC
FUNCTION
ReadInclude( tcLine, tcVar, tcVariables )
LOCAL lcFileToOpen
lcFile2open
= GETWORDNUM(tcLine,2)
IF FILE( (lcFile2open) )
ALINES( laINCL, FILETOSTR( lcFile2open), .T., CHR(13)+CHR(10))
FOR lnItemsInArray = 1 TO ALEN( laINCL,1)
tcVariables = WSTRIM( GETWORDNUM( laINCL[lnItemsInArray], 2))
IF UPPER(tcVar) == SUBSTR(UPPER(tcVariables), 1, LEN(tcVar)) THEN
* Add Match to list
iMatches = ALEN(aMatches,1) + 1
DIMENSION aMatches[iMatches]
aMatches[iMatches] = tcVariables
ENDIF
ENDFOR
ENDIF
ENDFUNC
PROCEDURE
addtoarray( tcVariables, taMatches, taVars, tcVar )
EXTERNAL ARRAY taVars
EXTERNAL ARRAY taMatches
* Let's handle multi-line definitions...
iOffset = 0
DO WHILE ";" == RIGHT(tcVariables, 1)
iOffset = iOffset + 1
tcVariables = LEFT(tcVariables, LEN(tcVariables)-1) + WSTRIM(aProgText[iLine+iOffset])
ENDDO
FOR
y = 1 TO ASPLIT(@taVars, tcVariables, ",")
cDeclaredVar = WSTRIM(taVars
)
IF " " $ cDeclaredVar Then && Don't include anything beyond the space; Strong-typing comes to mind
cDeclaredVar = LEFT(cDeclaredVar, AT(" ", cDeclaredVar)-1)
ENDIF
IF CHR
(9) $ cDeclaredVar Then && Don't include anything beyond the tab
cDeclaredVar = LEFT(cDeclaredVar, AT(CHR(9), cDeclaredVar)-1)
ENDIF
IF
"[" $ cDeclaredVar Then && Don't include anything beyond the array subscript; We could set this up to include the array subscript, as it will be used most places...
cDeclaredVar = LEFT(cDeclaredVar, AT("[", cDeclaredVar)-1)
ENDIF
IF
"(" $ cDeclaredVar Then && Don't include anything beyond the array subscript(some people use these parentheses for arrays!!!)
cDeclaredVar = LEFT(cDeclaredVar, AT("(", cDeclaredVar)-1)
ENDIF
IF UPPER
(tcVar) == SUBSTR(UPPER(cDeclaredVar), 1, LEN(tcVar)) Then
* Add Match to list
iMatches = ALEN(taMatches,1) + 1
DIMENSION taMatches[iMatches]
taMatches[iMatches] = cDeclaredVar
ENDIF
NEXT
ENDPROC
I hope it will be of good use for you.