<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Random Hacks: Real-time text annotation with Google Wave</title>
    <link>http://www.randomhacks.net/articles/2009/09/01/real-time-text-annotation-with-google-wave</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Technology and Other Fun Stuff</description>
    <item>
      <title>"Real-time text annotation with Google Wave" by Spyros</title>
      <description>&lt;p&gt;Google Wave will probably be the tsunami of nowadays communications online. Let&amp;#8217;s see what it will introduce the world to.&lt;/p&gt;</description>
      <pubDate>Tue, 06 Oct 2009 02:56:33 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:d07a9c8b-e199-4945-adc4-e99152049034</guid>
      <link>http://www.randomhacks.net/articles/2009/09/01/real-time-text-annotation-with-google-wave#comment-733</link>
    </item>
    <item>
      <title>Real-time text annotation with Google Wave</title>
      <description>&lt;p&gt;If you haven&amp;#8217;t seen Google Wave yet, you may want to watch this &lt;a href="http://www.youtube.com/watch?v=Itc4253kjhw"&gt;10-minute demo&lt;/a&gt; or take a look at the &lt;a href="http://wave.google.com/"&gt;official Wave site&lt;/a&gt;. Otherwise, this code won&amp;#8217;t make a lot of sense. :-)&lt;/p&gt;

&lt;p&gt;&lt;img style="border: 1px solid grey; margin-left: 50px" src="/files/buglinky-screenshot-large.png" width="300" height="401" /&gt;&lt;/p&gt;

&lt;p style="margin-left: 50px"&gt;&lt;b&gt;Figure:&lt;/b&gt; Real-time text annotation with Google Wave.&lt;/p&gt;

&lt;p&gt;I received my developer sandbox account last week, and spent some time experimenting with Wave. So far, it seems like a really sweet tool—it&amp;#8217;s fast (if you stay away from waves with 200+ messages), convenient, and fun to use. Wave isn&amp;#8217;t yet ready for prime time, but it could be fairly solid in six months and widely deployed by this time next year.&lt;/p&gt;

&lt;p&gt;After using Wave for less than a week, I &lt;em&gt;really&lt;/em&gt; wish my friends and coworkers had accounts. This is a good sign.&lt;/p&gt;

&lt;p&gt;Google has already released about 40,000 lines of Wave code as open source, and there&amp;#8217;s apparently quite a bit more in the pipeline.&lt;/p&gt;

&lt;h3&gt;Extending wave with gadgets and robots&lt;/h3&gt;

&lt;p&gt;Wave supports two major kinds of extensions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Gadgets&lt;/em&gt; are interactive content that users can embed in a wave. In the &lt;a href="http://www.youtube.com/watch?v=Itc4253kjhw"&gt;demo&lt;/a&gt;, Google shows off a map gadget, a chess game, a handy &amp;#8220;Yes/No/Maybe&amp;#8221; poll, and many others.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Robots&lt;/em&gt; are essentially a cross between IRC bots, text editor extensions, and web form processors. They can do anything another human could do, in real-time, as you type. They can also create and respond to HTML-style form elements.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far, I&amp;#8217;ve tried writing a robot in Java. (Why Java? Wave is built using &lt;a href="http://code.google.com/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt;, which compiles Java to JavaScript. So right now, the Java libraries are slightly more mature than the Python libraries.)&lt;/p&gt;

&lt;h3&gt;buglinky: Link to bugs as you type&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://wave-samples-gallery.appspot.com/about_app?app_id=27027"&gt;buglinky&lt;/a&gt; reads your text as you type, and automatically links strings of the form &amp;#8220;bug #123&amp;#8221; to a bug tracker of your choice. It can also detect raw bug tracker URLs and replace them with the corresponding text.&lt;/p&gt;

&lt;p&gt;Internally, buglinky is built around a custom &lt;code&gt;BlipProcessor&lt;/code&gt; class that does all the heavy lifting. All I need to do is hook up my individual processors and run them:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;ArrayList&amp;lt;BlipProcessor&amp;gt; processors =
  new ArrayList&amp;lt;BlipProcessor&amp;gt;();
processors.add(new BugUrlReplacer(BUG_URL));
processors.add(new BugNumberLinker(BUG_URL));
BlipProcessor.applyProcessorsToChangedBlips(
  processors, bundle, BOT_ADDRESS);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;#8217;s the code which links &amp;#8220;bug #123&amp;#8221; to the bug tracker:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;class BugNumberLinker extends BlipProcessor {
  // ...constructor sets up bugUrl...

  protected String getPattern() {
    return &amp;quot;(?:[Bb]ug|[Ii]ssue|[Tt]icket|[Cc]ase) \#?(\\d+)&amp;quot;;
  }

  protected void processMatch(
      TextView doc, Range range, Matcher match) {
    annotate(doc, range, &amp;quot;link/manual&amp;quot;,
      bugUrl.concat(match.group(1)));
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Replacing URLs with plain text is similarly easy:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;class BugUrlReplacer extends BlipProcessor {
  // ...constructor sets up bugUrl...

  protected String getPattern() {
    return Pattern.quote(bugUrl) + &amp;quot;(\\d+)&amp;quot;;
  }

  protected void processMatch(
      TextView doc, Range range, Matcher match) {
    replace(doc, range, &amp;quot;issue #&amp;quot; + match.group(1));
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you have a sandbox account, you can &lt;a href="https://wave.google.com/a/wavesandbox.com/#restored:wave:wavesandbox.com!w%252B06QQ6YMY%2525C.2"&gt;experiment with buglinky&lt;/a&gt;. You can also &lt;a href="http://github.com/emk/buglinky/tree/master"&gt;download the source code for buglinky from github&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Future directions&lt;/h3&gt;

&lt;p&gt;Obviously, this will look much better once somebody has the time to port it to JRuby. How about something like this?&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;match&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="comment"&gt;#{Regexp.escape(bugUrl)}(\\d+)/ do&lt;/span&gt;
  &lt;span class="ident"&gt;replace&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;issue ##&lt;span class="expr"&gt;#{$1}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;match&lt;/span&gt; &lt;span class="punct"&gt;/(&lt;/span&gt;&lt;span class="char"&gt;?:&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="constant"&gt;Bb&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;span class="ident"&gt;ug&lt;/span&gt;&lt;span class="punct"&gt;|[&lt;/span&gt;&lt;span class="constant"&gt;Ii&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;span class="ident"&gt;ssue&lt;/span&gt;&lt;span class="punct"&gt;|[&lt;/span&gt;&lt;span class="constant"&gt;Tt&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;span class="ident"&gt;icket&lt;/span&gt;&lt;span class="punct"&gt;|[&lt;/span&gt;&lt;span class="constant"&gt;Cc&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;&lt;span class="ident"&gt;ase&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; \&lt;span class="comment"&gt;#?(\\d+)/ do&lt;/span&gt;
  &lt;span class="ident"&gt;link&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;bug_url&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="global"&gt;$1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Additionally, the current robot API relies on a JSON-RPC-based proxy between the Wave server and a robot. This is fine for processing entire waves in a single pass, but it uses too much bandwidth for real-time text processing. So I would love to be able to run this code inside a real wave server. But that will have to wait until the federation protocol is turned on.&lt;/p&gt;</description>
      <pubDate>Tue, 01 Sep 2009 13:06:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:fb7773df-9b8b-4db5-9098-217d9c628bf8</guid>
      <author>Eric Kidd</author>
      <link>http://www.randomhacks.net/articles/2009/09/01/real-time-text-annotation-with-google-wave</link>
      <category>Wave</category>
      <category>Java</category>
      <trackback:ping>http://www.randomhacks.net/articles/trackback/710</trackback:ping>
    </item>
  </channel>
</rss>

