Code archives/File Utilities/Get online doc examples

This code has been declared by its author to be Public Domain code.

Download source code

Get online doc examples by markcw2014
This adds code from the Blitzmax online manual to the Brl and Pub module docs.

The code takes a few minutes to run through getting the examples from the website. It creates a local copy of the Modules folder where you run the file from.
If you want to update it you need to delete or rename the Modules folder. There is also a log file to remind you what was added.

Rebuild docs will remove the code examples but you can just run this again and if it has the local copy it won't download anything, it will just use the local copy.
You can run this file anywhere in your Blitzmax directory.

The way it works is, if there is an example in the docs already it won't add another one. If the online manual has an official entry it will be chosen,
and if there is an example from the comments section it chooses the first one in the most recent post, this way improvements can be made on existing code.

Oct 2014: updated to treat any text above selected code as about/comment. A char limit of 500 is there to prevent entries that are very long.
' Get online doc examples.bmx

SuperStrict

TGetHttpCode.FindAll()

End

' Gets code examples from the online manual and adds them to the docs
Type TGetHttpCode

	Global filei%,files$[1000],mdir$,aboutlimit%=500
	
	Function FindAll()
	
		mdir=FindDocs()
		
		If FileType("Modules")=0 ' no modules folder
			Print "Creating Modules folder"
			HttpFindFiles(mdir) ' get online examples
		Else
			Print "Modules folder already exists"
		EndIf
		
		CodeFindFiles("Modules") ' copy files
		
		CodeSaveFuncs()
		
		HtmlFindFiles(mdir) ' add to html files
		
	End Function
	
	Function FindDocs$()
	
		Local wdir$=CurrentDir()+"/" ' find the docs
		Local ldir$=wdir.Tolower() ' lowercase
		Local bms%=ldir.Find("blitzmax",0) ' bmax start
		If bms=-1 RuntimeError "Failed to find blitzmax directory e1"
		
		Local bme%=ldir.Find("/",bms) ' bmax end
		Return wdir[..bme]+"/docs/html/Modules" ' modules dir
		
	End Function
	
	' part 1: get code from http files
	
	Function HttpFindFiles(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e2"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then HttpFindFiles2(cfile) ' directory
		Forever
	
		CloseDir dh
		
	End Function

	Function HttpFindFiles2(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e3"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then HttpFindFiles3(cfile) ' directory
		Forever
		
		CloseDir dh
		
	End Function

	Function HttpFindFiles3(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e4"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=1 ' file, html
				If ExtractExt(cfile)="html" Then HttpOpenHtml(cfile)
			EndIf
		Forever
		
		CloseDir dh
		
	End Function

	Function HttpOpenHtml(path$)
	
		Local file:TStream=OpenFile(path)
		If Not file RuntimeError "could not open html file e5"

		While Not Eof(file)
		
			Local html$=ReadString(file,FileSize(path))
			Local html2$,link$,code$
			Local fr%=html.Find("Function reference",0)
			Local fts%=fr,fbs%,fen%,fte%,fbe%
			
			If fr>0 ' file has functions
			Print "Reading: "+path[mdir.length+1..path.Find("index.html",mdir.length)-1]
			
				While fts>-1 ' while functions in file
					fts=html.Find("colspan=2>Function ",fts+1)
					
					If fts>0
					
						fts:+19 ' to function name
						fbs=html.Find("(",fts) ' bracket start
						fte=html.Find("</td>",fts) ' table end
						fen=html[fts..fbs].Find(":",0) ' type (end of func name)
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("[",0) ' array
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("$",0) ' string
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("#",0) ' float
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("!",0) ' double
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("_",0)
						
						If fen=-1 ' not a lua_func
							fen=html[fts..fbs].Find(" ",0) ' trim spaces
							If fen>0 Then fbs=fts+fen
							Local func$=html[fts..fbs] ' get func name
							fbe=html[fts..fte].Find("NoDebug",0) ' bracket end or nodebug
							If fbe=-1 Then fbe=html[fts..fte].FindLast(")",0) Else fbe:+6
							fbe:+fts+1
							link="http::www.blitzmax.com/bmdocs/command.php?name="+func+"&ref=goto"
							code=HttpOpen(link,func)
							If code.length>0 Then HttpSaveCode(path,func,code)
						EndIf
						
					EndIf
					
				Wend
				
			EndIf
			
		Wend
		
		CloseStream file
		
	End Function

	Function HttpOpen$(url$,func$)
	
		Local in:TStream=ReadStream(url)
		If Not in RuntimeError "Failed to open a ReadStream to http file e6"
		
		Local http$
		While Not Eof(in)
			http:+ReadLine(in)+"~n"
		Wend
		
		Local user$,code$,about$
		Local tmp%,cs%,ps%,ai%,opf%,pe%,ui%,tmp2%,gt%,cu%,cc%,nc%
		Local paf%[1000],ua%[1000],pa%[1000]
		
		Print func
		ps=0
		While ps>-1
			ps=http.Find("<pre class=code>",ps+1)
			If ps>0 Then  pa[ai]=ps ; ai:+1 ' pre array
		Wend
		
		ps=0
		While ps>-1
			ps=http.Find("<textarea class=codebox ",ps+1)
			If ps>0 Then pa[ai]=ps ; ai:+1
		Wend
		
		ps=0
		While ps>-1
			ps=http.Find("<td class="+Chr(34)+"posthead"+Chr(34)+">",ps+1)
			If ps>0 Then  ua[ui]=ps ; ui:+1 ' username array
		Wend
		
		For tmp=0 To ai-1
			If pa[tmp]<cs Then opf=pa[tmp] ; Exit ' official pre found
		Next
		
		If opf ' official pre
			pe=http.Find("</pre>",opf)
			code=http[opf+16..pe].Trim() ' get the code
			
			CloseStream in
			Return code
		EndIf
		
		ua[ui]=-1 ' last user
		For tmp=0 To ai-1
			For tmp2=0 To ui-1
				If tmp2=ui-1 Then gt=pa[tmp]+1 Else gt=ua[tmp2+1] ' greater
				If pa[tmp]>ua[tmp2] And pa[tmp]<gt ' pre between these values
					cu=ua[tmp2] ' user
					If paf[tmp2]=0 Then cc=pa[tmp] ; paf[tmp2]=cc ' last user with first code example
				EndIf
			Next
		Next
		
		If cu=0 And cc=0 ' no code examples
			ps=0
			While ps>-1
				ps=http.Find("<td class="+Chr(34)+"posttext"+Chr(34)+">",ps+1) ' last comment
				If ps>0 Then nc=ps
			Wend
			
			tmp=http.Find("</td></tr>",nc+21)
			If tmp>0 And nc>0 ' found comment
				code="Rem~n"+http[nc+21..tmp]+"~nEndRem~n"
				code:+"' "+func.Tolower()+".bmx ()"
				If code.length<20 Or code.length>aboutlimit Then code="" ' ignore
			EndIf
			
			CloseStream in
			Return code
		EndIf
		
		ps=http.Find("<td >",cu) ' get username
		tmp=http[ps..ps+9].Find("<a href=",0) ' check for link
		If tmp>-1 Then ps=http.Find("</a>",tmp)
		tmp2=http.Find("</td>",ps)
		user=http[ps+5..tmp2]
		
		tmp=http.Find("<td class="+Chr(34)+"posttext"+Chr(34)+">",cu) ' get about text
		tmp2=http.Find(">",tmp)+1
		about="Rem~n"+http[tmp2..cc]+"~nEndRem~n"
		If about.length<20 Or about.length>aboutlimit Then about="" ' ignore
		
		tmp=http[cc..cc+9].Find("<pre ",0) ' get example
		If tmp=-1 Then pe=http.Find("</textarea>",cc) Else pe=http.Find("</pre>",cc)
		tmp2=http.Find(">",cc)+1
		code=http[cc..pe].Trim()
		tmp=code.Find("~n",0)
		If tmp2>-1 Then code=code[tmp..].Trim()
		tmp2=code.Find(".bmx",0)
		code=about+"' "+func.Tolower()+".bmx ("+user+")~n~n"+code
		
		CloseStream in
		Return code
		
	End Function

	Function HttpSaveCode(path$,func$,code$)
	
		Local success%,fs%,fs2%,file:TStream
		Local lpath$,ldir2$,ldir3$,ldir$
		
		ldir="Modules"
		If FileType(ldir)=0
			success=CreateDir(ldir)
			If Not success RuntimeError "error creating directory e7"
		EndIf
		
		fs=path.Find("/",mdir.length+1) ' directory level 2
		ldir2=ldir+path[mdir.length..fs]
		If FileType(ldir2)=0
			success=CreateDir(ldir2)
			If Not success RuntimeError "error creating directory e8"
		EndIf
		
		fs2=path.Find("/",fs+1) ' directory level 3
		ldir3=ldir+path[mdir.length..fs]+path[fs..fs2]
		If FileType(ldir3)=0
			success=CreateDir(ldir3)
			If Not success RuntimeError "error creating directory e9"
		EndIf
		
		lpath=ldir+path[mdir.length..fs]+path[fs..fs2]+"/"+func.Tolower()+".bmx" ' local file path
		file=WriteFile(lpath)
		If Not file RuntimeError "failed to open file e10" 
		WriteLine file,code
		CloseStream file
		
	End Function

	' part 2: copy local files to docs/html
	
	Function CodeFindFiles(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e11"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then CodeFindFiles2(cfile) ' directory
		Forever
	
		CloseDir dh
		
	End Function

	Function CodeFindFiles2(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e12"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then CodeFindFiles3(cfile) ' directory
		Forever
		
		CloseDir dh
		
	End Function

	Function CodeFindFiles3(dir$)
	
		Local ddir$,temp$,code$,file:TStream
		Local dh%,fp%,cf%,re%
		
		dh=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e13"
		
		Repeat
			temp=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			fp=cfile.Find("/",0)
			ddir=mdir+cfile[fp..]
			
			If FileSize(ddir)=-1 ' file, bmx
				files[filei]=cfile ' store local file path
				filei:+1
				
				code=HtmlReadCode(cfile)
				cf=code.Find(".bmx (",0) ' if comment file
				If cf>0 ' strip rem
					re=code.Find("EndRem",0)
					If re>0 And re<cf
						code=code[re+8..]
					EndIf
				EndIf
				
				cf=code.Find(".bmx ()",0) ' blank user=comment but no code
				If cf=-1
					file=WriteFile(ddir) ' copy from local to docs/html
					If Not file RuntimeError "failed to open file e14" 
					WriteLine file,code
					CloseStream file
				EndIf
			EndIf
			
		Forever
		
		CloseDir dh
		
	End Function

	Function CodeSaveFuncs()
	
		Local fi%,file:TStream
		
		If FileSize("Modules/log.txt")=-1 ' file doesn't exist
			file=WriteFile("Modules/log.txt")
			If Not file RuntimeError "failed to open file e15"
			
			For fi=0 To filei-1 ' file index
				WriteLine file,files[fi]
			Next
			CloseStream file
		EndIf
		
	End Function
	
	' part 3: add code examples to docs/html
	
	Function HtmlFindFiles(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e16"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then HtmlFindFiles2(cfile) ' directory
		Forever
	
		CloseDir dh
		
	End Function

	Function HtmlFindFiles2(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e17"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=2 Then HtmlFindFiles3(cfile) ' directory
		Forever
		
		CloseDir dh
		
	End Function

	Function HtmlFindFiles3(dir$)
	
		Local dh%=ReadDir(dir)
		If Not dh RuntimeError "failed to read current directory e18"
	
		Repeat
			Local temp$=NextFile(dh)
			If temp="" Then Exit ' done
			If temp="." Or temp=".." Continue ' skip
			Local cfile$=dir+"/"+temp ' current file
			If FileType(cfile)=1 ' file, html
				If ExtractExt(cfile)="html" Then HtmlOpenHtml(cfile)
			EndIf
		Forever
		
		CloseDir dh
		
	End Function

	Function HtmlOpenHtml(path$)
	
		Local html$,html2$,code$,row$,about$,info$
		Local file:TStream=OpenFile(path)
		If Not file RuntimeError "could not open html file e19"
		
		While Not Eof(file)
		
			html=ReadString(file,FileSize(path))
			Local fr%=html.Find("Function reference",0)
			Local fts%=fr
			Local fbs%,fen%,fte%,fls%,fep%,fer%,fet%,fri%,flr%,fhe%,fni%,fne%,fnt%,lnt%,fnf%,tmp%,tmp2%
			
			If fr>0 ' file has functions
			html2=html
			
				While fts>-1 ' while functions in file
					fts=html.Find("colspan=2>Function ",fts+1) ' table start
					
					If fts>0
					
						fts:+19 ' to function name
						fbs=html.Find("(",fts) ' bracket start
						fte=html.Find("</td>",fts) ' table end
						fen=html[fts..fbs].Find(":",0) ' type (end name)
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("[",0) ' array
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("$",0) ' string
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("#",0) ' float
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("!",0) ' double
						If fen>0 Then fbs=fts+fen
						fen=html[fts..fbs].Find("_",0)
						
						If fen=-1 ' not a lua_func
						
							fen=html[fts..fbs].Find(" ",0) ' trim spaces
							If fen>0 Then fbs=fts+fen
							Local func$=html[fts..fbs] ' get func name
							
							For fni=0 To filei-1 ' new index
							
								fls=files[fni].FindLast("/",0)+1 ' last slash
								fep=files[fni].Find(".bmx",fls) ' extension pos
								
								If files[fni][fls..fep]=func.Tolower()
								
									fne=html.Find("<table class=doc ",fbs) ' next entry
									If fne=-1 Then fne=html.Find("</body>",fbs)
									fet=html.Find("</table>",fbs) ' end table
									
									fnt=fbs
									For fri=0 To 3 ' last nested table
										lnt=fnt
										fnt=html.Find("<table>",fnt+1) ' nested table
										If fnt<fne And fnt>0 Then fnt=lnt ; Exit ' is nested
									Next
									
									fnf=0
									If fnt<fne And fnt>0 ' found nested table
										fet=html.Find("</table>",fnt)
										fnf=html.Find("</tr>",fet)
										fet=html.Find("</table>",fet)
									EndIf
									
									fer=fbs ' end row
									For fri=0 To 19 ' row index
										flr=fer ' last row
										fer=html.Find("</tr>",fer+1)
										
										If fer>fet Or fer=-1
											flr:+5
											If fnf Then flr=fnf+5
											Exit
										EndIf
									Next
									
									fhe=html.Find("Example</a>",fbs) ' has example	
									If fhe=-1 Or fhe>fet ' no example found
										code=HtmlReadCode(files[fni])
										Print "Adding Examples: "+files[fni]
										
										tmp=code.Find("EndRem",0) ' about text
										info="" ; about=""
										If tmp>-1
											about=code[4..tmp]
											tmp2=about.Find("<br>",about.length-6)
											If tmp2>-1 Then about=about[..tmp2] ' rm last br
											
											tmp2=0
											While tmp2>-1 ' rm blank link targets
												tmp2=about.Find(" target="+Chr(34)+"_blank"+Chr(34),tmp2+1)
												If tmp2>0 Then about=about[..tmp2]+about[tmp2+15..]
											Wend
											
											code=code[tmp+8..]
											If about.length>10
												info="<tr><td class=docleft width=1%>Comment</td>"
												info:+"<td class=docright>"+about+"</td></tr>"
											EndIf
										EndIf
										
										row=info
										tmp=code.Find(".bmx ()",0) ' blank user=comment but no code
										If tmp=-1
											row:+"~n<tr><td class=docleft width=1%><a href="
											row:+Chr(34)+func.Tolower()+".bmx"+Chr(34)
											row:+">Example</a></td><td class=docright><pre>"
											row:+code+"</pre>~n</td></tr>"
										EndIf
										html2=html[..flr]+row+html[flr..]
									EndIf
									
								EndIf
								
							Next
							
						EndIf
						
					EndIf
					html=html2 ' update html
				Wend
				
			EndIf
		Wend
		
		SeekStream file,0 ' overwrite file
		WriteString file,html
		CloseStream file
		
	End Function

	Function HtmlReadCode$(path$)
	
		Local file:TStream=ReadFile(path)
		If Not file RuntimeError "could not open bmx file e20"
		
		Local code$=ReadString(file,FileSize(path))
		
		CloseStream file
		Return code
		
	End Function

End Type

Comments

markcw2014
Just fixed a few bugs, nested tables and last entries on a page were not handled.


zoqfotpik2014
Very nice.


markcw2014
Thanks. I just updated this to add any text above a selected code as an about.


markcw2014
Just updated again. Now it adds an about/comment even if there is no code, which is quite handy. It will select the last non-code comment on a page (so poor comments can be overwritten).


Code Archives Forum