{ "metadata": { "name": "Ruby Notebook" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# This is an IPython notebook, backed by a ruby kernel.\n", "\n", "I wrote a kernel in Ruby that adheres to the [IPython](http://ipython.org/) messaging protocol. Then I modified IPython, with the help of minrk from #ipython, to instantiate my Ruby Kernel instead of its own Python kernel.\n", "\n", "The IPython KernelManager initializes the RubyKernel with popen, and from that point communication occurs over ZeroMQ, exactly as in IPython's kernel.\n", "\n", "Once that was done, it's easy to execute ruby against that kernel right in the browser." ] }, { "cell_type": "code", "collapsed": false, "input": [ "class Neat\n", " def eh?\n", " \"hell yes it is.\"\n", " end\n", "end\n", "\n", "Neat.new.eh?" ], "language": "ruby", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What does this give you?\n", "\n", "This gives us a very fancy web notebook interface for Ruby. It's a very good tool for programming presentations. Tom Brander's presentation to the BOSS meetup group made me realize exactly how far IPython had come since I last saw it, and I knew I wanted to have it for ruby.\n", "\n", "It's basically an in-browser REPL loop, with some extra goodies." ] }, { "cell_type": "code", "collapsed": false, "input": [ "class ThatsPrettyCool\n", " def how_does_it_work?\n", " puts \"I'm glad you asked!\"\n", " :see_below\n", " end\n", "end\n", "\n", "ThatsPrettyCool.new.how_does_it_work?" ], "language": "ruby", "metadata": {}, "outputs": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Here's how it works\n", "\n", "Each notebook has its own kernel. When you open a notebook in the web interface, a kernel is started in the background by the IPython webserver. A websocket is then used to connect the frontend directly to the kernel, more or less, and they pass messages back and forth.\n", "\n", "All of the messages are in a JSON format. The actual information passed over the wire between the web server and the kernel is a little different, but it basically just includes some session/auth information, and then the components of the message serialized, too be unserialized on the Kernel into the full json message again.\n", "\n", "### What does a message look like?\n", "\n", "A given JSON message looks like this:\n", "\n", " {\"header\"=>\n", " {\"username\"=>\"username\",\n", " \"msg_id\"=>\"38C1E3299BB14F7C99D95504CEAE4856\",\n", " \"msg_type\"=>\"execute_request\",\n", " \"session\"=>\"BAC5EA31BC6F4C1D888DD5F8C46B6F9D\"},\n", " \"msg_id\"=>\"msg_id\",\n", " \"msg_type\"=>\"msg_type\",\n", " \"parent_header\"=>{},\n", " \"content\"=>\n", " {\"user_variables\"=>[],\n", " \"allow_stdin\"=>false,\n", " \"code\"=>\n", " \"class ThatsPrettyCool\\n def how_does_it_work?\\n puts \\\"I'm glad you asked!\\\"\\n end\\nend\\n\\nThatsPrettyCool.new.how_does_it_work?\",\n", " \"silent\"=>false,\n", " \"user_expressions\"=>{}},\n", " \"buffers\"=>[]}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### What remains to be done for this to be 'complete'?\n", "\n", "- Right now, I'm not passing back the 'return value of the last expression' like you'd expect a proper REPL to do. I'm not exactly sure how to get the analog of python's sys.displayhook working, but I welcome anyone to teach me how it's done :) I can probably figure it out from the pry source.\n", "- backtraces are a little bit wonky right now and don't give you the proper backtrace into the executed code, but rather into the Kernel's source where the eval loop runs...not very helpful.\n", "- There aren't any tests.\n", "- It would be nice to support the fancy IPython graph and html-table gooies, I'll look into that.\n", "- IPython supports tab-completion in the browser REPL, but my kernel doesn't know how to respond to those messages.\n", "- There are some other message types I've not yet implemented, but I don't really see the problem at present :)" ] } ], "metadata": {} } ] }