2008-08-23

Syntax Highlighting on Blogger

You may have noticed that my code blocks are suddenly syntax-highlighted. You might think a tech-oriented company like Google would have included something like this by default, but you'd be wrong.

My new syntax highlighting comes courtesy of highlight.js, which is great, although it does have some holes in the English documentation. Unfortunately, I couldn't find any place it was being hosted for free, so I needed to set up a place of my own from which to serve it. Enter Google App Engine.

App Engine is Google's entry into the cloud computing space; if you write your application according to their guidelines, Google will run it on their infrastructure. As such, it is massive overkill for serving up static files, but it's free and it has good reporting tools. So I followed the "Hello, World!" documentation, added the files for highlight.js, then modified my app.yaml to add a handler for serving static files.


- url: /
 static_dir: highlight

Note that this conflicts with the handler from "Hello, World!"; since I didn't want to serve up "Hello, World!" anyway, I just deleted the other handler.

According to the documentation for highlight.js, all you should have to do now is add one simple block of Javascript:


<script src="$PATH_TO_HOSTED_JS" type="text/javascript"></script>
<script type="text/javascript">
 hljs.initHighlightingOnLoad();
</script>

This is technically accurate: this will cause the markup to be modified to support syntax highlighting. That's not enough for the highlighting to take place, however; you still need to bring in the CSS for the highlighting style you want to use (my two favorites are Sunburst and IDEA).


<link href="$PATH_TO_HOSTED_CSS" rel="stylesheet"/>

On Blogger, the best place to put this code is in the raw HTML for your template; that way you don't have to remember to include it in individual posts that will have code blocks. One final note: your code blocks have to be marked up by nesting a code tag inside a pre tag—if you've done something silly like nesting a pre tag inside a code tag, it won't work. Here's an example of the proper style:


<pre><code>
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
print "Hello, World!"
</code></pre>

Back to flipping out...

2008-08-12

Grails, The Acegi Plugin, and HTTP Basic

If you've heard of Rails but can't use it for whatever reason—my reason was an incompatible legacy schema—maybe Grails will work for you. Unashamedly inspired by Rails, Grails is written in Groovy and aims to provide the convenience of Rails while adding configurability and leveraging the power of the massive number of libraries written in Java and the other JVM languages (including Ruby, thanks to projects like JRuby). Between what comes with Grails out of the box and the available plugins, it can really take a big chunk of the grunt-work out of webapp development.

One of my favorite plugins so far is the Acegi plugin. It bolts Spring Security onto your Grails project and provides for configuration using the concise Groovy DSL for Spring. Just type grails install-plugin acegi to install the plugin, and start leveraging Spring Security.

One of the nice things about Spring Security is its built-in support for HTTP Basic authentication. Just change basicProcessingFilter from false to true in your SecurityConfig.groovy file and your application will now look for user credentials in the HTTP Authorization header. The only problem is that if no Authorization is sent, the server sends a 302 Found response to send the client to a login page. To be fully compliant with the HTTP Basic spec, it should be sending a 401 Unauthorized response with details on the supported authentication mechanisms. If you've read the documentation for the HttpBasicProcessingFilter—which you enabled by setting basicProcessingFilter = true earlier—you might expect Grails to be using HttpBasicProcessingFilterEntryPoint, but you'd be wrong. In an effort to be user-friendly for human users, it is instead using an AuthenticationEntryPoint that sends the 302. To change to the strict HTTP Basic mechanism, you'll need to rewire the AuthenticationEntryPoint Grails is using by adding the following to your resources.groovy file:


authenticationEntryPoint(org.springframework.security.ui.basicauth.BasicProcessingFilterEntryPoint) {
    realmName = 'YOUR REALM GOES HERE'
}

Back to flipping out….

2008-08-10

Exercises from Section 1.2 of SICP

Here's a quick update from my ongoing study of SICP.

Exercise 1.9

I didn't have access to a scanner to show the results of my expansion, but my answer to the recursive or iterative question was: recursive. The inc function in the definition of + is deferred until the recursive call to + is complete, so the function has a linearly recursive shape.

Exercise 1.10

  • (A (1 10))1024
  • (A (2 4))65536
  • (A (3 3))65536
  • (define (f n) (A 0 n))2n
  • (define (g n) (A 1 n))2n
  • (define (g n) (A 2 n))22n

Exercise 1.11

Recursive

(define (foo n)
  (cond ((< n 3) n)
        (else (+ (foo (- n 1)) (* 2 (foo (- n 2))) (* 3 (foo (- n 3)))))))
Iterative

There were a few false starts, but after Eli Bendersky's tip about solving the problem using a for loop, it all began to fall into place.

for Loop

function fooFor(n) {
    var a = 2;
    var b = 1;
    var c = 0;
    var result = n;
    for (i = 3; i <= n; i++) {
        result = a + 2*b + 3*c;
        c = b;
        b = a;
        a = result;
    }
    return result;
}
Tail-Recursion

(define (bar n)
  (cond ((< n 3) n)
        (else (bar-iter 2 1 0 n))))

(define (bar-iter a b c count)
  (cond ((= count 2) a)
        (else (bar-iter (+ a (* 2 b) (* 3 c)) a b (- count 1)))))

Back to flipping out…

2008-08-02

cd maven2 && mvn archetype:create fail-whale

I like the premise behind Maven, I really do. In the real world, though, Maven is an attractive nuisance: it lures developers in with its promises of an easier, consistent build process and quality project documentation, then ambushes them with constant breakage.

My latest brush with Maven breakage came this weekend when I tried to use the Archetype plugin. The archetype plugin creates a new project from an existing template. Typical archetypes do things like create the necessary directory structure and download dependencies, and some go as far as creating source code for a functional skeleton, e.g., the AppFuse Archetypes.

Sounds great, right? Well, it would be if it worked. Instead, when I tried to use the archetype plugin, it started downloading dependencies and broke. It turns out, they released my version of the plugin with dependencies that don't exist in the central repositories (specifically, commons-collections version 3.2 and commons-lang version 2.1). This is fairly widespread among third-party maven projects, but I didn't expect it from something as central as the archetype plugin.

I was irritated, but I wasn't ready to give up. Luckily for me (I thought), the error message suggested a workaround: manual installation of the dependency into your local repository. It even provided instructions: mvn install:install-file -DgroupId=commons-lang -DartifactId=commons-lang -Dversion=2.1 -Dpackaging=jar -Dfile=/path/to/file and mvn install:install-file -DgroupId=commons-collections -DartifactId=commons-collections -Dversion=3.2 -Dpackaging=jar -Dfile=/path/to/file. The straw that programmer's back came when I tried to follow those directions.

[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error installing artifact 'commons-collections:commons-collections:jar': Error installing artifact: /Users/hankgay/.m2/repository/commons-collections/commons-collections/3.2/commons-collections-3.2.jar (No such file or directory)

At this point, I didn't have the energy to dig any deeper, but that error message is monumentally frustrating. Of course /Users/hankgay/.m2/repository/commons-collections/commons-collections/3.2/commons-collections-3.2.jar doesn't exist; the whole point of the command was to create it!

The moral of the story? Maven is the sort of tool that only a masochist could love.

Update

I really wanted to use the maven-archetype-webapp, so I started futzing about with those dependencies again. Eventually I fixed the problem by manually mirroring the proper versions from ibiblio. I hope the Maven team works on this soon, because these are some pretty absurd lengths to go to make something work that comes in the box.

Back to flippin' out…