Saturday, November 1, 2014

Pigshell - A peek at the inside

A shell for the web

Terminal windows are a developer's best friend. But sometimes having to render everything in a grid of 40x60 characters feels just a little bit lacking in expressive power in a world of retina screens. Sure, like most number crunchers I have a set of small scripts that take data from a terminal window and display them in a browser, adhering to that age old adage "Look at your data or get junk out of your analysis." but I recently bumped into a shell that lives right in a web browser. It takes cat img.jpg to a whole new level! It's immature, it's new, it clearly needs some serious thought about the fundamentals, but I do believe that this is the future.
You can start playing with the shell right now at http://pigshell.com. But the developer in you will want to understand how it works and build more tools. There aren't really any guides out there right now on how to hack pigshell so here are my notes. Just to be clear, there are plenty of documents on how to use ps and write shell scripts for it, but not for how to dip under the covers. Today I made the simplest builtin command you could possibly imagine and added it to my local build of pigshell:

Initial installation:

The developer's notes for this are pretty accurate. I recorded the installation commands that I ran for Debian here. The only thing to note is that at the moment the domain name is hardwired in some places in the code and so the easiest way of setting up your own build is to point pigshell.com at your own server in your /etc/hosts file. Hopefully that will change soon!

Making a builtin

Builtin commands are those such as cd and ls that come with pigshell itself. Their code is in src/cmd/

Destructive testing:

Go on, break the code! In src/cmd/ls.js add a call to the non-existent but highly effective function called boom:
function Ls(opts) {
    var self = this;
    boom;
    ...
Build by running make and then, in pigshell, try the newly knobbled ls:
pig:/$ ls facebook
Exception: Uncaught ReferenceError: boom is not defined
OK, now you know your code is being used! Now fix it! Bad boy.
git checkout src/cmd/ls.js

Registering a command

Here is a minimal command that does nothing:

function Jline(opts) {
    // your code will go here
}
Command.register("jline", Jline);

If you put that in src/cmd/jline.js and build you should be able to run jline on the command line:

pig:/$ jline
pig:/$

If you don't:
  • Did you run make?
  • Look for your function in the newly compiled file pigshell.js.
  • Refresh the browser. I haven't needed to but it might help!

Hello Web

To print you need to access the API. And no, console.log won't do that for you! There is an HTML div that you can populate with, say, an image of a cute little piglet:

function Jline(opts) {
    var self = this;
    Jline.base.call(self, opts);
}
inherit(Jline, Command);

Jline.prototype.next = check_next(function(opts, cb) {
    var self = this
      , term = opts.term
      , tdiv = term.div;
    $('<img src="images/pigshell-logo-320x240.png" width="100px" />').appendTo(tdiv);
    $('<span>Doodlebug</span>').appendTo(tdiv);
    self.exit(0);
});

Command.register("jline", Jline);


And bingo:


Much as I love ASCII art that's some cool pig.

No comments:

Post a Comment