> 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
©2006 Bill Arnold |
|