# このURLから試せます。(ただしFirefoxに限る) # http://dl.dropbox.com/u/3622136/misc/typo/typo.html # # String::Trigram でテキストの類似度を測る # http://blog.livedoor.jp/techblog/archives/64737211.html # # ここを参考にメソッドが見つからなかったら名前が似てるメソッドを呼ぶようにした # ※ただし__noSuchMethod__がある処理系でのみ動きます # # Typoクラスを継承するとtypoしたメソッドを呼び出しても動く! class Ngram constructor: (@src) -> @cache = {} getNgram: (n) -> return @cache[n] if @cache[n]? index = 0 result = [] result.push @src.substr(index++, n) while (index < @src.length - 1) @cache[n] = result class Typo __noSuchMethod__: (id, args) -> method = new Ngram(id).getNgram(2) methods = ([p, new Ngram(p).getNgram(2)] for p in @allProperties this) threshold = 0.5 contain = (x, y) -> if x.indexOf(y) isnt -1 then 1 else 0 sum = (s, x) -> s + x similar = (one, another) -> count = (contain another, x for x in one).reduce sum count / one.length cmp = (a, b) -> if a[1] > b[1] then -1 else if a[1] < b[1] then 1 else 0 suggest = ([m[0], similar method, m[1]] for m in methods).sort(cmp)[0] if suggest[1] > threshold console.log "correct #{id} to #{suggest[0]}(#{suggest[1]})." this[suggest[0]].apply(this, args) else console.log "method #{id} is missing. You mean #{suggest[0]}(#{suggest[1]})?" allProperties: (o) -> names = [] while o? names = names.concat Object.getOwnPropertyNames(o) o = Object.getPrototypeOf(o) names class Hello constructor: (@name) -> @name ||= "world" message: (mes) -> alert "Hello, #{@name}!" class HelloTypo extends Typo constructor: (@name) -> @name ||= "world" message: (mes) -> alert "Hello, #{@name}!" try new Hello("hanachin").msesage() catch e console.log "error" new HelloTypo("hanachin").msesage() new HelloTypo("hanachin").msesagaaae()