like all developers, whatever their preferred language or environment, i have my own personal set of tools and utilities that i use to make life a little easier for myself. although not particularly generic, or even clever, i find that these little things really help so i offer some more of them here, as is, for your enjoyment, adoption and modification.

the first is a little routine that i wrote when i was asked to address some issues that were being reported in an application written by someone else. i was given access to the source code and needed to find out where the problems were. so i ran the program from the command window and saw the first issue in a form, but what was the form name? which file was it defined in, and since the problem was actually in a grid, where was the code?

so "tellme.prg" was born. it's function is to grab an object reference to whatever control is under the mouse and display all the relevant information about it in a message box with an option to copy the data to the clipboard (so i can alt+tab over to an open word document and paste it in for later reference!). i just assign the program to convenient hot key and away i go (see figure 1)

to implement it all you need (assuming that the source code is in the path) is a simple

on key label ctrl+t tellme()

and here is the code:

***********************************************************************
* program....: tellme.prg
* author.....: andy kramek
* date.......: 31 august 2002
* notice.....: copyright (c) 2002 tightline computers ltd, all rights reserved
* compiler...: visual foxpro 08.00.0000.1916
* purpose....: details of the control under the mouse pointer
***********************************************************************

local loobj, lcohchy, lcclass, lcbclass, loparent, lcstr, lcsource, lnsave, lcparlib, lcparent
local lcclib, lcfile, lcloc
#define crlf chr(13) + chr(10)
*** get the object reference
loobj    = sys( 1270 )
if vartype( loobj ) # "o"
  return
endif
*** get the associated information from the reference
lcclass  = loobj.class
lcclib   = loobj.classlibrary
*** sys(1271) gets us the file name
lcfile   = sys( 1271, loobj )
lcloc = sys(1272, loobj )
if type( "loobj.parent" ) = "o" and not isnull( loobj.parent )
  loparent = loobj.parent
  lcparent = alltrim( loparent.class ) + "::" + alltrim( loparent.name )
  lcparlib = alltrim( loparent.classlibrary )
else
  lcparent = ""
  lcparlib = ""
endif
lcsource = iif( pemstatus( loobj, 'controlsource', 5 ), alltrim( loobj.controlsource ), "" )
if empty( lcsource )
  lcsource = iif( pemstatus( loobj, 'recordsource', 5 ), alltrim( loobj.recordsource ), "" )
endif
*** build the string
lcstr = ""
lcstr = lcstr + "object: " + alltrim( loobj.name ) + crlf
lcstr = lcstr + "class: " + alltrim( lcclass ) + crlf
lcstr = lcstr + "classlib: " + alltrim( lcclib ) + crlf
lcstr = lcstr + "location: " + alltrim( lcloc ) + crlf
lcstr = lcstr + iif( empty( lcsource ), "", "source: " + alltrim( lcsource ) + crlf)
lcstr = lcstr + iif( empty( lcparent ), "", "parent: " + alltrim( lcparent ) + crlf)
lcstr = lcstr + iif( empty( lcparlib ), "", "classlib: " + alltrim( lcparlib ))
lcstr = lcstr + iif( empty( lcfile ), "", "scx file: " + alltrim( lcfile ))
*** display it
lnsave = messagebox( lcstr, 36, "save details to clipboard?" )
if lnsave = 6
  _cliptext = strtran( lcstr, crlf, "~", -1, -1, 1)
endif

 

another very simple little tool that i use quite is one to find a specific occurrence of a string in a file. now i know we have the excellent code references tool built into the newer versions of vfp, but, apart from the fact that this tool pre-dates those, it is rather different in intent. most of my vfp work has been concerned with non-visual objects (middle tier components and the data access layer) and i use programmatically defined classed extensively. however, it's tough to manage the prg files – though the document view was a huge benefit it is totally interactive and doesn't always do what i wanted. so i wrote findtext allow me to search through a prg and find all occurrences of a specific text string and write them out to file with, optionally, the relevant line number (ready for the goto function).

so why do i need this? well, as those of you who have ever seen my code will know i am a strong believer in commenting the code (just look at tellme.prg above) and a very quick way to document some code is to use findtext because i always prefix my comments with a triple "*". so the following line of code:

findtext( '***', 'findtext.prg', 'findtext.txt', .f., .t. )

creates a file named findtext.txt that contains:

searching for: '***' in file: findtext.prg
==========================================
**********************************************************************
**********************************************************************
*** check parameters - search string must be passed
*** if no file, get one!
*** but check that the file exists (in case)
*** get the type of input file (based on extension)
*** if we have no target file, just send output to standard text file named "findtext.txt"
*** get search string into local variable too
*** create the output file and add a header to it:
*** we have a form or class library
*** open the file as a table
*** get all non-deleted method code into a single string
*** close file and restore work area
*** just grab the entire file
*** get data into an array, one row per line and trim them (third param!)
*** nothing found
*** we have something to search, so go for it
*** check each line for the search string
*** dump it to the output file

and here is the code for this one:

 

**********************************************************************
* program....: findtext
* compiler...: visual foxpro 06.00.8492.00 for windows
* copyright..: andy kramek and marcia akins, tightline computers inc, 2001
* abstract...: locate all occurrences of a specified text string and dump to file
**********************************************************************
lparameters tcfindstring, tcinfile, tcoutfile, tlshowlines, tlsuppressdisp
local array lalines[1]
local lcinfile, lcext, lcoutfile, lcstr, lnselect, lnlines, lncnt
#define _crlf    chr(13)

*** check parameters - search string must be passed
if vartype( tcfindstring ) # "c" or empty( tcfindstring )
    assert .f. message "must pass a character string to findtext()"
    return .f.
endif
*** if no file, get one!
if vartype( tcinfile ) # "c" or empty( tcinfile )
    lcinfile = getfile( 'prg;scx;txt;vcx', "file", "open", 0, "choose file to search" )
    if empty( lcinfile)
        assert .f. message "must specify a file to search for findtext()"
        return .f.
    endif
else
    lcinfile = alltrim( tcinfile )
endif
*** but check that the file exists (in case)
if ! file( lcinfile )
    assert .f. message "must pass an available file to search to findtext()"
    return .f.
endif

*** get the type of input file (based on extension)
lcext = justext( lcinfile )
*** if we have no target file, just send output to standard text file named "findtext.txt"
lcoutfile = iif( vartype( tcoutfile ) # "c" or empty( tcoutfile ),  "findtext.txt", alltrim( tcoutfile ))
*** get search string into local variable too
lcfindstr = alltrim( tcfindstring )

*** create the output file and add a header to it:
lcstr =  "searching for: '" + lcfindstr + "' in file: " + lcinfile
strtofile( lcstr + _crlf , lcoutfile )
strtofile( replicate( "=", len( lcstr) ) + _crlf, lcoutfile, .t. )
strtofile( _crlf, lcoutfile, .t.)

if inlist( lcext, "scx", "vcx")
    *** we have a form or class library
    lnselect = select()
    *** open the file as a table
    use ( lcinfile ) in 0 alias filetosch
    *** get all non-deleted method code into a single string
    select filetosch
    lcstr = ""
    scan for ! deleted()
        lcstr = lcstr + alltrim( methods )
    endscan
    *** close file and restore work area
    use in filetosch
    select (lnselect)
else
    *** just grab the entire file
    lcstr = filetostr( lcinfile )
endif

*** get data into an array, one row per line and trim them (third param!)
lnlines = 0
lnlines = alines( lalines, lcstr, .t.)
if lnlines < 1
    *** nothing found
    return .f.
endif
*** we have something to search, so go for it
for lncnt = 1 to lnlines
    *** check each line for the search string
    if lcfindstr $ lalines[lncnt]
        *** dump it to the output file
        if tlshowlines
          strtofile( "line " + transform(lncnt) + ";  " + lalines[lncnt] + _crlf, lcoutfile, .t.)
        else
          strtofile( lalines[lncnt] + _crlf, lcoutfile, .t.)
        endif
    endif
next

if ! tlsuppressdisp
  modi file (lcoutfile) nowait
endif

finally, today, another 'quick and dirty' little dump program. this time for listing out the contents of a vfp database container, either just the table and column names, or the names and the actual column definitions. as with most of my little utilities, this dumps the information to a text file in the current working directory.

********************************************************************
*** name.....: getfoxdbc.prg
*** author...: andy kramek
*** date.....: 1/1/2005
*** notice...: copyright (c) 2005 tightline computers, inc
*** compiler.: visual foxpro 08.00.0000.3117 for windows
*** function.: get a listing of all tables in a dbc and write the fields out to a text file
********************************************************************
lparameters tcdbc, tlnostru
local lctable, lncnt, lcoutfile, lcstr, lnfields
close all
*** define some constants here
#define crlf  chr(13) + chr(10)
#define _line crlf + replicate( "=", 60 ) + crlf
set asserts on

*** create the output file
lcoutfile = alltrim( tcdbc ) + ".txt"
lcstr = "table definitions for " + upper(alltrim( tcdbc )) + " database" + _line + crlf
strtofile( lcstr, lcoutfile )

*** get the tables
lcdbc = forceext( tcdbc, 'dbc' )
select objectname as table_name ;
  from (lcdbc) ;
where objecttype = 'table' into cursor curtables

use in (tcdbc)
select curtables
go top
scan
  *** get the table name and open it
  lctable = alltrim( table_name )
  lcstr = crlf + proper( lctable ) + crlf + crlf
  strtofile( lcstr, lcoutfile, 1 )
  use (lctable) in 0
  select (lctable)

  *** get the field data
  lnfields = afields( lafields )
  lcstr = ''
  for lncnt = 1 to lnfields
    *** field definition
    lcstr = lcstr + lower( lafields[lncnt,1] )
    if not tlnostru
      lcstr = lcstr + "   " + lafields[lncnt,2] + " (" ;
      + padl( lafields[lncnt,3], 3 ) ;
      + iif( empty( lafields[lncnt,4] ), '', ',' + alltrim( str( lafields[lncnt,4] ))) + ' )'
    endif
    lcstr = lcstr + crlf
  next
 
  *** write out field list
  strtofile( lcstr, lcoutfile, 1 )

  *** process the list
  use in (lctable)
  select curtables
endscan

 
as with the last set of tools i posted, i hope that these will give you some ideas for how you can make them better, so please feel free to improve the code and do let me know what improvements you make.

 

 

3 Responses to More of my Useful Utilities (at least, I think they are)

  • Greg S. says:

    These are the type of tools I consider “must have’s” for development. Especially if you are working on someone else’s code. Well done!

    Thank you, I trust you will be able to improve on these reather crude ideas — Andy

  • Ahmed Siddiqui says:

    As well as for someone else’s code, TellMe() will be also be useful when I’m called to support apps I wrote ages ago. Thanks Andy!

    That’s what I use it for tooSmile [:)] Glad it’ll be helpful — Andy

  • Koen says:

    Very cool and clear, one of those lifesavers, will definitely part of my goodies.
    Thanks for sharing with us.

    Thasnk Koen, glad you like it, — Andy

Leave a Reply

Your email address will not be published. Required fields are marked *