10 September, 2011

Emacs: Mark Ring

Editing existing code is rarely a sequential task, and emacs has a really neat feature that helps you out with this; the mark ring. Large navigation commands ( M-< , M-> , C-r , C-s, C-v , M-v , etc.. ) all push the position prior to the movement onto the mark ring of the buffer so you can easily get back to where you were. C-u U-SPC pops off the last mark on the ring and takes you to it.

So for example I am editing this test case:
  sub test_pop : Test(4) {
my $array = shift->{test_array};
is(pop @$array, 2, 'pop = 2');
is(pop @$array, 1, 'pop = 1');
is_deeply($array, [], 'array empty');
is(pop @$array, undef, 'pop = undef');
};
And I need to add a 5th test case at the end of the test sub. After adding the line I need to edit the number of tests to 5 so I type:
C-r Test RET          -- Reverse search back to Test
M-f M-f Backspace 5 -- Forward 2 words, Replace 4 for 5
C-u C-SPC -- Back to where we were.
And then I'm back where I was. Free to add another test or fix the added test when it doesn't quite work. ;)

While this example is a touch contrived, for bigger jumps ( e.g jumping to the top of a file ) it becomes really useful.

For added coolness, turns out there is also a global mark ring, so you can jump between all the buffers that you are editing as well with C-x C-SPC. Super neat.

Vim also has the concept of marks, called a tagstack; though I don't know if they are as nicely build into all the navigation commands like they are here. Nothing that a bit of vim script wouldn't fix either way.

For more information:
http://www.gnu.org/s/libtool/manual/emacs/Mark-Ring.html
http://www.gnu.org/s/libtool/manual/emacs/Global-Mark-Ring.html#Global-Mark-Ring

11 August, 2010

Scalatra + Embedded Jetty

Lets face it; it is extraordinarily simple to deploy a quick & simple CGI script in languages like Perl or Python. It has often left me a very sad, sitting in Scala/Java land while admiring the beautifully simplistic and lightweight tools that my neighbours all have.

Sure, things like Lift & Grails make building big applications very very nice, but when you just need a simple form and touch of backend processing, I find that it is often harder than it needs to be. (Although if you have other suggestions I would love to be proven wrong here)

Came across a neat Scala library today called Scalatra that I believe fills this void. Essentially it is an abstraction over plain old java servlets to make REST style path parsing, form processing and response generation very very easy. It is based on a ruby library called Sinatra.

Take a look at this simple code that takes in two files and diffs them, outputting the diff output in a nice green (addition) and red+strikeout (removes).

package com.benkolera.scalatradiff

import org.scalatra._
import org.scalatra.fileupload._
import org.apache.commons.fileupload.FileItem
import ScalaDiff._

class DiffServlet extends ScalatraServlet with FileUploadSupport {

before {
contentType = "text/html"
}

get("/") {
<form method="post" enctype="multipart/form-data">
<p>Old File: <input type="file" name="oldFile" /></p>
<p>New File: <input type="file" name="newFile" /></p>
<input type="submit" />
</form>
}

post("/") {
val oldFile = fileParams("oldFile").getString
val newFile = fileParams("newFile").getString

<div>
{
diff(oldFile,newFile).map{
case Insert(t) => mkDiffSpan(t=t,colour="green")
case Delete(t) => mkDiffSpan(t=t,colour="red",strike=true)
case Equal(t) => mkDiffSpan(t=t)
}
}
</div>
}

def mkDiffSpan(
t: String,
colour: String = "black",
strike: Boolean = false
) = {
val style = "white-space:pre;color:"+colour + (
if (strike) ";text-decoration: line-through" else ""
)
<span style={style}>{t}</span>
}
}

There isn't much to say about the code. It is all nice, simple and easy to follow. Scala's inbuilt XML syntax makes things even easier by removing your need to bugger around with Strings. It also adds the neat bonus of validating that your XTHML is well formed upon code compile.

Also take good notice of those beautiful named and default parameters being used in mkDiffSpan. Perhaps one of the most simple additions to Scala in 2.8, I find that they clean up my code quite a lot. What you see there is cleaner (to me, at least) than how I would do it in 2.7.7. IMHO, the 2.7.7 version isn't that bad; it is just that the named and defaults is even better.

This would be my 2.7.7 version:


<div>
{
diff(oldFile,newFile).map{
case Insert(t) => mkDiffSpan(t,Some("green"),false)
case Delete(t) => mkDiffSpan(t,Some("red"),true)
case Equal(t) => mkDiffSpan(t,None,false)
}
}
</div>
}

def mkDiffSpan(
t: String,
colour: Option[String],
strike: Boolean
) = {
val col = colour.getOrElse("black")

val style = "white-space:pre;color:"+col + (
if (strike) ";text-decoration: line-through" else ""
)
<span style={style}>{t}</span>
}


All the code does is presents a simple form asking for two files. Upon submitting these files it diffs them and produces something that looks like this:



To play around, I also embedded jetty inside the code so that the application is run as a standalone jar rather than a war that is deployed somewhere. While this is nice and easy, it is probably of little help to the kind of applications you'll make with Scalatra. After all, your app will usually end up on a server somewhere and needs to be daemonised in some way. You can install and use jsvc, but it's probably just as easy to install jetty so you don't really win anything there. Food for thought though; the jar may be a better alternative if you're just running the thing locally (using it for a mock REST API for testing, tailing local files, etc) and don't need to run it in a hands off fashion.

Here is the code. Incredibly simple stuff:

package com.benkolera.scalatradiff

import org.mortbay.jetty.Server
import org.mortbay.jetty.servlet.{Context,ServletHolder}

object DiffApp {

def main(args: Array[String]) = {
val port =
args match {
case Array(port) => Some(port.toInt)
case _ => None
}

val server = new Server(port.getOrElse(8080))
val root = new Context(server,"/",Context.SESSIONS)
root.addServlet(new ServletHolder(new DiffServlet()), "/*")
server.start()
}
}

You can checkout the full code here if you desire:

http://github.com/benkolera/scalatra-diff