February 2008 Archives

In reply to Marty's Haiku: Winter Advice

| No Comments | No TrackBacks
Marty is pretty awesome to make this short Haiku: Winter Advice
お勧めだ
黄色な雪を
食べないで

(Somehow his blog entry text is all garbled but I can read it fine in its RSS
feed. So I just quote his text in here.)
It never snowed in my place, but there are just about 10 families have *that dog* as their pet in my neighborhood. So I just made this make short haiku, in replay to Marty's:

黒と白
エスキモーから
活発な犬

It's not so brilliant as Marty's. You're the man of Haiku, Marty.

For anyone who feels very confused about what the hack is these all about, go watch this youtube video.

Labels: ,

One way to use Markdown in Emacs.

| No Comments | No TrackBacks

I recently use markdown to write my blog post in Emacs, and convert it to HTML with the official markdown.pl perl script, then paste it to blogger.

First, grab the markdown.pl from Markdown website and put that in one of your $PATH. I put it in $HOME/bin.

Then, start from scratch, type your post in using Markdown. When your're done, hit

  1. C-x h (Select whole buffer)
  2. M-| (Run shell command on region)
  3. Type "markdown.pl" in the minibuffer prompt

Then copy the HTML out of the shell command output buffer. done.

Labels: ,

Decide if a sub calling from current package

| No Comments | No TrackBacks

When you're writing a Perl module, this subroutine can test if your sub is called from current package:

sub __in_current_package__ {
    my $level = 0;
    my @c = caller(++$level);
    while ( @c > 0 ) {
        return 1 if defined $c[0] && $c[0] eq __PACKAGE__;
        @c = caller(++$level);
    }
    return 0;
}

How you use it:

sub do_something {
    if (__in_current_package__) {
        return &do_this;
    }
    return &do_that;
}

Labels:

link to somewhere, the web forms

| No Comments | No TrackBacks

Rails has this "link_to" methods with pretty good semantic:

link_to "Gugod's website", :url => "http://gugod.org/"

Pretty much just like speaking English. In Jifty, it has several different varints. One is "hyperlink" if you use Template::Declare:

hyperlink(
    label => "Gugod's website",
    url   => "http://gugod.org"
);

In plain HTML, that's

<a href="http://gugod.org/">Gugod's website</a>

In Socialtext wikitext, that's:


   "Gugod's website"<http://gugod.org>

In Markdown, that's:


   [Gugod's website](http://gugod.org)

Each one make sense here. The frst two are designed to be written inside application's templates, the last two are designed to be written as application content. HTML are somewhere in the middle. It can be written as part of your templates, or part of your application content.

Maintianing templates of the application are usually programmer's job. Sometimes templates becomes a managable content such that users have to maintain them too. Like blogger's template, or bricolage's tempate.

Subjectively I vote for Socialtext wikitext syntax if I am a heavy content provider. For several reasons:

Backward compatible punctuations. The double quotes natually emphasizes the link label to mean: "Something different in here".

Direct. Human readers immediately catches the first part, which is the link label. Can ignore the rest of text between < and > since those characters are not likely helpful without a proper reader. Comparing this:

You must visit "Gugod's website"<http://gugod.org> and donate him.

with this:

You must visit <a href="http://gugod.org/">Gugod's website</a> and donate him.

The second one makes me stop breathing for 1.74 seconds in the middle so I can read the whole sentence. (I voicelessly read text in my head, it's a bad habbit that I have been trying to fix for 20 years since I was awared of this problem.)

The same semantic looks ok in Markdown:

You must visit [Gugod's website](http://gugod.org) and donate him.

It looks even better in Markdown with another type of syntax:

You must visit [Gugod's website][1] and donate him.

[1]: http://gugod.org

Which makes the whole article looks like a research paper with whole bunch of citation links afterwards. It's either good or bad.

The Template::Declare way to do this is quite said:

outs_raw("You must visit ");
hyperlink(
    label => "Gugod's website",
    url   => "http://gugod.org"
);
outs_raw(" and donate him.");

I'm almost out of oxygen and can't get any high. This snippet is too heavy for what it does. A sprintf-like way for these inline-level elements can work better:

outs_raw + sprintf(
    "You must visit %s and donate him",
    hyperlink(....)
)

But this doesn't work like what you'd expect due to the design of Template::Declare, another "inconvienent truth."

I feel it much lighter to be able to use just "..."<...> to represent a simple hyperlink.

But that raises a very interesting issue for framework designers: Why should this optimized to let developer put more literal links in view code ? I would also vote against for over-optimizing these things that you don't really need.

Or I would just delegate it to other formatters for such purposes, say, having a "wikitext" helper in Template::Declare:

div {
  wikiext qq{
    You must visit "Gugod's website"<http://gugod.org> and donate him.
  }
};

Or a "markdown" helper:

div {
  markdown qq{
    You must visit [Gugod's website](http://gugod.org) and donate him.
  }
};

This reminds me of my previous work, Template-Provider-Markdown, which allows you use Markdown to replace HTML in your TT2 templates.

If I have to generate a tangent link then it's a totally different story. That's something no need to be optimized. (Maybe)

Socialtext wikitext syntax is very close to be a valid piece of Perl6:

"Gugod's website"<http://gugod.org>

"" forms a string value, and <> means getting a thing from a hash with the hash key barely given inside. So that means: getting the value associated with "http://gugod.org/" from the Hash represented by "Gugod's website". Syntax error.

But there might be a chance to make this work for Perl6, since the form

$obj.<>

is a method-like postcircumfixes, it might be able to be overloaded for Strings. In fact, if this is true, the original dot-less form might just work too. That would make perl6 the best langauge to design templating system for both appllication templates and application content -- just overload a bunch of Perl6 operators such that our content can be a form of valid subset Perl6.

Labels: , , , , ,

We’ve recently working with Jifty team for a big internal update. Jifty team has been using Selenium as one of their testing tools, specifically, it’s Selenium-RC. In short, one current test application is first started and ask selenium server to connect to its URL and follow by a sequences of instructions to test the framework itself. Since this is a web application framework, it’s good and important to know a feature will be working on all browsers. Therefore, we need to write tests and run the tests on different browsers.

It’s simple to run those tests, just do somethingl like:

cd jifty/
prove -lr t/TestApp-*/

Conventionally t/TestApp-* contains Jifty applications that are specially designed for running tests. Their sub-tests lives under t/TestApp-*/t/. For instance, our recent work goes under t/TestApp-JiftyJS/t/. If you run the prove command above, then you’ll see your Firefox browser pops up and start doing something. That means it’s doing it’s job just well. Of course you’ll need to install a bunches of Perl modules including Alien::SeleniumRC and WWW::Selenium. And your OS needs to be able to run Java. I’m a Mac user, so this all works for me.

Then I need to run these tests on Windows browsers to see if they all works. What should I do ? First way, I can install whole Jifty suit on my Windows box, also install Java for running selenium-rc. Sounds simple, but it’ll take too much windows-fu from me. I might gain a lots of experiences value, but 85% of my health points will be lost. Not a good choice.

Give it a second thought, it’s mindless to prepare multiple instance of Jifty environments just to run tests on different browsers.

Here’s what I’ve done on my windows box (it’s really a virtual machine, but that makes no difference at all):

  1. Install Java Runtime
  2. Download Selenium-RC

  3. Download Putty, the greatest windows SSH client with worst user experiences. No offense, but I really have to complain that it’s setting screen works against my intuition.

  4. Run the selenium-server.jar in the downloaded selenium-rc with this (do this in your CMD window):

    • java -jar selenium-server.jar


  5. Use putty to connect to one of your server where Jifty are all setup. Let’s say it’s example.com. Also open a tunnel to forward port 4444 on remote to port 4444 on localhost.

    • Note: With UNIX commands it’s this: ssh -R4444:localhost:4444 example.com

    • Putty users can see the screenshot down below to find where to open that tunnel


  6. Setup these environment variables on your remote host, they’ll be recognized by Jifty::Test::WWW::Selenium modules to do the right thing :



export SELENIUM_RC_SERVER=localhost:4444
export SELENIUM_RC_TEST_AGAINST=example.com
export SELENIUM_RC_BROWSER='*iexplore'

Now run the prove command on example.com, you should see your local Internet Explorer pops up and do something.

The concept here is to only run selenium-server on Windows, but running the Jifty test applications on somewhere else. The caveat is that these two machines need to be connected. VPN is fine. The SELENIUM_RC_TEST_AGAINST variable is set to the remote host hostname or IP address on remote. Because it’s telling selenium server where the Jifty testing application is.

With this technique, I can use my Mac to run the selenium server, and ssh into that example.com with ssh -R5555:localhost:4444, change SELENIUM_RC_SERVER to localhost:5555. Then I can test Jifty with my Mac browsers, without the need to setup another Jifty environment again.

If I’m not running my Windows in a virtual machine, but on a real machine where it has it’s own public IP, or it’s a private IP but it’s accessible from example.com. Then I don’t even need to use Putty to open up a ssh tunnel. I’ll just configure SELENIUM_RC_SERVER to it’s IP, like 192.168.10.123:4444. And directly run the prove on example.com, it’ll just work.

PS: This post is cross-posted to Handlino Blog

Labels: , ,

JavaScript::Writer + Template::Declare

| No Comments | No TrackBacks
I spent last 24 hours figured out a nice way to play JavaScript::Writer with Template::Declare. It was super neat. Download the this zip and check out the source code. It depends on an future version of JavaScript::Writer module that had not been released to CPAN yet, so it won't work for you. But you can see the source code in lib/JT/View.pm, line 141:
  link_to(
      "Hello",
      href => "http://google.com",
      onclick => ajax_replace( "#area", "data/hello.html" )
  );

And line 109, for the definition of ajax_replace:

  sub ajax_replace {
      my ( $target, $uri ) = @_;
      return sub {
          jQuery("#loading")->fadeIn(
              sub {
                  jQuery("#area")->load($uri)->show(
                      sub {
                          jQuery("#loading")->fadeOut();
                      }
                  );
              }
          );
          js->append("return false;");
      };
  }
It returns a Perl sub, and eventually converted to a Javascript function that work as the onclick handler. One nice feature is, although the A tag and onclick handlers are put together in Perl code, they are seperated in HTML code. All generated javascript are put to the end of body. A elements get an auto-generated ID for latter reference. And it's all kept in perl so programmer worries nothing.

Now it works great with CGI::Minimal, no model code in this spike. I want to somehow make a better integration of such concept into Jifty, or Catalyst. That feels like an assignment to myself in the coming OSDC.tw and YAPC::Asia

Labels: ,

How do a script find itself.

| No Comments | No TrackBacks

I admit it that I do not really dislike the idea of putting script tags directly inside body. That means I am not a xhtml strict person. But I can't understand that why it isn't put into the design (or implementation) to locate current script node easily.

What I'm try to solve can be described with this code snippet:

<p>
<script type="text/javascript">
    var this_node = get_this_node();

var p = this_node.parentNode; // get the <p> node.
</script>
</p>



Turns out the only way around is to assign an element id to the script tag:

<p>
<script id='the-script' type="text/javascript">
    var this_node = document.getElementById('the-script');

var p = this_node.parentNode; // get the <p> node.
</script>
</p>



This is only OK when everything is generated. Which is what I'm trying to do recently with my JavaScript::Writer perl module.

Labels:

Getting the coordination of a node in DOM.

| No Comments | No TrackBacks

This is a function that takes a DOM node, and returns the offset of that node. What's the "offset" ? It's the ordinal number in its siblings, the number "n" of node.parentNode.childNodes[n]. Sadly there's no easy way to do this with DOM API, basically it's just iterating over all its siblings and keep counting.

getNodeOffset = function(node) {
    var p = node.parentNode;
    if (p == null) return;
    for (var i = 0, l = p.childNodes.length; i < l ; i++ ) {
        if (p.childNodes[i] == node) break;+    }
    return i;
}

Here's one other interesting function, I called it "getNodeCoordination". Since each node must have a parent node, it can always be traced all the way up to document.body. This forms a simple coordination system. You can use a list of numbers like:


[3,0,0,1]


To uniquely locate a node. The example above can be translated into this horrible English: "The 1st child of the 0th child of the 0th child of the 3rd child of document.body". Or this elegant XPath representation:



//body/*[4]/*[1]/*[1]/*[2]


Those numbers are offset by one for obvious reason. Here's the code of that "getNodeCoordation" function.

getNodeCoordination = function(node, baseNode) {
    if (baseNode == null) baseNode = window.document.body;
    var coord = [];
    var p = node;
    while (p != baseNode) {
        var offset = getNodeOffset(p);
        if (offset == null) break;
        coord.unshift(offset);
        p = p.parentNode;
    }
    if (p != baseNode) return null;
    return coord;
}

Obviously the return value is very fragile against DOM change. Any DOM modification can invalid a previously stored coordination value. However, If you ever need to bookmark the location of a node and serialize it for storage, this is one approach.

ps. This is a cross-post from handlino.com

Labels: , ,