Archive for the ‘Coding’ Category

Updated WordPress Code Highlighter to GeSHi 1.0.8.6

Wednesday, May 12th, 2010

Today I've been tracking down a little rendering bug with MarsEdit and WordPress. It's in the pre tags that run through the Code Highlighter plugin that I've been using for quite a while. It's the "less-than-sign". If I use the HTML escape code then I get that as the literal text in the MarsEdit preview pane as well as the WordPress page. But if I place the single character, MarsEdit thinks it's the start of a tag, and gets confused on the syntax highlighting.

So the two questions are: why can't the Code Highlighter handle the HTML escape for the less-than-sign, and why is MarsEdit not rendering it properly? I'm going to attack the first, and let Daniel handle the second.

First thing I noticed was that the Code Highlighter is based on the GeSHi engine and the version it's working on was 1.0.7.x whereas the current version is 1.0.8.6. So let's see if we can update the GeSHi engine in the plugin without breaking anything.

Turns out, it's a pretty simple encapsulation of the GeSHi engine. I was able to drop in the new version without too much trouble. In the doing, I've upgraded the languages that this guy can work with considerably. That's a very nice little perk.

Unfortunately, this didn't solve the problem with the less-than-sign. I did a cursory look in the GeSHi code and didn't see where it'd be doing any conversions. I'll probably spend a little more time on it - just to see if it's possible. But even if that doesn't come to anything, we have a far better selection of supported languages:

4cs            div            lscript       python
abap           dos            lsl2          qbasic
actionscript   dot            lua           rails
actionscript3  eiffel         m68k          rebol
ada            email          make          reg
apache         erlang         mapbasic      robots
applescript    fo             matlab        rsplus
apt_sources    fortran        mirc          ruby
asm            freebasic      mmix          sas
asp            fsharp         modula3       scala
autohotkey     gambas         mpasm         scheme
autoit         gdb            mxml          scilab
avisynth       genero         mysql         sdlbasic
awk            gettext        newlisp       smalltalk
bash           glsl           nsis          smarty
basic4gl       gml            oberon2       sql
bf             gnuplot        objc          systemverilog
bibtex         groovy         ocaml-brief   tcl
blitzbasic     haskell        ocaml         teraterm
bnf            hq9plus        oobas         text
boo            html4strict    oracle11      thinbasic
c              idl            oracle8       tsql
c_mac          ini            pascal        typoscript
caddcl         inno           per           vb
cadlisp        intercal       perl          vbnet
cfdg           io             perl6         verilog
cfm            java           php-brief     vhdl
cil            java5          php           vim
clojure        javascript     pic16         visualfoxpro
cmake          jquery         pike          visualprolog
cobol          kixtart        pixelbender   whitespace
cpp-qt         klonec         plsql         whois
cpp            klonecpp       povray        winbatch
csharp         latex          powerbuilder  xml
css            lisp           powershell    xorg_conf
cuesheet       locobasic      progress      xpp
d              logtalk        prolog        z80
dcs            lolcode        properties
delphi         lotusformulas  providex
diff           lotusscript    purebasic

[5/13] UPDATE: I was doing some more digging into the GeSHi engine - actually the Code Highlighter plugin, and I found what I thought was going to be a good place to fix this problem. In the codehighlighter.php file, we see:

  1. if ($lang != null) {
  2. $tabstop = 2;
  3.  
  4. $code = trim($matches[5], '\r\n');
  5. $code = str_replace('< /pre>', '</pre>', $code);
  6.  
  7. $geshi =& new GeSHi($code, $lang);
  8. $geshi->set_tab_width($tabstop);

where it's clear in the comments that he's allowing for the special case use of the pre tag, and I decided to try a simple modification of that for these less-than and greater-than signs I'm having trouble with:

  1. if ($lang != null) {
  2. $tabstop = 2;
  3.  
  4. $code = trim($matches[5], '\r\n');
  5. $code = str_replace('< /pre>', '</pre>', $code);
  6. $code = str_replace('\&\l\t\;', '<', $code);
  7. $code = str_replace('\&\g\t\;', '>', $code);
  8.  
  9. $geshi =& new GeSHi($code, $lang);
  10. $geshi->set_tab_width($tabstop);

This is a little odd in the way I have to show it, but it's pretty simple to understand - you replace the HTML escape sequence with the single character in the code. From there, you let the GeSHi engine do it's thing.

What I found was that it worked wonderfully! What a treat. Now I can use either method, and hopefully Daniel will have a fix for MarsEdit sooner rather than later.

The next thing I wanted to tackle with the Code Highlighter was the line numbers. There was far too much space between the lines in a code sample with line numbers. Turns out, there's a style for that in GeSHi. Simply edit the geshi.php file:

  1. /**
  2.   * Line number styles
  3.   * @var string
  4.   */
  5. var $line_style1 = 'font-weight: normal; vertical-align:top;';
  6.  
  7. /**
  8.   * Line number styles for fancy lines
  9.   * @var string
  10.   */
  11. var $line_style2 = 'font-weight: bold; vertical-align:top;';

to be:

  1. /**
  2.   * Line number styles
  3.   * @var string
  4.   */
  5. var $line_style1 = 'margin: 0; font-weight: normal; vertical-align:top;';
  6.  
  7. /**
  8.   * Line number styles for fancy lines
  9.   * @var string
  10.   */
  11. var $line_style2 = 'margin: 0; font-weight: bold; vertical-align:top;';

and the extra border space that the default WordPress theme puts into the li tag will be removed and it'll look much better.

The last little annoyance is the blank lines that start, and end, the code section when you use line numbers. It's just plain annoying. It makes it hard to get the numbers right, and it's whitespace that's not needed. It's a little more involved, but not too bad. In the geshi.php file, you need to change:

  1. // Get code into lines
  2. /** NOTE: memorypeak #2 */
  3. $code = explode("\n", $parsed_code);
  4. $parsed_code = $this->header();

to:

  1. // Get code into lines
  2. /** NOTE: memorypeak #2 */
  3. $code = explode("\n", $parsed_code);
  4. // remove a blank first and last line
  5. if ('' == trim($code[count($code) - 1])) {
  6. unset($code[count($code) - 1]);
  7. $code = array_values($code);
  8. }
  9. if ('' == trim($code[0])) {
  10. unset($code[0]);
  11. $code = array_values($code);
  12. }
  13. $parsed_code = $this->header();

Now I can imagine a way that might be a little more efficient, but I'm not worried at this point. It's not all that bad, and it's very solid. If the first or last lines are empty of code, they get removed and the array is re-indexed. Simple.

With this, I have a really nicely workable solution for my code. Nice.

A Little Wrinkle in AJAX – Failed Requests

Wednesday, May 12th, 2010

AJAX.jpg

I was working on a few problems this morning and ran into one that I thought I'd solved with a simple binary flag. Well... let's do the set-up.

We have a web page with a JavaScript timer on it, and every so often, it fires off a request to the server to get new data. It's a poor man's push notification system, but it works - expect when it doesn't. Case in point: what happens when the requests are taking longer to service at the server than the timer's interval? Well, they still get sent, and they stack up at the server, and slow things down even more.

It's a mess. We need to have some idea that the request is in process, and if so, we don't want to send anther to the server. It'd just make things worse. So my first cut looked a lot like this:

  var requesting = false;
 
  function refreshData() {
    if (!requesting) {
      requesting = true;
      ...
    }
  }
 
  function handleResponse() {
    ...
    requesting = false;
  }

And while it's not a good design, the idea is simple - have a global variable that indicates if there's a pending request, and if so, then just skip the current request as the timer will issue another in just a little bit. Should work great... and it does - except when it doesn't.

Where it fails is in the failure on the server. If the request fails, then the handleResponse() code might not be called. Some cases it will and some it won't - it depends on the library doing the call. In my case, that's the Google Visualization Query, and that seems to be about 50-50, depending on the server's condition.

When it fails, the flag will never get reset and from that point on, no requests will get sent to the server. That's not good. What I needed was a much more secure method of knowing when it's busy, with the ability to detect when it had failed.

What I came up with was the idea of a simple timeout. That, coupled with a global timeout limit should be able to do the trick:

  var requestTimeout = null;
 
  function refreshData() {
    var now = new Date();
    if ((requestTimeout == null) || (now > requestTimeout)) {
      requestTimeout = now;
      requestTimeout.setSeconds(requestTimeout.getSeconds() + ServletTimeout);
      ...
    }
  }
 
  function handleResponse() {
    ...
    requestTimeout = null;
  }

In this code sample, we're going to get the current date/time and compare the timeout to that value. If we've passed the timeout, or there is none, then we can hit it again - setting the new timeout to the appropriate distance in the future.

In my tests, this works great with servers that die on the page, and it also doesn't allow too many requests to buffer up on the server. Hopefully, there aren't any other gotchas that I missed with this guy.

Google Chrome (dev) 5.0.396.0 is Out

Tuesday, May 11th, 2010

This morning I noticed that Google Chrome 5.0.396.0 (dev) was out and since I've been using Chrome for a week or so now, it's nice to stay up to date as this guy is evolving pretty darn fast. I can't say as I noticed anything bad, but I didn't notice anything, and that's good too.

The Coolest Language Ever Created

Monday, May 10th, 2010

I've been coding on and off in Objective-C for several years, and recently I've decided to get back into it to work on a little project that I've done several times over, but this time I just wanted to do it in Objective-C and on the Mac. It's been a while, and I wanted to make sure I still remembered all the neat things the platform had to offer.

Holy Cow! I had forgotten how elegant and beautiful Objective-C is and the Cocoa frameworks in particular are. The code is just so incredibly expressive and wonderful, it's hard to imagine why someone would purposefully choose to not code in this language.

Amazing.

Writing the C++ equivalent of the copy constructor is so wonderful:

- (id) copyWithZone:(NSZone*)zone
/*"
**   This is the standard copy method for the Legend so that we can make
**   clean copies without having to worry about all the details. It's a nice
**   deep copy, where the contents of the returned Legend are the same as
**   this instance's.
"*/
{
    // simply use the allocWithZone and populate it properly - easy
    return [[[Legend allocWithZone:zone] initWithMap:[self getMap]] autorelease];
}

where I had already created the setMap and getMap methods because they are the setters and getters for the class. It's so easy.

Yup, the more I code in ObjC, the more I realize I shouldn't be coding in anything else. It's just too much fun.

UPDATE: I read about headerDoc in the Xcode docs, and it seems to be the new AutoDoc documentation generator. So I changed the comments on my code to be more in-line with that, and as a benefit, they look more like my C++ comments, and that's a big win in my book:

/*!
 This is the standard copy method for the Legend so that we can make
 clean copies without having to worry about all the details. It's a nice
 deep copy, where the contents of the returned Legend are the same as
 this instance's.
 */
- (id) copyWithZone:(NSZone*)zone
{
    // simply use the allocWithZone and populate it properly - easy
    return [[[Legend allocWithZone:zone] initWithMap:[self getMap]] autorelease];
}

Bit of a Shocker – Tons of Broken Web Pages

Monday, May 10th, 2010

Crazy Lemon the Coder

Well, this morning I got a nice shocker - several of my web tools were broken in London, but working fine in Chicago. Since the server is in Chicago, I started looking at the network as the issue. Everything here worked fine, but nothing there was working. Well... the basic page was loading, but nothing else.

What a pain. I was able to see the server was up and returning data. I was able to make it work for me. But they were dead. So I asked them to have a look at the JavaScript console log in Chrome and let me know what it said.

The answer was simply astounding: it couldn't find the Java applet on the page.

Now a bit of background for this one. My web app needs to have some sense of authorization. It's got P/L data for the entire organization for a long time. There's a desire to have this somewhat controlled. OK, fine by me, corporations can choose to filter their data as they see fit. I just needed to put something into the JavaScript to make it possible to read the logged in user running the web browser (Chrome or Firefox).

I solved this a while ago, but recently my teammate Steve decided that I didn't need to have the applet tag visible, and so he changed all the applet tags from:

  <applet archive="firecache.jar" code="Bridge"
   height=10 width=10>

to:

  <applet archive="firecache.jar" code="Bridge"
   height=1 width=1 style="display: none;">

He said I had made a mistake in leaving it visible, and too big. I remember doing tests on it, and thought I had tested this, but hey... maybe it's an update to Chrome, and it's working better now.

Yeah... I should have trusted myself.

It's important to realize that I have a multi-level process of getting the authenticated username: first, we check for a cookie, if that's not there, then we hit the applet, and if that's not available, then we throw up a login panel. The problem was, with the applet not accessible, the JavaScript stopped at that step and we never say the login panel.

So I changed the code to ignore the cookie, and quickly reproduced the problem. Now I knew what it was. Then I changed the HTML on the page to:

  <applet archive="firecache.jar" code="Bridge"
   height=1 width=1>

leaving it "small" is OK with me, but I have to have it "visible" so that it's accessible to the JavaScript engine.

When I did that, I had the page working again. Whew! All I had to do now was to fix up the thirty-some other pages and check it all in and put it in UAT.

It didn't take too long, but it was a pain to look stupid to the London users, but I took the bullet for Steve. It is my web app, not his, and while he didn't test his changes, I didn't either, and that's my fault. I'll be a lot more careful about Steve's work in the future.

I do not like looking stupid to the London users.

Adobe Flash Player 10.1.53.38 (Release Candidate) is Out

Friday, May 7th, 2010

This morning I saw that the latest release candidate of Flash Player for Mac OS X was out, and with the recent announcements of the hardware-accelerated library from Apple, it's been a stated promise from Adobe that they will use this in the final release of the 10.1 Flash PLayer. If so, this may be the cut that includes it. The timing is right, which is just great.

So I'm hoping that soon we'll have a decent Flash Player that uses hardware acceleration on my laptop.

Transmit 4.0.2 is Out

Wednesday, May 5th, 2010

Transmit 4

As with all new, major releases, very soon after it's initial release, Transmit 4.0.2 is out with a lot of bug fixes and new little features. It's really nice to see the responsiveness to the user's issues.

I still need to enter in all my hosts to Transmit from Cyberduck. But I've at least got the biggies.

Google Chrome dev 5.0.375.29 is Out

Tuesday, May 4th, 2010

GoogleChrome.jpg

This morning I noticed that Google Chrome dev was updated to 5.0.375.29 and with it are a few more improvements in the V8 JavaScript engine and the typical stability and security fixes. I have to say, Chrome is getting to the point that it's supplanted Firefox as my backup browser. And when I say backup browser I really mean that it's my second browser that I always run with my hosting service pages always loaded - just in case. So you could think of it as my primary HostMonster browser.

It's fast, it's gotten rid of the problems with a page crashing taking down the entire browser... and the connectivity issues I noticed. It's solid, stable, and while it may not have all the bells and whistles of some browsers, or even the stability of Safari, it's good. Good enough for my second choice.

The Difference Between Average and Really Good (again)

Monday, May 3rd, 2010

Crazy Lemon the Coder

This morning I was pulling in code that had been checked in by one of the other developers in the group. Steve's code is, well... an interesting mix of optimistic code and a very obvious trial-and-error process. It's there, and it works, after a fashion, but even the Old Guard guy at The Shop called Steve's work "...slow and a little, you know, problematic." It's not that Steve isn't trying, he's working "hard enough" for The Shop, but had The Shop not had the "employment for life" plan, I'm guessing Steve would have been pushed out in one of the cuts.

Nice, but that's not really the issue - it's about making good, solid, reliable code in a short amount of time that is reasonably easy to maintain and has a minimal set of bugs that need to be fixed. It's about productivity, not popularity.

So today I knew I had to integrate some of Steve's code into the core of the web app I started and Steve's been adding pages to. I knew this because he asked me about it on Friday before I left - and I knew what to expect. I've had to do this a few times before.

When I got into the code, it was pretty much just what I expected - the basics were there, but a lot of the detail work was missing. For example, checking for nulls, putting in a new ivar's test in the Java equals() and hashCode() methods... things that aren't really killer bugs, but they could very well be a major pain in the rear trying to figure out if you didn't know that there were these weak points in the code.

So I fixed up all the problems so that the code looked like the rest of the code in the servlet, and helper class. I checked it in and sent Steve an email about the changes I'd made. What I didn't expect was Steve's response: mildly miffed.

You see, when I'd changed Steve's code for the helper class to check for the null on the new ivar, and changed:

  public class UserInfo extends Object {
    ...
    private String[]    _pages = new String[0];
    ...
  }

to:

  public class UserInfo extends Object {
    ...
    private String[]    _pages = null;
    ...
  }

and then added the tests in the methods to check for null - as it was always possible to have the user set a null in the setter, I had broken his page. His page didn't check for nulls returned from methods, and Steve's point was that he didn't like making methods that returned nulls.

I can appreciate that he has a style, while I'm struggling to see why he'd want to make code that left out such a beautifully expressive value like null, I can see that he likes to write code a certain way. Good for him. But this isn't his code. It's not my code. It's The Shop's code. And because of that, we need to make it better than it needs to be for our private, individual use. It's got to work when we get bad inputs, when we get bad method outputs. It's got to just plain work. Period.

This is one of those seminal differences between average developers and good developers. The god ones know that they aren't writing it for themselves. They are writing code that's as good as they can make it. They know this doesn't take that much more time - but the effect is dramatic. It's the details.

Why would the return value from the servlet break the page? It should at least gracefully degrade capabilities. You don't want to have a page bomb just because the server died. Have a nice error message and then let the user see what they had last.

It's stuff like this that makes me wish I were in a group of a few, very hard working, very good, developers. Yes, it's a lot more work per person, but you don't have to worry about this kind of thing. You can divide the work and just know that the pieces will fit together and work well when it's all brought together.

What amazes me is that management knows this too, but they are seemingly happier with the idea that they'll be banking their success on the 'average' and just hope they can deal with things as they come up. Still kind of amazing.

Getting Clojure Set Up for Snow Leopard

Friday, April 30th, 2010

Clojure.jpg

This morning I had time to spend a bit getting Clojure set up on my MacBook Pro. I have started reading the Pragmatic Programmer book Programming Clojure, and I wanted to be able to start playing with the examples in the book. So I did what any tech guy would do - I Googled to see if anyone had done this already. Simple.

I found this page where he installs just the required jars into ~/Library/Clojure, and after looking at the extent of the installs, it seemed reasonable to try this install method as opposed to what I might have normally done. I ended up getting version 1.1.0 of Clojure which was the latest release version on the site.

Personally, I'd have probably put the Clojure, JLine, and Clojure-contrib installs into /usr/local and then soft-linked them to their non-versioned names. From there, I'd have probably made a similar script, and put it in ~/bin - as he suggests linking to. It's not that big a difference what he's suggesting - it's just keeping it all in one place. Fair enough.

I will say that I did not need to build clojure-contrib as that's now available from Google Code. But other than that, the page was spot on.

I will say I'm stunned that there's no "exit" from the clojure.main run-loop. You have to type:

  user=> (System/exit 0)

to get out. Or, just hit Ctrl-D. This is even referenced in the book. Wild, but hey... that's what they wanted to do.

Now I can play with Clojure and see what all the hub-hub is about.