これを動かしてみたくなった。

スーパーマリオブラザーズをRubyで作ってみた - I am Cruby!

まず、portsでSDLを入れる。

℗ sudo port install libsdl +quartz
℗ sudo port install libsdl_image libsdl_mixer libsdl_ttf rb-rubysdl

つぎに、こちらのサイトを参考にrsdlのソースをコンパイルして、バイナリをパスの通ったどこかに置く。

℗ wget http://www.kum...
℗ tar zxf rsdl[TAB]
rsdl/        rsdl.tar.gz

あ、あれ?

℗ which rsdl
/opt/local/bin/rsdl

ひゃぁ、入ってる。

本来はこうなったはず。

$ ./configure.rb
$ make
$ cp ./rsdl ....#どこかパスの通ったところ。

これで、

ꐪ rsdl -Irskit main.rb  

で起動できて遊べるのだが、ブロックの上のクリボーを下からたたくと落ちる。 SGEが無いらしい。

macportsにはいらっしゃらないうえに、素直にはmakeできないとか。 こちらこちらを参考に、Makefileにパッチを当てればOKらしい。 二度と見たくないので、Portfileを作ってcodereposに置いておいた。

適当な場所にsvn coして、

/opt/local/etc/macports/sources.confに次の一行を加える。(パスはcoしたパス)

# /opt/local/etc/macports/sources.conf
file:///Users/.../coderepos/config/ports/ [nosync]

さらに、portsディレクトリの中でportindexすれば使えるようになる。

ꐪ sudo port install libsdl_sge

念のためRuby/SDLを入れ直して、めでたしめでたし。 動いた。 mariobros

参考:


QRコードをPostScriptで吐き出す、という話。

QRコード自体の生成には、libqrencode, PostScript 生成には、cairo を利用している。

友人曰く、IllustratorでQRコードをパスとして扱うには、数万円するプラグインを買うか(結構高機能)、ラスター画像をトレースするのが一般的なんだとか。 えぇぇ。

そんなこんなで作りました。betaだよ。

QRコードジェネレータ(PostScript版)

参考:

RubyInline with pkg-config

投稿者 nanki 2008-03-04 16:10:00 GMT

qrencoder.rbにこんなコード足した。

  builder.add_compile_flags "-I `pkg-config --variable=includedir libqrencode`"
  builder.add_link_flags "`pkg-config --libs libqrencode`"

プログラミング言語 purl を ruby で実装

投稿者 nanki 2008-02-21 01:40:00 GMT

言語処理系を実装するのは、初めて(だと思う)

PostScript などと同じ逆ポーランド風の言語で、画像処理用途。

以下purlのソース。

2:load:dup:2:shadow:swap:composite:geom:1:load:100:100:4:pull:4:pull:crop:swap:composite:to.png

:がリテラルの区切り、その他は数字と演算子。 上のコードでは、2番の画像をロードして、ドロップシャドウしたものに1番の画像を背景として合成している。

ソースコード中に改行は入れられない。何故ならコードはURLの一部だから…

sample


DoCoMoのラジオボタン

投稿者 nanki 2008-02-20 11:40:00 GMT

DoCoMo機から

<input type='radio' checked='checked' name='id' value=''/>

を送信すると、id=’on’ が送られてくるようだ。

.blank? を使って判定してると危険。

詳細情報求ム。


ターミナルで色づけ

投稿者 nanki 2008-02-02 03:37:00 GMT

手軽に使えるフィルタコマンドが欲しかったので、rubyで書いた。

$ gem install term-ansicolor した後、

☶ cat public/javascripts/prototype.js |color red -- function |color yellow -- return | tail

terminal-color-filter

参考:

/lang/ruby/misc/color - CodeRepos::Share - Trac


named routesでtransit_sidが動かない

投稿者 nanki 2008-02-01 11:50:00 GMT

person_urlとかにsession_idがつかないと思ったら、最適化のためのコードが、defaulturloptionsを無視するらしい。

#10925 (Routing optimization, named routes missing default url options) - Rails Trac - Trac


Re: netswitch! | vim/rubyのための部分最適化

投稿者 nanki 2008-01-26 21:39:00 GMT

Re: netswitch! | vim/rubyのための部分最適化

今はこんな風になっている。

function SymbolUnderCursor(tran)
  return synIDattr(synID(line("."),col("."), a:tran),"name")
endfunction

function SmartSemicolon()
  execute "normal a "
  try
    throw SymbolUnderCursor(1)
  catch /rubyString\|rubyRegexp/
    execute "normal r;"
  catch /.*/
    execute "normal xo \<BS>"
  endtry
endfunction

function SmartEnd()
  execute "normal a1"
  try
    throw SymbolUnderCursor(0)
  catch /rubyString\|rubyRegexp\|rubyLocalVariableOrMethod/
    execute "normal xae\<Esc>and"
  catch
    execute "normal xae\<Esc>and\<Enter> \<BS>"
  endtry
endfunction
  
    
function SmartDefine()
  try
    throw SymbolUnderCursor(1)
  catch /rubyDefine/
    execute "normal oe\<Esc>and\<Esc>k"
  catch
  endtry 
endfunction
    
au FileType ruby imap <buffer> begin begin<Enter>
au FileType ruby imap <buffer> end  <Esc>:call SmartEnd()<CR>a
au FileType ruby imap <buffer> then then<Enter>
au FileType ruby imap <buffer> ensure ensure<Enter>
au FileType ruby imap <buffer> else else<Enter>
au FileType ruby imap <buffer> elsif elsif<Enter>
au FileType ruby imap <buffer> ; <Esc>:call SmartSemicolon()<CR>a
au FileType ruby imap <buffer> def def<Esc>:call SmartDefine()<CR>a
追記:
  • rubyRepeat追加

BenchmarkForRails導入でrakeが動かない

投稿者 nanki 2007-12-28 11:10:00 GMT
 ♞ rake test:units
(in /Users/nanki/work/...../trunk)
rake aborted!
undefined method `watch' for BenchmarkForRails:Module

これは困った。

AutoLoadingがうまくいっていないようだが、この手の問題は追跡が難しい。 とりあえず適当な箇所で、require 'benchmark_for_rails'しておけば大丈夫だが、気持ち悪いので次の日原因を追ってみた。

p追跡の結果だけ書くと、rake 実行時に読み込まれるlogs.rake冒頭でのrequireで、BenchmarkForRailsモジュールが初期化されて、本来読まれて欲しいはずの、benchmark_for_rails.rbがロードされないのが問題。

# in vendor/plugins/benchmark_for_rails/tasks/logs.rake
require File.dirname(__FILE__) + '/../lib/parsing.rb'
require File.dirname(__FILE__) + '/../lib/report.rb'

対処法はこちらの通り。

と思ったら、今朝五時に直ってるじゃないの。

参考:


Kanasan.JS#2

投稿者 nanki 2007-12-11 00:34:00 GMT

朝九時から夜九時まで、prototype.jsを読む、という勉強会が開催されていたので、夕方の数時間だけオンラインで参加。 読んでいるソースのバージョンが違っていて、行数指定の話の内容を勘違いしていた。

僕が読んだ範囲は、prototype.js v1.6.0 l.587 - l.1193, Enumerable - Ajax.Baseまで。

Kanasan.JS本体の人はもっと広いはず。

Enumerable

l.587

Rubyと似たのが多いので、ほとんど違和感無く読める。 each の実装は_eachのみに依存して、他のメソッドはeachのみに依存している。

l.775

zipの実装がなかなか素敵。

こんな使い方。

>> [1, 2, 3].zip([1, 2, 3], [1, 2, 3]);
[[1, 1, 1], [2, 2, 2], [3, 3, 3]]

>> var sum = function(r,m) { return r + m };
>> [1, 2, 3].zip([1, 2, 3], [1, 2, 3], function(e){return e.inject(0, sum)})
[3, 6, 9]
// l.775
  zip: function() {
    var iterator = Prototype.K, args = $A(arguments);
    if (Object.isFunction(args.last()))
      iterator = args.pop();

    var collections = [this].concat(args).map($A);
    return this.map(function(value, index) {
      return iterator(collections.pluck(index));
    });
  }

[this].concat(args).map($A)と、collections.pluck(index) がキモ。

Array

l.813

WebKitでは、NodeList#toArrayにネイティブ実装を使う。 できれば、パフォーマンスのためのコードは、一目でわかるようにしておいて欲しいorおきたい。 パフォーマンスのためなのか、互換性のためなのかがわからない。(できればかかわりたくない)

l.837

this.length = 0;で配列の初期化ができるとは、知らなかった。 ちなみに、元の長さより長くすると、undefinedでpadされる。

l.877

array.uniq遅そう。 arrayがソート済みの場合、array.uniq(true)でずいぶん速くなりそう。 次のintersectもdetectで遅そうだけど、arrayはEnumerableであれば何でもよさそうなので、これでいいか。 気をつけて使う。 Enumerableって、極端な話、each実行するたびに結果が違ってもいいんだもんな。

Number

l.956

toColorPart:0-255の値を2桁16進にするためのコード。

l.979

Math.ceil とかをNumber#ceilにしてる。methodize().

Hash

l.987

いきなりのif文がわけわからないが、なにかの挙動の違いで、パフォーマンスをあげようとしているのだろうか。 v1.6.0.1ではなくなっているので、あまり気にしないで読み進む。

eachの中で、pair.key, pair[0] の両方のアクセス方法を許すようなコードが書かれている。

l.1016

この書き方(無名関数の中で関数を作って、return でオブジェクトを返す)は、JavaScriptでプライベート関数を実現するイディオムのようなもので、 この場合は、toQueryPairは、外からはアクセスできない。

1.5時代のソースも見てみると、Hashががらりと変わっていることに気がつく。 1.5では、値をthis自身に、1.6では、値をthis._objectに格納している。

// 1.5
$H({a: 3})["a"] // => 3

// 1.6
$H({a: 3})["a"] // => undefined
$H({a: 3}).get("a") // => 3
$H({a: 3}).toObject()["a"] // => 3

うーん、これは結構使ってしまっている気がするんだなぁ。

l.1072

toQueryString 突然のcurryに緊張が走る。 配列をQueryStringに変換する際、toQueryPairの第一引数を固定しているだけのようだ。

>> $H({a: [1,2,3]}).toQueryString()
"a=1&a=2&a=3"

そういえば、最近、近所の交差点がcurry激戦区になりつつある。

l.1100

toTemplateReplacements. どうも、1.5, 1.6間でHashの実装が大きく変わったのは、これが原因のような気もする、この関数。 evaluateの中で勝手に呼ばれるので、気にする事はない。

//v1.5
>> (new Template("hello #{name} #{each}.")).evaluate($H({name: 'ujihisa'}))
"hello ujihisa function (iterator) {
....
...
}."

//v1.6
>> (new Template("hello #{name} #{each}.")).evaluate($H({name: 'ujihisa'}))
"hello ujihisa ."

ObjectRange

RubyのRangeみたいなの。 Range だと、DOMのRangeとかぶるので、ObjectRangeらしい。 exclusiveは、最後の要素を含まないか含むか。

start, endは、比較可能で、succが実装されていれば何でもよい。 比較も、オーバライド可能なメソッドにしてほしいな。

Arrayは比較可能なので、Array.prototype.succを実装すると、ObjectRangeで使えるようになると思う。 あんまり意味なさそうだけど。

$R("a", "c").map()
// => ["a", "b", "c"]

Array.prototype.succ = function() {
  var clone = this.clone();
  clone.push(this.last());
  return clone;
}

$R([1], [1,1,1]).map()
// => [[1], [1, 1], [1, 1, 1]]

Ajax.Responders

Ajaxのリクエストに関するイベントリスナを管理している。

l.1162

なぜapplyの第一引数がresponderなのか、という話題になる。 たぶん、こういう使い方をしたいから、という気がする。

Ajax.Responders.register({onComplete: function () { Ajax.Responders.unregister(this)}});

Ajax.Base

あんまり読みどころがない。 目がAjax.Requestの中の$superを見つけてしまう。なんだこれ。

$super

  initialize: function($super, url, options) {
    $super(options);

という使われ方から、親クラスのメソッドを呼び出す関数だというのはわかるのだが・・・

$superで検索すると、文字列として見つかる。あやしい。

  1. value には関数が入る。
  2. value.argumentNames()で関数宣言のソース文字列を正規表現でパースし、引数のリストを取得して、
  3. 第一引数が$superならば、その関数を置き換えている。
  4. function() { return ancestor[m].apply(this, arguments) }; が$superの中身。
  5. wrapで、method(arg1, arg2) という呼び出しを、method($super, arg1, arg2) に置き換えつつ、
  6. 置き換えた事を悟られないように、toString, valueOfをオーバーライドしている。

嘘を嘘で塗り固めたような・・・。

//l.76
Class.Methods = {
  addMethods: function(source) {
    var ancestor   = this.superclass && this.superclass.prototype;
    var properties = Object.keys(source);

    if (!Object.keys({ toString: true }).length)
      properties.push("toString", "valueOf");

    for (var i = 0, length = properties.length; i < length; i++) {
      var property = properties[i], value = source[property];
      if (ancestor && Object.isFunction(value) &&
          value.argumentNames().first() == "$super") {
        var method = value, value = Object.extend((function(m) {
          return function() { return ancestor[m].apply(this, arguments) };
        })(property).wrap(method), {
          valueOf:  function() { return method },
          toString: function() { return method.toString() }
        });
      }
      this.prototype[property] = value;
    }

    return this;
  }
};

本筋とは関係ないけど、if (!Object.keys({ toString: true }).length) というコードを見ると、一瞬困惑するRuby脳。

おまけ

l.1222

      else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
        params += '&_=';

この謎の&_=、Safariのどれかのバージョンで、POSTのリクエストの後ろに変な文字列をつけるバグへの対策らしい。&_=........となるので、切り捨てられる。

参考: