<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>zw963 (Billy.Zheng)</title>
    <link>https://ruby-china.org/zw963</link>
    <description>推理狂...</description>
    <language>en-us</language>
    <item>
      <title>procodile, 一款类似 foreman 的工具，但可运行在前台或后台，也支持定时任务</title>
      <description>&lt;h2 id="宣布发布 procodile 2.0.0-rc1"&gt;宣布发布 &lt;code&gt;procodile&lt;/code&gt; 2.0.0-rc1&lt;/h2&gt;
&lt;p&gt;我很高兴地宣布 &lt;code&gt;procodile&lt;/code&gt; 2.0.0-rc1 正式发布。自上一个版本以来，这是一次重大更新，累计包含了 130 多个 commit。&lt;/p&gt;

&lt;p&gt;这次更新之所以非常重要，主要有以下几个原因：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;这是第一个完整实现原始 Ruby 版本功能的 &lt;a href="https://github.com/adamcooke/procodile" rel="nofollow" target="_blank" title=""&gt;procodile&lt;/a&gt; 发布版本。&lt;/li&gt;
&lt;li&gt;它还修复了原始 Ruby 版本中存在的许多 bug 和边界情况问题。(感谢 Crystal 程序语言，让暴露和修复这些问题，相对于 Ruby 简单得多）&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;与此同时，2.0 版本在原始 Ruby 版本的基础上也有了显著增强，并引入了一些此前 Ruby 版本并不具备的新功能：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;支持通过 &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt; 文件&lt;/strong&gt;加载环境变量，这项功能基于 &lt;a href="/jwoertink" class="user-mention" title="@jwoertink"&gt;&lt;i&gt;@&lt;/i&gt;jwoertink&lt;/a&gt; 开发的 &lt;a href="https://github.com/luckyframework/lucky_env" rel="nofollow" target="_blank" title=""&gt;lucky_env&lt;/a&gt;。&lt;/li&gt;
&lt;li&gt;支持&lt;strong&gt;定时任务&lt;/strong&gt;。这是一次重要更新，使你可以在同一个地方同时管理长期运行的进程和定时任务。得益于 &lt;a href="/kostya" class="user-mention" title="@kostya"&gt;&lt;i&gt;@&lt;/i&gt;kostya&lt;/a&gt; 开发的 &lt;a href="https://github.com/kostya/cron_parser" rel="nofollow" target="_blank" title=""&gt;cron_parser&lt;/a&gt;，它不仅支持标准的五段式 crontab 表达式，还支持精确到秒级的 cron 调度。&lt;/li&gt;
&lt;li&gt;引入了 &lt;strong&gt;Runtime Issues&lt;/strong&gt;。当命令执行结束后如果检测到问题，你会立即在命令行中收到反馈。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;请参阅 &lt;a href="https://github.com/crystal-china/procodile/wiki" rel="nofollow" target="_blank" title=""&gt;Wiki&lt;/a&gt;，其中提供了结构清晰且内容详尽的文档说明。&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Wed, 15 Apr 2026 15:33:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/44552</link>
      <guid>https://ruby-china.org/topics/44552</guid>
    </item>
    <item>
      <title>Crystal China</title>
      <description>&lt;p&gt;&lt;a href="https://crystal-china.org" rel="nofollow" target="_blank"&gt;https://crystal-china.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;最初的目的，主要是希望分享自己在使用 Crystal 过程中的一些心得体会（很多笔记待整理），做一些 Crystal 方面的普及。&lt;/p&gt;

&lt;p&gt;域名注册好好几年了，一直没动，今年终于断断续续建起来了，文档更新不快，看时间，看心情。&lt;/p&gt;

&lt;p&gt;文档里，有个 &lt;code&gt;写给 Rubyists&lt;/code&gt;，有兴趣的朋友不妨读一下，期望给你带来收获。&lt;/p&gt;

&lt;p&gt;欢迎 &lt;code&gt;程序语言自身角度&lt;/code&gt; 的讨论，Ruby 已经很小众了，Crystal 更加小众，本来就不是适合所有人（尤其是本就不太熟悉 Ruby 的人）&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Wed, 25 Jun 2025 15:36:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/44205</link>
      <guid>https://ruby-china.org/topics/44205</guid>
    </item>
    <item>
      <title>有没有人有兴趣一起 fork 一个功能简单的 Homeland？使用 Crystal?</title>
      <description>&lt;p&gt;看起来坛子里对 Crystal 似乎不感冒。之前有个用户 &lt;a href="/ThxFly" class="user-mention" title="@ThxFly"&gt;&lt;i&gt;@&lt;/i&gt;ThxFly&lt;/a&gt; 写了不少东西，但是似乎他也放弃改 Golang 了。&lt;/p&gt;

&lt;p&gt;唉，让人忍不住要吐槽的 golang 啊，就算有强大的 LSP 支持，我还是真心用不下去啊！&lt;/p&gt;

&lt;p&gt;不扯淡了，说正经的，几个月前注册了域名，crystal-china.org, 但是因为一直有事，还没开始搞起。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://luckyframework.org/" rel="nofollow" target="_blank"&gt;https://luckyframework.org/&lt;/a&gt; 现在已经挺好用了，我自己用 kemal, 还有 lucky 也算做过几个小项目，算是练过手了。&lt;/p&gt;

&lt;p&gt;但是目前一直没行动，除了时间，还有个原因是前端太菜，头疼，简单的 CSS 还没用下样子，又开始用 tailwind 了，
那一堆一堆的 class ...&lt;/p&gt;

&lt;p&gt;其实就是想问问，有没有人还对 Crystal 感兴趣啊？大家一起业余时间论坛搞起来，大家也有个窝。&lt;/p&gt;

&lt;p&gt;就用 lucky,  backend 我来写应该不会遇到太大的问题，前端需要有个帮手，当然对 Homeland Code Base  熟悉的 XD 最好了，
那样 fork 起来就更快了。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;Crystal 版本已经到 1.8.1 了，虽然社区小，人少，但是还在不断进步，没事多去 &lt;a href="https://forum.crystal-lang.org" rel="nofollow" target="_blank" title=""&gt;社区&lt;/a&gt; 逛逛。&lt;/p&gt;

&lt;p&gt;Github 上我也建立了一个 &lt;a href="https://github.com/orgs/crystal-china/repositories" rel="nofollow" target="_blank" title=""&gt;crystal-china&lt;/a&gt; 组织，都是些我写的、或从 Ruby 
fork 的小项目，目前只有几个，也许大家觉得有用。&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Sat, 06 May 2023 01:18:55 +0800</pubDate>
      <link>https://ruby-china.org/topics/43053</link>
      <guid>https://ruby-china.org/topics/43053</guid>
    </item>
    <item>
      <title>写了一个 Gem, 叫做 hot_reloader, 请大家帮忙测试一下.</title>
      <description>&lt;p&gt;如果你是一个 Rails 开发者，这个 Gem 的功能已经有了。&lt;/p&gt;

&lt;p&gt;而且，Rails 6 的新 reloader 和这个 Gem 采用了同样的方案。&lt;/p&gt;

&lt;p&gt;对于有需求的同学，欢迎测试，以及提出宝贵的意见。&lt;/p&gt;
&lt;h3 id="安装"&gt;安装&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;hot_reloader&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者增加下列内容到 Gemfile&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'hot_reloader'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="一个 Roda 例子:"&gt;一个 Roda 例子：&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.ru&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'roda'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'hot_reloader'&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'RACK_ENV'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'production'&lt;/span&gt;
  &lt;span class="no"&gt;HotReloader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__dir__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'another/root/path'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="no"&gt;HotReloader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;will_listen&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;__dir__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'another/root/path'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更多的详情，见相关的 Gem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zw963/hot_reloader" rel="nofollow" target="_blank" title=""&gt;hot_reloader&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fxn/zeitwerk" rel="nofollow" target="_blank" title=""&gt;zeitwerk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/guard/listen" rel="nofollow" target="_blank" title=""&gt;listen&lt;/a&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Thu, 21 Mar 2019 19:35:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/38272</link>
      <guid>https://ruby-china.org/topics/38272</guid>
    </item>
    <item>
      <title>Senior Ruby programer 慢寻一份 Remote 工作. (Senior Ruby programer looking for remote jobs)</title>
      <description>&lt;h2 id="简单介绍一下自己:"&gt;简单介绍一下自己：&lt;/h2&gt;
&lt;p&gt;| Billy.Zheng | M | ShangHai | NUC/automatic control &lt;/p&gt;

&lt;p&gt;Self-taught, Linux Geek, Expert in Ruby/TDD, proficient in BASH, ThoughtWorks
retired employee, OS active contributor, github: &lt;a href="https://github.com/zw963" rel="nofollow" target="_blank"&gt;https://github.com/zw963&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="TDD/Refactor"&gt;TDD/Refactor&lt;/h3&gt;
&lt;p&gt;Expert in TDD/Refactor, Write complex business logic.
Advocate more test, less/better code, fast health iteration.&lt;/p&gt;
&lt;h3 id="Ruby"&gt;Ruby&lt;/h3&gt;
&lt;p&gt;Expert in Ruby, multiple Gem author, experience in API development.&lt;/p&gt;
&lt;h3 id="Linux/Bash/Emacs"&gt;Linux/Bash/Emacs&lt;/h3&gt;
&lt;p&gt;Automate everything that can be automated use BASH/Ruby script, CLI fans,
love UNIX K.I.S.S principle, Emacs deep customization user.
.&lt;/p&gt;
&lt;h2 id="My last Project"&gt;My last Project&lt;/h2&gt;
&lt;p&gt;ChenYa education technology Co., Ltd (ShangHai) (2018/4 -)&lt;/p&gt;

&lt;p&gt;Join in "GrowUp Together" APP second edition team as a senior ruby programmer,
   technology stack use &lt;code&gt;Sequel+GraphQL&lt;/code&gt;, Has been in develop for a few months, 
   bad code smell, all DB/table created by "mysql workbench", responsible for rewrite
    all ruby code, db schema/data migration, and new features development.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use ActiveRecord migration/normalize all table to new schema.&lt;/li&gt;
&lt;li&gt;Introduce TDD, continuous develop/refactoring core feature,
 feature is more rich, but code is more less. coverage from zero to 88%,
 Some new project (Getui message pusher) test coverage is 97%.&lt;/li&gt;
&lt;li&gt;Update graphQL ruby to 1.8x, rewrite all interface with new usage.&lt;/li&gt;
&lt;li&gt;Hack GraphiQL + Miniprofier, Add profiler to all environment.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Ruby+ActiveRecord&lt;/code&gt; migration millions records to new APP, TS:
 multithreading(concurrency ruby), multiprocess(data split), Cache.&lt;/li&gt;
&lt;li&gt;Normalize Sequel usage, write gem to add feature, fix error, optimize SQL.&lt;/li&gt;
&lt;li&gt;New feature development with new created ruby team.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="Other"&gt;Other&lt;/h2&gt;
&lt;p&gt;If you need more detailed CV, please email to me. (mail address see my github)&lt;/p&gt;

&lt;p&gt;Shortcoming is bad spoken english and English hearing.&lt;/p&gt;

&lt;p&gt;Expect search a suitable remote career opportunities within a month.
Consider company job in ShangHai too if there is an excellent opportunity.&lt;/p&gt;

&lt;p&gt;Thanks&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Tue, 19 Feb 2019 02:00:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/38119</link>
      <guid>https://ruby-china.org/topics/38119</guid>
    </item>
    <item>
      <title>A complete Todo App in less than 100 lines of code in Ruby with Hyperloop ! </title>
      <description>&lt;p&gt;&lt;span class="embed-responsive embed-responsive-16by9"&gt;&lt;iframe class="embed-responsive-item" src="//www.youtube.com/embed/gtL4kAKUt_g" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Wed, 16 Aug 2017 17:16:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/33854</link>
      <guid>https://ruby-china.org/topics/33854</guid>
    </item>
    <item>
      <title>Ruby on Rails is out: major coding bootcamp ditches it, due to waning interest</title>
      <description>&lt;p&gt;来点唱衰 Ruby on Rails  的话题，哈哈 &lt;/p&gt;

&lt;p&gt;&lt;a href="https://thenextweb.com/dd/2017/07/26/ruby-rails-major-coding-bootcamp-ditches-due-waning-interest/#.tnw_qFaP3McA" rel="nofollow" target="_blank"&gt;https://thenextweb.com/dd/2017/07/26/ruby-rails-major-coding-bootcamp-ditches-due-waning-interest/#.tnw_qFaP3McA&lt;/a&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Fri, 28 Jul 2017 02:51:47 +0800</pubDate>
      <link>https://ruby-china.org/topics/33654</link>
      <guid>https://ruby-china.org/topics/33654</guid>
    </item>
    <item>
      <title> Helix: Build Native Ruby Extensions Without Fear</title>
      <description>&lt;p&gt;&lt;a href="https://usehelix.com/getting_started" rel="nofollow" target="_blank"&gt;https://usehelix.com/getting_started&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;能 FQ 的也可以看对应的 Youtube 视频。&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Fri, 07 Jul 2017 20:50:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/33427</link>
      <guid>https://ruby-china.org/topics/33427</guid>
    </item>
    <item>
      <title>使用 Ruby 写 Node &amp;&amp; 如何使用 Opal 包装 Javascript 库到 Ruby</title>
      <description>&lt;p&gt;&lt;a href="http://funkworks.blogspot.hk/2017/05/opening-up-node-ecosystem-for-ruby-http.html" rel="nofollow" target="_blank" title=""&gt;原文地址&lt;/a&gt;, 我只是使用我自己当时理解的方式，分步骤讲了出来。&lt;/p&gt;
&lt;h3 id="使用 node 启动一个 http server."&gt;使用 node 启动一个 http server.&lt;/h3&gt;
&lt;p&gt;Node 自带 http 模块，启动一个 http_server 很简单，新建 &lt;code&gt;node.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// node.js&lt;/span&gt;
&lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动 server:&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$:&lt;/span&gt;  node node.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;浏览器访问：&lt;a href="http://127.0.0.1:1337" rel="nofollow" target="_blank"&gt;http://127.0.0.1:1337&lt;/a&gt;, 看到 &lt;code&gt;hello world&lt;/code&gt;, 成功。&lt;/p&gt;
&lt;h3 id="最简单的 wrap 方式, node.rb 第一版:"&gt;最简单的 wrap 方式，node.rb 第一版：&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Opal 自带这个库.&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nodejs'&lt;/span&gt;

&lt;span class="c1"&gt;# 这是 Opal 新增的 node_require 方法, 用来  require 一个 node 模块.&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;

&lt;span class="c1"&gt;# 直接把上面的 js 原样拷贝过来,  放到  X-strings 里面执行, 就像 MRI 执行外部程序一样.&lt;/span&gt;
&lt;span class="sb"&gt;`
http.createServer(function(req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sb"&gt;');
}).listen(port);
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;浏览器访问：&lt;a href="http://127.0.0.1:1337" rel="nofollow" target="_blank"&gt;http://127.0.0.1:1337&lt;/a&gt;, 看到 &lt;code&gt;hello world&lt;/code&gt;, 成功。&lt;/p&gt;
&lt;h3 id="让它看起来更 Rubyify 一点点, 第二版."&gt;让它看起来更 &lt;code&gt;Rubyify&lt;/code&gt; 一点点，第二版。&lt;/h3&gt;
&lt;p&gt;如果你足够熟悉 Ruby, 你可能遇到了接触 Opal 以来的第一个大坑 (至少对我来说是的), 
变量名的 string interpolation  在哪里呢？这是因为 &lt;code&gt;http = node_require('http')&lt;/code&gt; 为 JS
的 runtime 定义了 JS 的本地变量，因此不需要 interpolation, 不过，为了让看起来更像 Ruby,
这样做也不无不可。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nodejs'&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;

&lt;span class="c1"&gt;# 加上字符串插值, 现在更像 Ruby 了.&lt;/span&gt;

&lt;span class="sb"&gt;`
&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;.createServer(function(req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sb"&gt;');
}).listen(&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;);
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;仍然成功。&lt;/p&gt;
&lt;h3 id="更进一步, X-strings 的方式太丑了, 我可以不可以用更 Ruby 的方式来写这段 JS 代码? 第三版."&gt;更进一步，X-strings 的方式太丑了，我可以不可以用更 Ruby 的方式来写这段 JS 代码？第三版。&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nodejs'&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;

&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;值得一提的是：这里的 &lt;code&gt;.JS&lt;/code&gt; 是 Opal 0.9 开始支持的一个特殊的词法，而不是方法调用。
&lt;code&gt;to_n&lt;/code&gt; 方式是要将 js native 对象类型转化为 Opal 支持的 Native::Object 类型 Ruby 对象.
但是我们 JS 调用了三次，太丑了，换个写法如何？&lt;/p&gt;
&lt;h3 id="使用 Opal 的 Native 模块, 第四版"&gt;使用 Opal 的 Native 模块，第四版&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nodejs'&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1337&lt;/span&gt;

&lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;opal_res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;opal_res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;opal_res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看起来又好了一点点，这里的 Native(http) 使用 method_missing 实现了 createServer 到 JS native 对象的委托.
可是写起来感觉还是挺烂的，我们定义一个接口，把它 wrap 起来如何？&lt;/p&gt;
&lt;h3 id="我们要用我们自己的接口.   第五版"&gt;我们要用我们自己的接口。第五版&lt;/h3&gt;
&lt;p&gt;我需要定义一个 HTTP 模块，再定义一个 Server 类，然后创建一个 listen 方法，用这个方法来 wrap
我们不想见到的 JS 方法，下面的接口就看起来不错：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
   &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下面的代码看起来想那么回事儿。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'nodejs'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;HTTP&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# 这里使用 Native 模块封装下 http&lt;/span&gt;
      &lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="c1"&gt;# 直接把 JS 传入的 block 和 port 委托给原始的 createServer 方法.&lt;/span&gt;
      &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt; &lt;span class="s2"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看起来不错，快去运行下！&lt;/p&gt;

&lt;p&gt;很不幸，他不工作。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;res.&lt;span class="nv"&gt;$writeHead&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;200, &lt;span class="nv"&gt;$hash2&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;, &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt;: &lt;span class="s2"&gt;"text/plain"&lt;/span&gt;&lt;span class="o"&gt;}))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    ^
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这因为 res 对象没有 writeHead 可用！他是一个 JS 的 native 对象，你不能在 Ruby 中
直接调用 JS 的原生方法。&lt;/p&gt;

&lt;p&gt;因此，不得不改成这样：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt; &lt;span class="s2"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;哈，终于 OK 了。&lt;/p&gt;
&lt;h3 id="既然要 wrap, 那就彻底一点, 我们的目标是完全的 Rubyify, 你不需要知道我其实 wrap 的是 JS."&gt;既然要 wrap, 那就彻底一点，我们的目标是完全的 Rubyify, 你不需要知道我其实 wrap 的是 JS.&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;HTTP&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node_require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;# 在这里把要返回的参数先 wrap 一下, 然后再传到 block 中.&lt;/span&gt;
          &lt;span class="k"&gt;yield&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1337&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt; &lt;span class="s2"&gt;"Hello World&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;终于彻底消除了 JS 的痕迹，虽然，仍然暴露了几个 node 的内部实现方法.
不如改成 rack 兼容的实现，具体实现，留给读者自己去做吧。(原文内有答案)&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Thu, 15 Jun 2017 20:55:31 +0800</pubDate>
      <link>https://ruby-china.org/topics/33240</link>
      <guid>https://ruby-china.org/topics/33240</guid>
    </item>
    <item>
      <title>发布一个 gem erb_to_slim</title>
      <description>&lt;p&gt;发觉自己好久不写正则表达式了，正好最近不忙，练练手，测试下自己的正则水平。&lt;/p&gt;

&lt;p&gt;这也是我发布的第一个 Gem, 好歹知道如何发布 Gem 了，好简单！&lt;/p&gt;
&lt;h2 id="特点:"&gt;特点：&lt;/h2&gt;
&lt;p&gt;相比较 Slim 官方的 gem, 这个 gem 具有以下特点：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;最小修改，保持原始的格式不变 (简单的执行正则替换), 方便和原始的  ERB 格式文件对照。&lt;/li&gt;
&lt;li&gt;没有任何其他依赖。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="用法:"&gt;用法：&lt;/h2&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;erb_to_slim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后到 ERB 所在目录下：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;erb_to_slim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;你没有看错，没有任何参数，这会生成同名 slim 文件，并且将原来的 erb 文件，加个 bak 扩展名备份。&lt;/p&gt;
&lt;h2 id="github 主页:"&gt;github 主页：&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/zw963/erb_to_slim" rel="nofollow" target="_blank"&gt;https://github.com/zw963/erb_to_slim&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;欢迎围观，拍砖。包含很详细的测试，这对于这个 Gem 最终能够发布，起到了决定性的作用.
有兴趣的同学，也可以通过这个项目学习正则表达式。;)&lt;/p&gt;
&lt;h2 id="贡献"&gt;贡献&lt;/h2&gt;
&lt;p&gt;目前还不完善，主要根据我对 Slim Parser 的理解来写的，也没有在很多页面测试过。可能存在明显的错误，
希望大家有空试试，帮助我一起改善这个 Gem. 请给我提 &lt;a href="https://github.com/zw963/erb_to_slim/issues" rel="nofollow" target="_blank" title=""&gt;issue&lt;/a&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Sat, 30 Aug 2014 02:30:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/21298</link>
      <guid>https://ruby-china.org/topics/21298</guid>
    </item>
    <item>
      <title>Add a pointer in a lambda to point to current lambda.</title>
      <description>&lt;p&gt;e.g.  named this pointer as &lt;code&gt;this&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;
  &lt;span class="n"&gt;memo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 354224848179261915075&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;instead of:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;
  &lt;span class="n"&gt;memo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;feb&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;feb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;feb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;feb&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# =&amp;gt; 354224848179261915075&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>zw963</author>
      <pubDate>Sun, 01 Jun 2014 14:03:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/19668</link>
      <guid>https://ruby-china.org/topics/19668</guid>
    </item>
    <item>
      <title>Javascript underscore vs Ruby</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/zw963/underscore_ruby/blob/master/underscore.md" rel="nofollow" target="_blank"&gt;https://github.com/zw963/underscore_ruby/blob/master/underscore.md&lt;/a&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Tue, 20 May 2014 21:28:42 +0800</pubDate>
      <link>https://ruby-china.org/topics/19424</link>
      <guid>https://ruby-china.org/topics/19424</guid>
    </item>
    <item>
      <title>有用 MBP 装 Linux 的吗？</title>
      <description>&lt;p&gt;社区内有朋友这么干吗？&lt;/p&gt;

&lt;p&gt;有没有专门定制的版本，让这个事情比较轻松些？&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Tue, 04 Mar 2014 23:51:39 +0800</pubDate>
      <link>https://ruby-china.org/topics/17669</link>
      <guid>https://ruby-china.org/topics/17669</guid>
    </item>
    <item>
      <title>祝大家马上成功!</title>
      <description>&lt;p&gt;本贴表达了本人对社区 `所有朋友' 马年最美好的的祝愿！&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Fri, 31 Jan 2014 00:00:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/17061</link>
      <guid>https://ruby-china.org/topics/17061</guid>
    </item>
    <item>
      <title>过年了, 转发个很有才的图片, 大家乐呵乐呵!</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2014/537f60c725233136bfd7e382403e71c3.jpg" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Thu, 30 Jan 2014 11:59:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/17058</link>
      <guid>https://ruby-china.org/topics/17058</guid>
    </item>
    <item>
      <title>[讨论] reverse 一个字符串的顺序.</title>
      <description>&lt;p&gt;大家如何实现 String#reverse ?&lt;/p&gt;

&lt;p&gt;我想到了三个方法，虽然第一个其实用到了迭代器中的 reverse_each .... &lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reverse_each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_char&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;
&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;
  &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>zw963</author>
      <pubDate>Wed, 22 Jan 2014 15:21:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/16925</link>
      <guid>https://ruby-china.org/topics/16925</guid>
    </item>
    <item>
      <title>发个可定制的自动化测试脚本. [Watchr + Spring]</title>
      <description>&lt;p&gt;自己写的自动化测试脚本，Rails 和 非 Rails 程序都可以用，希望对大家有帮助。&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zw963/ass/blob/master/common/ruby/lib/autotest.rb" rel="nofollow" target="_blank"&gt;https://github.com/zw963/ass/blob/master/common/ruby/lib/autotest.rb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;必须的 gem 只有一个 watchr. &lt;a href="https://github.com/mynyml/watchr" rel="nofollow" target="_blank"&gt;https://github.com/mynyml/watchr&lt;/a&gt; 
虽然很久不更新了，但是是仍旧可用的，打算有时间的话，fork 一个 watchr, 好歹维护下。&lt;/p&gt;

&lt;p&gt;还有一个可选的 gem, Spring,  &lt;a href="https://github.com/rails/spring" rel="nofollow" target="_blank"&gt;https://github.com/rails/spring&lt;/a&gt;
是个 preloader, 强烈推荐使用，让你的测试 flow 更加顺畅。&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Fri, 10 Jan 2014 20:57:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/16725</link>
      <guid>https://ruby-china.org/topics/16725</guid>
    </item>
    <item>
      <title>Linux 窗口之间快速切换 - 加速你的开发效率!</title>
      <description>&lt;p&gt;废话少说，这是一篇在 Linux 下的各个窗口之间快速切换的文章。&lt;/p&gt;
&lt;h2 id="先说下 Spec."&gt;先说下 Spec.&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;假设开发过程中，涉及到以下界面：Terminal, Editor, Browser, 外加一个随便什么鬼玩意儿。例如：某个 PDF 阅读软件，在阅读 PDF. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;地球人都知道 ALT TAB, 但是最大的问题是：如果开的多了，你常常需要 ALT + TAB TAB ... 很多次。在 Win 7 下，对于系统托盘，有类似于 Win + 0, Win + 1 的快捷键，我相信很多 Linux 发布版也有类似功能。如果你用的很爽，而且也不打算换发布版，下面不用看了。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;我要求所有 UNIX Like 系统都通用 (只要有 X), 即：使用 Linux 下一些最基本的功能来实现。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;我要求在任何桌面，按下一个快捷键，会立即弹出我想要的以上任一窗口，再按一次，一定会返回到原来的窗口。例如：我的快捷键是：C-M 立即激活 Terminal (当然，你可以开任意多个 TAB), C-I 会激活到 Emacs 的某个 Frame (或创建一个),  C-; 会激活 Firefox. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;当然你也可以任意组合，例如：你打开一个 pdf 再看一本书，然后 C-m 切换到 Terminal 下写点东西，然后直接 C-i 打开 Emacs 做点笔记，然后再次 C-i 回到之前的 pdf, C-; 浏览下网页，再次 C-; , 又返回 pdf...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;好吧我知道很多 XD 都是多显示器，而且显示器很大，常常拆分成好几块儿，鼠标玩的也很转，如果你那样很爽，我没有任何意见，这只是我个人的习惯，分享给同好者吧。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="准备工作"&gt;准备工作&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt; 首先，你需要一个叫做 Xbindkeys 的工具。传送门：&lt;a href="http://www.nongnu.org/xbindkeys/" rel="nofollow" target="_blank"&gt;http://www.nongnu.org/xbindkeys/&lt;/a&gt;
他的用途是：绑定任意&lt;code&gt;全局&lt;/code&gt;快捷键到一个脚本或命令，他是基于纯 X 的。你甚至不需要 Gnome 或 KDE , 仅仅启动一个 Xterm, 就可以用它。&lt;/li&gt;
&lt;li&gt;你需要一个 dropdown Terminal, 就是一个下拉式的全屏 Terminal.  当你按下快捷键时，自顶向下，会弹出 Terminal. 当你再次按下快捷键或点击任何其他窗口时，自动隐藏了。如果你没有，我推荐一个足够简单，对我来说也足够好的 XFCE Terminal. 传送门：&lt;a href="http://git.xfce.org/apps/xfce4-terminal/" rel="nofollow" target="_blank"&gt;http://git.xfce.org/apps/xfce4-terminal/&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;wmctrl, 很多发布版应该带这个小命令了，可以让你激活指定的窗口，甚至不同 Work Space 之间也可以切换。如果碰巧你没有，传送门：&lt;a href="http://tomas.styblo.name/wmctrl/" rel="nofollow" target="_blank"&gt;http://tomas.styblo.name/wmctrl/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; 你需要 xprop 命令... 我想哪怕是最老的 UNIX , 只要有 X 都应该有这个命令吧 ?&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="步骤"&gt;步骤&lt;/h2&gt;
&lt;hr&gt;
&lt;h3 id="首先我们要编写两个公共函数, 这些函数可以方便的在所有脚本中被使用."&gt;首先我们要编写两个公共函数，这些函数可以方便的在所有脚本中被使用。&lt;/h3&gt;
&lt;p&gt;这些公共函数你可以单独放在一个文件中，然后稍后通过 find, 全部 source, 你可以直接放到你的 .bashrc 里面。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;第一个函数主要用来获取某个窗口的 id , 名称之类的信息，我的函数是这样的&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;GET_CURRENT_FRAME_VARIABLE &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; Cygwin &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nv"&gt;CURRENT_WND_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xprop &lt;span class="nt"&gt;-root&lt;/span&gt; _NET_ACTIVE_WINDOW 2&amp;gt;/dev/null |cut &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; 5|cut &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt; &lt;span class="nt"&gt;-f1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nv"&gt;CURRENT_WND_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;xprop &lt;span class="nt"&gt;-id&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; _NET_WM_NAME 2&amp;gt;/dev/null |cut &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[0m[32m(&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt;&lt;span class="s2"&gt;)[0m"&lt;/span&gt;

        &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;xprop &lt;span class="nt"&gt;-id&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; WM_WINDOW_ROLE |cut &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="nt"&gt;-f2&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"xfce4-terminal-dropdown"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        &lt;span class="nv"&gt;DROPDOWN_TERMINAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
        &lt;/span&gt;&lt;span class="k"&gt;return &lt;/span&gt;0
    &lt;span class="k"&gt;fi
    return &lt;/span&gt;1
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; GET_CURRENT_FRAME_VARIABLE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;CURRENT_WND_ID 获取任意窗口的 ID
CURRENT_WND_NAME 获取对应名称。&lt;/p&gt;

&lt;p&gt;最后一段，是判断当前 Terminal 窗口是不是 xfce4-terminal-dropdown.  之所以这样做，是我可能会开两个 Terminal, 一个非 dropdown, 一个 dropdown, 标题一模一样。只能通过这种方式判断了。如果当前 Terminal 是 dropdown, 那么返回一个值为 true 的变量 DROPDOWN_TERMINAL, 否则变量值为空。&lt;/p&gt;

&lt;p&gt;记得写完后，source .bashrc&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;strong&gt;第二个函数是一个通用模板，其中保存了一大坨用来切换窗口的公共代码&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;switch_to &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    GET_CURRENT_FRAME_VARIABLE &amp;amp;&amp;gt;/dev/null

    &lt;span class="nb"&gt;eval local&lt;/span&gt; &lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$SHM_TMP&lt;/span&gt;/.&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &amp;amp;&amp;gt;/dev/null
    &lt;span class="nb"&gt;eval local &lt;/span&gt;before_&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$SHM_TMP&lt;/span&gt;/.before_&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &amp;amp;&amp;gt;/dev/null

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;wmctrl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;before_&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;egrep &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_WND_NAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$SHM_TMP&lt;/span&gt;/.&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
        wmctrl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;before_&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DROPDOWN_TERMINAL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$SHM_TMP&lt;/span&gt;/.before_&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;

        &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$CURRENT_WND_ID&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; wmctrl &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;eval echo&lt;/span&gt; &lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$2_wnd_id&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        wmctrl &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;amp;&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;:3&lt;span class="k"&gt;}&lt;/span&gt; &amp;amp;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; switch_to
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这逻辑稍稍有点杂乱，但是基本原理可以说下，不过提前声明，你完全可以无视这一坨代码，你只要稍后按照我的方式调用即可。&lt;/p&gt;

&lt;p&gt;1) 如果不是 Emacs 窗口，那么首先保存当前窗口的 id 到 $SHM_TMP 目录下的某个文件中.
2) 切换到之前保存的 id 对应的窗口，如果不成功，尝试选择一个，还不行，新启动一个。
3) 切换成功之后，将激活的这个 Emacs 窗口 id 保存起来。
4) 如果是原先的 Emacs 窗口，切换回到来之前的窗口。
5) 如果是一个新的 Emacs 窗口 (我常常会存在多个), 那么将新的窗口 id 存起来。稍后快捷键就在新的窗口和原窗口之间切换了。&lt;/p&gt;

&lt;p&gt;大概懂点编程的人应该都可以看个大概懂了...  &lt;/p&gt;

&lt;p&gt;几个地方稍稍提下：&lt;/p&gt;

&lt;p&gt;1) GET_CURRENT_FRAME_VARIABLE 调用的之前定义的那个函数.
2) $SHM_TMP 是我的一个全局变量，我设的是 /dev/shm, 你也可以设 /tmp, 随你.
3) wmctrl -i -a 是切换到 id, 格式大概为：0x03e00075, 你可以 wmctrl -l 看看.
 wmctrl -a 是按照名字切换，可以模糊匹配。&lt;/p&gt;
&lt;h3 id="设定脚本快捷键"&gt;设定脚本快捷键&lt;/h3&gt;
&lt;p&gt;home 下面新建一个 .xbindkeysrc, 加入以下内容：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; ☠ &lt;span class="c"&gt;# cat emacs_frame&lt;/span&gt;

&lt;span class="s2"&gt;"switch_to_firefox"&lt;/span&gt;
Control + semicolon

&lt;span class="s2"&gt;"emacs_frame"&lt;/span&gt;
Control + i
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后启动  &lt;code&gt;xbindkeys &amp;amp;&lt;/code&gt; 启动 daemon.  你应该将这个加到 .bashrc  当中，让它自动启动。&lt;/p&gt;
&lt;h3 id="最后一步, 编写在 xbindkeys 中调用的那两个脚本"&gt;最后一步，编写在 xbindkeys 中调用的那两个脚本&lt;/h3&gt;
&lt;p&gt;因为有了上面那一坨公共逻辑代码，脚本写起来就很简单了，只需要一行。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; ☠ &lt;span class="c"&gt;# cat emacs_frame&lt;/span&gt;
&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;


&lt;span class="nv"&gt;emacs_frame_pattern&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$MY_EDITOR&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'(concat "  " "-" "  " invocation-name "@" system-name)'&lt;/span&gt;|sed &lt;span class="s1"&gt;'s#"##g'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
switch_to &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$emacs_frame_pattern&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"emacs"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MY_EDITOR&lt;/span&gt;&lt;span class="s2"&gt; -nc --eval (nav)"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; ☠ &lt;span class="c"&gt;# cat switch_to_firefox &lt;/span&gt;
&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="c"&gt;# 使用方式: switch_to '标题模板' ' 关键字' '调用的命令'&lt;/span&gt;
switch_to &lt;span class="s1"&gt;'Mozilla Firefox'&lt;/span&gt; &lt;span class="s2"&gt;"firefox"&lt;/span&gt; &lt;span class="s2"&gt;"firefox &lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;最后，重要的一点：记得给这个文件加 x 执行属性。chmod +x emacs_frame switch_to_emacs.&lt;/p&gt;

&lt;p&gt;完了，写了一堆，其实一点都不复杂... 写到这里，其实你也看出来了，dropdown 的 Terminal, 并非必须的。你完全可以将 Terminal 放到一个新的 Workspace, 来达到同样的 (当未激活时，完全隐藏窗口) 效果，只不过，少了 dropdown 特效而已。&lt;/p&gt;

&lt;p&gt;好吧，我有理由相信在 Apple 占大多数的咱社区，对这文章有兴趣的不多，如果你觉得没什么用，嘴下留情呀。也许有人觉得有用呢？&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Sat, 12 Oct 2013 21:33:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/14702</link>
      <guid>https://ruby-china.org/topics/14702</guid>
    </item>
    <item>
      <title>给 Ruby 新人一个建议: 不懂 Linux, 不懂 CLI, 你无法了解 Ruby 是多么的优雅.</title>
      <description>&lt;p&gt;斗胆给 Ruby 新人这个建议。&lt;/p&gt;

&lt;p&gt;就说 split 和 join 吧。用 shell 脚本写，如果不用第三方工具 (awk  我也就不会), 需要这样写：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# 以 _ 作为 delimiter, 将一个字符串 split 到一个叫做 array 的数组中.&lt;/span&gt;
&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'_'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; array &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# 现在 $array 里面有了个数组.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 以 : 作为 delimiter, 将数组的元素合成一个字符串. 
IFS=":" &amp;amp;&amp;amp; task="${array[*]}"
# 恢复默认 IFS.
IFS=
echo "$task"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果用 ruby, 真的好简单，你根本不用考虑记录分隔符的问题。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; |ruby &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'print ARGF.readlines(".").map(&amp;amp;:chop).join(":")'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;通过比较，你可能再也不想用 shell 脚本了。 &lt;/p&gt;

&lt;p&gt;唯一的一个问题是：万一某些发布版没有 Ruby 解释器咋办？可能有点杞人忧天？&lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Mon, 23 Sep 2013 10:17:58 +0800</pubDate>
      <link>https://ruby-china.org/topics/14311</link>
      <guid>https://ruby-china.org/topics/14311</guid>
    </item>
    <item>
      <title>想轻易的做内存压力测试吗?  告诉你一段代码, 轻易的搞死你的 Linux.</title>
      <description>&lt;p&gt;好吧，其实是写代码时，误操作造成的副作用，但是我发现有个好处，它可以轻易的在很段时间，耗光我的 8GB 内存，
还让你没办法 C-c ... 然后，你会发现，你甚至无法正常关机了，因为你没有足够的内存来关机...&lt;/p&gt;

&lt;p&gt;定义一个函数：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;a&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;    &lt;span class="si"&gt;$(&lt;/span&gt;a&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后 a &amp;amp;&lt;/p&gt;

&lt;p&gt;原理解释：function a 会启动一个 &lt;code&gt;子 shell&lt;/code&gt;,  在子 shell 下再次调用 function a, 递归无穷尽也....
如果你的系统够快，你可以 ps 一下，你会看到无数个 bash 进程.. &lt;/p&gt;</description>
      <author>zw963</author>
      <pubDate>Mon, 23 Sep 2013 00:51:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/14304</link>
      <guid>https://ruby-china.org/topics/14304</guid>
    </item>
  </channel>
</rss>
