每周源代码29 – Ruby,Shoes和第一个Ruby病毒

[原文发表地址]  The Weekly Source Code 29 - Ruby and Shoes and the First Ruby Virus

[原文发表时间] 2008-06-24 07:47

上周我在挪威参加挪威开发者会议,所以恐怕这个月的每周源代码要变成双周源代码了。一次国外旅行能让人放松下来,感觉太棒了。这次旅行让我完全沉浸其中。不过我还是在慢慢地回归到现实的生活中来。

我最近对运用插件和其他工具扩展应用程序这类越来越有兴趣了。秉持着我一贯的信念——勤读代码,有助于成为更高水准的程序开发者——亲爱的读者们,这里我为你们奉上第29篇“每周源代码”,之后也会不断继续。

本周的源是为Ruby设计的“一点”式外挂。这非常酷,因为它集结了许多技术,形成了十分清晰的终极用户体验。其目的是使Ruby的GUI应用程序轻松运行,这的确有效可行,而且在各个层面的表现都非常突出。感谢Sam Saffron告诉我这个!

最开始,是名叫“为什么是幸运的僵硬”(或者简称"_why")的黑客提到的,所以这起源很早,而且有错误。你可以在GitHub上查看代码:https://github.com/why/shoes/tree/master 或通过“git clone git://github.com/why/shoes.git”克隆整个结构。

Shoes

在我看来,Ruby是一种非常美观,赏心悦目而且灵活的语言。Shoes则是使用Ruby制作窗口应用程序的GUI工具包。我在每周源代码12中曾提及过。Shoes是一个传奇,原因有很多,不过最重要的是因为它具有在所有软件文档历史上最伟大的API文档。在Shoes开发中最主要的著作叫做《没人知道Shoes》,这本书非常棒,连Chris Sells都对它爱不释手

这是用Ruby和Shoes写成的通讯录程序样本的一部分:

    1: Shoes.app :width => 320, :height => 350 do
    2:  
    3:    stack :margin => 40 do
    4:     stack :margin => 10 do
    5:       para "Name"
    6:       @name = list_box :items => ["Yes, please!", "NO.  No thankyou."]
    7:     end
    8:     stack :margin => 10 do
    9:       para "Address"
   10:       @address = edit_line
   11:     end 
   12:    stack :margin => 10 do
   13:       para "Phone"
   14:       @phone = edit_line
   15:     end 
   16:    stack :margin => 10 do
   17:       button "Save" do
   18:         Shoes.p [@name.text, @address.text, @phone.text]
   19:       end
   20:     end
   21:   end
   22: end 

感觉上和Tcl/Tk或者Rebol很像。如果有人写了一个非凡的主流程序,那一定很有趣。Shoes可以在XP,Vista,MacOSX和Linux上运行。注意你在Vista上必须点击右键,以管理者身份运行,因为_why还没有写入权限

提升提示。你得通过管理者进行初始引导安装。

不过,为了让Shoes正常运行,在今天之前,你必须安装Ruby,然后安装Shoes库,通常通过gem来实现。然后你需要通过ruby.exe,yourapp.rb或者你设置的快捷来运行程序。_why的博文发布的第二个评论就说了这些:

哇,这太棒了,我们现在可以把我们的应用程序给别人了。

Shoes的“引导程序”(我这样表述)是怎么运行的呢?_why给出的解释是:

如果你摆弄一下Windows PE二进制格式中的十六进制编辑器,你会在包含图标,对话框的文件末尾找到.rsrc部分。我把Ruby脚本添加进去:

 binj = Binject::EXE.new("blank.exe")
 binj.inject("SHOES_FILENAME", "simple-accordion.rb")
 File.open("simple-accordion.rb") do |f|
  binj.inject("SHOES_PAYLOAD", f)
 end
 binj.save("accordion.exe")

超棒的黑客。他把Ruby脚本升级成了Windows资源!他还为Mac OSX上的DMG(Disk Images)做了同样的升级。所以现在你可以创建移植到这两个运行平台上的Ruby脚本了。

运行时,它会查询Shoes是否存在于你的系统中。它在C:\Program Files (x86)\Common Files\Shoes\中。如果Shoes(包含Ruby的私有拷贝)不在其中,那就下载安装,然后程序就运行了。多棒啊,一点式跨平台GUI。

我也不清楚什么是安全分歧。好吧。我很清楚。我怀疑没有不被主机操作系统认证的安全性。你一旦运行,Ruby脚本就有完全的自由做任何它想做的事情。所以我在想有没有人可以写一个恶意的程序,就像如果他们愿意,可以给.NET程序写恶意程序一样。

你运行shoes –package就可以实现打包程序。点击打包,然后就会出现这样的对话框。如果你愿意你可以选在把Shoes和Ruby包括在最终EXE中。

Shoes

Shoes还支持自定义"Widgets"。比如,下面就是一个自定义里程表控制。

Shoes (2)

程序的完整代码,包括自定义控制代码如下:

    1: class Speedometer < Widget
    2:   attr_accessor :range, :tick, :position
    3:   def initialize opts = {}
    4:     @range = opts[:range] || 200
    5:     @tick = opts[:tick] || 10
    6:     @position = opts[:position] || 0
    7:     @cx, @cy = self.left + 110, self.top + 100
    8:  
    9:     nostroke
   10:     rect :top => self.top, :left => self.left,
   11:       :width => 220, :height => 200
   12:     nofill
   13:     stroke white
   14:     oval :left => @cx - 50, :top => @cy - 50, :radius => 100
   15:     (ticks + 1).times do |i|
   16:       radial_line 225 + ((270.0 / ticks) * i), 70..80
   17:       radial_line 225 + ((270.0 / ticks) * i), 45..49
   18:     end
   19:     strokewidth 2
   20:     oval :left => @cx - 70, :top => @cy - 70, :radius => 140
   21:     stroke lightgreen
   22:     oval :left => @cx - 5, :top => @cy - 5, :radius => 10
   23:     @needle = radial_line 225 + ((270.0 / @range) * @position), 0..90
   24:   end
   25:   def ticks; @range / @tick end
   26:   def radial_line deg, r
   27:     pos = ((deg / 360.0) * (2.0 * Math::PI)) - (Math::PI / 2.0)
   28:     line (Math.cos(pos) * r.begin) + @cx, (Math.sin(pos) * r.begin) + @cy,
   29:       (Math.cos(pos) * r.end) + @cx, (Math.sin(pos) * r.end) + @cy
   30:   end
   31:   def position= pos
   32:     @position = pos
   33:     @needle.remove
   34:     append do
   35:       @needle = radial_line 225 + ((270.0 / @range) * @position), 0..90
   36:     end
   37:   end
   38: end
   39:  
   40: Shoes.app do
   41:   stack do
   42:     para "Enter a number between 0 and 100"
   43:     flow do
   44:       @p = edit_line
   45:       button "OK" do
   46:         @s.position = @p.text.to_i
   47:       end
   48:     end
   49:  
   50:     @s = speedometer :range => 100, :ticks => 10
   51:   end
   52: end

完成后,大概占磁盘库的24兆,但你因此拥有了多媒体支持以及在那个范围内的许多库的支持,更不用说Ruby本身的拷贝。裸下载只需2.5M,带视频支持的版本下载也只需6.8M。

我觉得建立一个用Shoes的Twitter客户端也很棒。比赛已经开始!希望我们赶在一些写Ruby Shoes病毒的坏人之前做好Twitter客户端。我会把自己写的Ruby Shoes病毒亲自保管好。好吧,这不算是真正的病毒,只是自寻烦恼的源头罢了。不过我还是会保管好的。

追踪它演变的过程一定会非常有趣的。我希望会有更清晰的升级过程。如果你想试试运行你的第一个Ruby/Shoes程序,那就运行这个EXE,只要你有Windows,或者这个DMG如果你是Mac用户,那就看看简单的demo程序,不过最重要的是,体验一下安装/引导过程。