Monday, February 20, 2006

About: Format My Source Code

Several times I have wanted to post code to my blog. Only to find the process frustrating. To put the code on a blog you have to convert the source text into HTML. This also involves converting tabs to spaces; converting special characters to HTML encoding; setting a nice fixed-width font; and fixing a couple of other minor issues.

After searching around, I found a web page that would format C# and other Microsoft languages at C# code format. Which was great for C#, but I wanted to post Ruby, Java and other languages. My answer was to code my own source code to HTML converter. After hacking a little java-script, I have created:

Format My Source Code

The application is just a little bit of Java Script and DHTML to perform the conversion. I decided to publish it on blogspot since it was a tool for blogging. Getting everything to fit in the confines of a Blog page was a little limiting. I might change the layout when I've got more time.

The application has a few interesting features. When you press the "Format" button, I have the output section perform a yellow fade which was invented by Matthew Linderman at 37 Signals. I modified their technique a little to adjust the timing.

One problem I encountered was Blogger's editor. The "Compose" option would eat vertical pipe characters: |. Since my favorite language Ruby uses this character a lot, I tried hard to find a way to fix it. But "Compose" would always remove the characters. Fortunately, the "Edit HTML" option leaves the | character alone. So I added the detection of this character and a small warning will display.

To increase the usability, I added some code to automatically select the first input when the page loads. So a simple ctrl-v will paste into the input field without requiring any additional typing or mousing. Likewise, the generated HTML is automatically selected so all you need is to hit ctrl-c to copy to the clipboard.

I have the example output clipped to 25 lines. Also, if Embed Stylesheet is not used, an example style sheet will appear.

Enjoy!

If you are curious, here is the source code (at the time it was first posted):
<head>
<!-- THIS STUFF GOES IN THE HEADER TEMPLATE -->
<style type="text/css">
pre.source-code {
font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
color: #000000;
background-color: #eee;
font-size: 12px;
border: 1px dashed #999999;
line-height: 14px;
padding: 5px;
overflow: auto;
width: 100%
}
p.warning {
color: #000000;
background-color: #FFB6C1;
font-size: 12px;
border: 3px double #333333;
line-height: 14px;
padding: 5px;
overflow: auto;
width: 100%
}
</style>
<SCRIPT LANGUAGE="JavaScript">
<!--
var Color= new Array();
Color[1] = "ff";
Color[2] = "ee";
Color[3] = "dd";
Color[4] = "cc";
Color[5] = "bb";
Color[6] = "aa";
Color[7] = "99";

function fadeIn(where) {
if (where >= 1) {
document.getElementById('fade').style.backgroundColor = "#ffff" + Color[where];
if (where > 1) {
where -= 1;
setTimeout("fadeIn("+where+")", 200);
} else {
where -= 1;
setTimeout("fadeIn("+where+")", 200);
document.getElementById('fade').style.backgroundColor = "transparent";
}
}
}

function format() {
var strIn = document.getElementById("textin").value;
var strOut = null;
if ( document.getElementById("embedstyle").checked ) {
strOut = "<pre style=\"font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%\"><code>";
hideElement("style");
} else {
strOut = "<pre class=\"source-code\"><code>";
showElement("style");
}
var strOut25 = null;
var line = 1;
var strTab;
var hasVerticalPipe = false;

if ( document.getElementById("tab4").checked ) {
strTab = " ";
} else {
strTab = " ";
}

for ( i = 0; i < strIn.length; i++ ) {
var code = strIn.charCodeAt(i);
switch( code ) {
case 9: // tab
strOut += strTab;
break;
case 10: // line-feed
case 13:
strOut += "\n";
line += 1;
if ( line == 26 ) {
strOut25 = strOut + "[only the first 25 lines shown in this example]\n\n";
}
if ( code == 13 && (i + 1) < strIn.length && strIn.charCodeAt(i + 1) == 10 ) {
i++;
}
break;
case 34:
strOut += "&quot;";
break;
case 38:
strOut += "&amp;";
break;
case 60:
strOut += "&lt;";
break;
case 62:
strOut += "&gt;";
break;
case 124: // vertical pipe (blogger modifies this)
strOut += "&#124;";
hasVerticalPipe = true;
break;
default:
if ( code >= 32 && code <= 127 ) {
strOut += strIn.charAt(i);
} else {
strOut += "&#" + code + ";";
}
break;
} // switch
} // for
strOut += "\n</code></pre>";
var textoutelement = document.getElementById("textout")
textoutelement.value = strOut;
textoutelement.focus();
textoutelement.select();

if ( hasVerticalPipe ) {
showElement( "vert-pipe-warning" );
} else {
hideElement( "vert-pipe-warning" );
}

var resultselement = document.getElementById("results");
if ( strOut25 != null ) {
resultselement.innerHTML = strOut25;
} else {
resultselement.innerHTML = strOut;
}

fadeIn(7);
}

function onloadEvent() {
var textinelement = document.getElementById("textin");
textinelement.focus();
textinelement.select();
}

function showElement(strId) {
var ref = document.getElementById(strId);
if ( ref.style) { ref = ref.style; }
ref.display = '';
}

function hideElement(strId) {
var ref = document.getElementById(strId);
if ( ref.style) { ref = ref.style; }
ref.display = 'none';
}
//-->
</SCRIPT>
<!-- END STUFF GOES IN THE HEADER TEMPLATE -->
</head>
<!-- THE BODY ELEMENT NEEDS THE ONLOAD EVENT -->
<body onLoad="javascript:onloadEvent()">
<!-- THIS STUFF GOES IN POST -->
<form>
<p>
<textarea wrap="off" rows="5" cols="50" id="textin">Paste your text here.</textarea><br/>
<table>
<tr>
<td><button onclick="format()" type="button">Format Text</button></td>
<td>
Tab size: <input type="radio" name="tabsize" id="tab4" checked="true">4</input> <input type="radio" name="tabsize" id="tab8">8</input><br/>
Embed Stylesheet: <input type="checkbox" id="embedstyle" checked="true"></input><br/>
</td>
</tr>
</table>
</p>
<p>
<div class="step-instr" id="fade">Copy the HTML below to your clipboard. Insert the HTML of your blog or wiki.<br/>
<textarea wrap="off" rows="12" cols="50" id="textout">formatted HTML will appear in here.</textarea></div>
</form>
</p>
<div id="vert-pipe-warning" style="display: none">
<p class="warning">
<b>Vertival Pipe Character Warning:</b><br/>
The text contains the vertical pipe character '|' which Blogger's editor may remove. Blogger's editor on the web has two edit tabs: "Edit HTML" and "Compose". The "Compose" tab will remove all | characters! Use the "Edit HTML" tab only.
</p>
</div>
<div id="results"><pre class="source-code"><code>This is an example of what your text will look like.
&#8226; Tabs are converted to spaces.
&#8226; Quotes and other special characters are converted to HTML.
&#8226; Everything is enclose in HTML's 'pre' and 'code' tags.
&#8226; Style is set:
&#8226; Fixed width font.
&#8226; Shaded box.
&#8226; Dotted line border.

</code></pre>
</div>
<p>
<div id="style" style="display: none">
Example Stylesheet:<br/>
<textarea wrap="off" rows="13" cols="50" id="textout"><style type="text/css">
pre.source-code {
font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;
color: #000000;
background-color: #eee;
font-size: 12px;
border: 1px dashed #999999;
line-height: 14px;
padding: 5px;
overflow: auto;
width: 100%
}
</style></textarea>
</div>
</p>
<!-- END STUFF IN POST -->
</body>

Thursday, February 16, 2006

JUnit 4.0 is here!

Download: http://sourceforge.net/project/showfiles.php?group_id=15278&package_id=12472&release_id=394034

v 3.8.1 was release in September 2002. It has been a long time since the last update. V4.0 requires Java5, as it uses annotations to mark tests.

Monday, February 06, 2006

VMWare Server for Free :)

VMWave is making a new VMWare Server product available for free. See http://www.theregister.com/2006/02/03/vmware_goes_free/ for a better write up.