CFEclipse Dictionary for CF on Wheels

Posted by Quinn Madson | Posted in | Posted on 9:56 PM

3

As far as I could tell, there was no CFEclipse dictionary available for CF on Wheels so I created one.


To get it, download the XML at: http://su.pr/6s1VUi

To use it:
  • Open your Eclipse plugins/ directory
  • Open the directory: org.cfeclipse.cfml_X/ (where X is your CFEclipse version number)
  • Open the directory: dictionary
  • Copy cfwheels.xml to this location
  • Close Eclipse if it is running
  • Open up: dictionaryconfig.xml
Change:
<version key="cf8" label="Coldfusion 8">
<grammar location="cf8.xml" />
<grammar location="user.xml" />
</version>
To:
<version key="cf8" label="Coldfusion 8">
<grammar location="cf8.xml" />
<grammar location="user.xml" />
<grammar location="cfwheels.xml" />
</version>
I am not sure if it is an Ubuntu bug but, any thing that is not in the first grammar file is not loaded in Eclipse. If you run into problems, just copy and paste the functions listed in cfwheels.xml to cf8.xml or whatever dialect you use. The other option is to create a separate CFWheels dictionary entry but, it doesn't work very well switching back and forth between dictionary sets.

In the likely event that I am struck by a bus, a very confused sperm whale, or bowl of petunias, I created a script that scrapes the CF on Wheels documentation and creates the dictionary XML. If more functions are added and the structure of the docs pages don't change immensely, rerun the script to refresh the dictionary XML.

Here's the code:

<cfparam name="url.page" default="0">
<cfparam name="url.start" default="0">
<cfparam name="url.end" default="0">

<!---
Strips all table and table content tags and extra whitespace from a string.

@param string String to format. (Required)
@return Returns a string.
@author Jared Rypka-Hauer (jared@web-relevant.com)
@version 1, August 25, 2005
--->
<cffunction name="detableize">
<cfargument name="string" type="string" required="true" />
<cfset var outputString = arguments["string"]>
<cfset outputString = reReplaceNoCase(outputString , "</*table>", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "</*td>", "ø", "all")>
<cfset outputString = reReplaceNoCase(outputString , "</*t[rhd](\s*\w*=*""*\w*""*)*>", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "(?m)^\s*", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "\n{2,}", "#chr(10)#", "all")>
<cfreturn outputString />
</cffunction>

<!--- based on function above; removes garbage from api page --->
<cffunction name="detagify">
<cfargument name="string" type="string" required="true" />
<cfset var outputString = arguments["string"]>
<cfset outputString = reReplaceNoCase(outputString , "</*li>", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "<code>[a-z\(\)]*</code>", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "<a href=""", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , """></a>", ",", "all")>
<cfset outputString = reReplaceNoCase(outputString , "(?m)^\s*", "", "all")>
<cfset outputString = reReplaceNoCase(outputString , "\n{2,}", "#chr(10)#", "all")>
<cfreturn outputString />
</cffunction>

<cfscript>
/**
* Returns the content enclosed in a tag pair.
*
* @param tag The tag to look for. Should be passed without < or > and without attributes. (Required)
* @param string The string to search. (Required)
* @return Returns a string.
* @author Johan Steenkamp (johan@orbital.co.nz)
* @version 1, September 16, 2002
*/
function getTagContent(tag,str) {
var matchStruct = structNew();
var startTag = "<#tag#[^>]*>";
var endTag = "</#tag#>";
var endTagStart = 0;
matchStruct = REFindNoCase(startTag,str,1,"true");
if(matchStruct.len[1] eq 0 ) return "";
endTagStart = REFindNoCase(endTag,str,matchStruct.pos[1],"false");
return Mid(str,matchStruct.pos[1]+matchStruct.len[1],endTagStart-matchStruct.pos[1]-matchStruct.len[1]);
}
</cfscript>

<!--- get urls --->
<cfhttp url="http://cfwheels.org/docs/function/"></cfhttp>
<cfscript>
urlsFilecontent = cfhttp.filecontent;
urlsStartPoint = find("<h1>Wheels <abbr title=""Application Programming Interface"">API</abbr></h1>", urlsFilecontent);
urlsEndPoint = len(urlsFilecontent) - urlsStartPoint;
urlsChopped = mid(urlsFilecontent, urlsStartPoint, urlsEndPoint);
urlsChopped = getTagContent("ul", urlsChopped);
urlsChopped = detagify(urlsChopped);
urlsChopped = listToArray(urlsChopped);
dictionary = "";
itemsPerPage = 25;
urlsPages = ceiling(arrayLen(urlsChopped) / itemsPerPage);
</cfscript>

<cfoutput>
<h1>CFWheels API to CFEclipse Dictionary Conversion</h1>
<p>#arrayLen(urlsChopped)# functions listed in documentation. Function conversions are broken up into batches to prevent timeouts.
Click below to convert a batch.</p>
<ul>
<cfloop from="1" to="#urlsPages#" index="i">
<cfscript>
if (i neq 1) {
start = (i - 1) * itemsPerPage;
end = start + itemsPerPage - 1;
} else {
start = 1;
end = itemsPerPage - 1;
}

if (end gt arrayLen(urlsChopped)) {
end = arrayLen(urlsChopped);
}
</cfscript>
<li><a href="?page=#i#&start=#start#&end=#end#">#i#: #start# - #end#</a></li>
</cfloop>
</ul>
</cfoutput>

<cfif url.page>
<cfloop from="#url.start#" to="#url.end#" index="i">

<!--- convert html to cfeclipse dictionary xml --->
<cfhttp url="http://cfwheels.org#urlsChopped[i]#"></cfhttp>
<cfset functionFilecontent = cfhttp.filecontent>

<cfscript>
functionStartPoint = findnocase("contentWrapper", functionFilecontent);
functionEndPoint = len(functionFilecontent) - functionStartPoint;
functionChopped = mid(functionFilecontent, functionStartPoint, functionEndPoint);
functionName = getTagContent("code", functionChopped);
functionChopped = replacenocase(functionChopped, "<code>", "", "all");
functionChopped = replacenocase(functionChopped, "</code>", "", "all");
functionDescription = getTagContent("p", functionChopped);
functionParameters = getTagContent("tbody", functionChopped);
functionParameters = detableize(functionParameters);
functionParameters = listToArray(functionParameters, "ø", true);
</cfscript>

<cfoutput>
<cfsavecontent variable="functionOutput">
<function xmlns="http://www.cfeclipse.org/version1/dictionary" name="#xmlFormat(functionName)#" returns="">

<help><![CDATA[
#xmlFormat(trim(functionDescription))#
]]></help>
<cfloop from="1" to="#arrayLen(functionParameters)-1#" index="i" step="5"><cfif functionParameters[i+2] eq "No"><cfset required="false"><cfelse><cfset required="true"></cfif>
<parameter name="#xmlFormat(trim(functionParameters[i]))#" type="#xmlFormat(trim(functionParameters[i+1]))#" required="#xmlFormat(trim(required))#">
<help><![CDATA[
#xmlFormat(trim(functionParameters[i+4]))#
]]></help>
</parameter>
</cfloop>
</function>
</cfsavecontent>
</cfoutput>

<cfset dictionary = dictionary & functionOutput>

</cfloop>
<cfoutput>
<textarea cols="150" rows="50">
#dictionary#
</textarea>
</cfoutput>
</cfif>
Hopes this helps some other CFEclipse & CF on Wheels developers out there.

Comments (3)

I cannot wait to try this when I get home. You just might be my new hero :-)

Thanks for this :-)

Randy

Hey Randy, I'm really eager to install this awesome dictionary you created... but I can't find a cfeclipse subdirectory under my plugins. I definitely have CFEclipse installed, but for some reason I see lots of similarly-named directories, but none for cfeclipse. I'm on Windows 7. Any ideas?

Oh Sorry Quinn I saw Randy's comment above mine and that name got stuck in my head.