> Is there a way to have the Help builder pull in the 'header' block of
> comments of the code?
>
> -Charlie
Hi Charlie,
Here's a utility I wrote to do this, below.
Bill
* COMGRAB.PRG
* This program will extract comment lines from the top of all prgs in
* a specified folder, and create a set of corresponding comment (doc)
files
* for each prg in a target folder.
* Comment lines are lines that begin with an asterisk. Interspersed
blank
* lines among comment lines are taken with comment lines.
* Scanning begins with the 1st line in each prg, and ends when a line
* not containing an asterisk (or blank) is found.
* The caller provides the name of the folder containing the prgs and the
* name of the folder to contain the result extraction files.
* Each prg in the input folder will result in a .TXT file in the target
folder.
* If a prg does not contain comment lines at the top (before the 1st
instruction),
* a comment file with only the prg name and today's date/time will be
created.
* Change log:
* 6-26-02 wja initial development
parameters csourcelib,ctargetlib
* to test: do comgrab with 'c:\grab','c:\comments'
* There are 2 parameters: the folder containing the source programs, and
the
* folder to contain the extracted comment files. For each program in
* the source program file, a corresponding file is created (or replaced)
* in the target folder.
* If the input (programs) folder name is not provided, the operator is
* prompted to point to it.
* If the output folder name is not provided, C:\COMMENTS is used by
default.
* If an output folder name is provided, and it doesn't exist, it is
created.
* Programs are stored as variable length ASCII text files. CR/LF
sequences
* separate the lines of the prg.
public ccursrc,ccurtgt,ldoneflag,cprglist,nprgcount,ccomments
cstartdir = curdir() && save current folder on entry
nprgsdone = 0 && number of prgs scanned
do checkparms with csourcelib,ctargetlib && make sure we have
source/target folders
if ldoneflag && if anything is wrong
return && can't continue
endif
* We have valid source and target folder names
* Load an array (CPRGLIST) with an entry for each prg in folder
do loadplist && load cprglist array with program
names
if ldoneflag && if anything is wrong
return && can't continue
endif
* On return from LOADPLIST, CPRGLIST contains 1 row for each prg in the
folder
* and NPRGCOUNT contains the count of programs (rows) in the CPRGLIST
array.
* Here are calls to SCANPRG and WRITECOMF for each prg in the source
folder.
* Programs without comments will be represented in the output folder,
because
* at the very least, a header line is built for each prg before the scan
* starts.
* SCANPRG loads the CCOMMENTS variable with a header and extracted
comment lines.
* WRITECOMF writes CCOMMENTS to the output folder.
for ncurprg = 1 to nprgcount && loop for each prg in CPRGLIST
array
do scanprg with cprglist(ncurprg,1) && scan the first/next program
for comments
do writecomf with ccurtgt,cprglist(ncurprg,1) && create
[programname].txt in target folder
endfor
cd (cstartdir) && restore opers current folder
nprgsdone = ncurprg - 1 && number of prgs actually scanned
=messagebox("Scanning completed. "+transform(nprgsdone,'999,999,999')+"
comment files have been ;
placed into "+trim(ccurtgt)+" for programs in
"+trim(ccursrc),0,"Comments grabber")
return
*
------------------------------------------------------------------------
procedure writecomf && write CCOMMENTS to prgname.txt in
tgt folder
parameters ctgtfolder,csrcname && target folder name, source prg file
name
* The output comments file is named using the source program file name +
the
* file type .TXT.
* For example, MYPROG.PRG will get a counterpart comments file named
MYPROG.TXT
* If the output (comments) file already exists, it will automatically be
replaced
ndotloc = at('.',csrcname)
if empty(ndotloc)
ctgtname = alltrim(csrcname)+'.txt'
else
ctgtname = stuff(csrcname,ndotloc,4,'.txt')
endif
ctgtname = lower(trim(ctgtfolder)+'\'+ctgtname) && e.g.
c:\comments\myprg.txt
* If the target .TXT file exists, overlay it
set safety off
strtofile(ccomments,ctgtname) && create the comments counterpart file
for this prg
set safety on
return
*
------------------------------------------------------------------------
procedure scanprg && scan and extact comments from ctheprg
parameters ctheprg
* This rtn performs the scanning operation against the current program
(CTHEPRG)
* The scanning operation itself is basically a top to bottom reading of
the
* lines of the current program, checking each line to see if it's a
comment
* or not.
* At the start, the CCOMMENTS var is loaded with a header line
identifying
* the program and showing the date of the comments extraction.
* As the top to bottom scan continues, comment (and blank) lines are
added
* to the CCOMMENTS variable, which will be written out as a comments
file
* when we're done.
* Since programs are stored as variable length ASCII records,
identifying
* lines is done by scanning for CRLF sequences within the program file.
* Instead of maintaining positioning within the program files, a simple
trick
* is used: the "occurances" parameter in the AT function. By simply
bumping
* this number, we can jump forward from line to line to continue the
scan
* without regard to knowing what offset we are within the file. Since
* we're only reading the top of each file, processing is fairly
efficient,
* regardless of the fact that using AT to scan for the "Nth" occurance
will
* more than likely restart VFP processing at the beginning of the file
* each time AT is used.
* After the 1st line of the prg is handled, subsequent scan restarts
will
* start at each of the successive CRLF markers in the file. For all
lines
* except the 1st, processing is handled by examining the text following
the
* CRLF to determine whether it's a comment or code line, and then
bumping the
* "occurances" variable so the restart begins with the next CRLF
sequence.
* This loop continues until EOF or a non-comment (code) line is
encountered.
cd (ccursrc) && switch into source folder
cprgvar = filetostr(ctheprg) && read prg into a var
nhits = 1 && new line occurance counter
ntotlen = len(cprgvar) && total len of prg text
ccomments = trim(ctheprg)+'
'+dtoc(datetime())+chr(13)+chr(10)+chr(13)+chr(10) && program name at
top, 2 CRLF's
do while .t. && loop till no more CRLF's
ncrlfpos = at(chr(13)+chr(10),cprgvar,nhits) && find first/next CR/LF
if empty(ncrlfpos) && if no CRLF at all
if nhits = 1 && and we're looking for 1st comment
line
ccomments = ccomments+cprgvar && take what we've got
endif && and exit
exit
endif
* If we get here, there are at least 2 lines in the prg
* Take the 1st line of the prg file, if it's a comment line, before we
* start taking successive lines (that is, when NHITS = 1, we're scanning
* for the 1st CRLF, which is a special case because we have yet to take
* the first comment line. After NHITS is incremented, we'll be
inspecting
* subsequent lines and taking comments from AFTER the CRLF (this works
because
* we'll then go back and find the next CRLF by bumping NHITS for the AT
scan)
if nhits = 1 && special process for 1st line only
if left(cprgvar,1) = '*'
ccomments = ccomments+left(cprgvar,ncrlfpos-1)+chr(13)+chr(10)
endif
endif
* Take blank lines and comment lines until we've got them all, then
we're done
* If another CRLF or a command, take it
if substr(cprgvar,ncrlfpos+2,2) = chr(13)+chr(10) .or. ;
substr(cprgvar,ncrlfpos+2,1) = '*'
remlen = ntotlen - ncrlfpos+2 && remaining prg len
if remlen > 200 && if more than a 200 chr line
left
remlen = 200 && limit scan for end of line to
200 chrs
endif
cnextline = substr(cprgvar,ncrlfpos+2,remlen) && take next 200 (or
less) chrs
* Find the next CRLF within the (200 or fewer chrs) extracted into
CNEXTLINE
nlinelen = at(chr(13)+chr(10),cnextline)
* If there is a CRLF, take text from the line up to the CRLF
* If there is no CRLF, take the entire line + add a CRLF
if empty(nlinelen) && if CRLF not found
ccomments = ccomments + trim(cnextline)+chr(13)+chr(10)
else
ccomments = ccomments + substr(cnextline,1,nlinelen+1)
endif
nhits = nhits + 1 && bump occurance # (next scan will start with
next occurance #)
else && else, no
exit && we're done
endif
enddo
* On return CCOMENTS will contain the extracted comments for this
program file
return
*
------------------------------------------------------------------------
procedure loadplist && load the CPRGLIST array with names of
* prgs in folder being scanned
dimension cprglist(500,5)
if right(trim(ccursrc),1) = '\'
ccursrc = alltrim(ccursrc)
else
ccursrc = alltrim(ccursrc)+'\'
endif
string = ccursrc+'*.prg' && all prgs in source folder
nprgcount =adir(cprglist,(string)) && load CPRGLIST array, get count
in NPRGCOUNT
if empty(nprgcount) && if empty
=messagebox("There are no .PRG files in "+trim(ccursrc),0,"Comment
grabber")
store .t. to ldoneflag && stop processing
endif
return
*
------------------------------------------------------------------------
procedure checkparms && check the input parameters
parameters csource,ctarget
* If the source prg library name wasn't passed or it's not a folder
name,
* prompt for it's name/loc
if vartype(csource) = 'U' .or. !directory(csource)
ccursrc = "c:\devtest"
ccursrc = getdir(ccursrc,"Source prgs")
else
ccursrc = csource
endif
* If the target folder name wasn't passed, create it in root folder with
* the name "C:\COMMENTS" (if C:\COMMENTS already exists, use it)
* If the target folder name was passed but it doesn't exist, create it.
Note
* that a folder structure will be created if parent/child folders are
named
* as the output folder name and none of the nodes exist.
if vartype(ctarget) = 'U' && if target folder name not supplied
ccurtgt = "c:\comments" && use default name c:\comments
else
ccurtgt = ctarget && use supplied target folder name
endif
if !directory(ccurtgt) && if target folder doesn't exist
md (ccurtgt) && create it now
endif
return
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/profox
OT-free version of this list: http://leafe.com/mailman/listinfo/profoxtech
** All postings, unless explicitly stated otherwise, are the opinions of the
author, and do not constitute legal or medical advice. This statement is added
to the messages for those lawyers who are too stupid to see the obvious.