2005年2月 8日

JavaScript でインクリメンタル 検索 (grepではない版)

JavaScript でインクリメンタル grep 検索 のコードでは、検索に正規表現をそのまま使っています。正規表現を使うと pr.*f のような検索ができるのですが、一方で、 . や * や ( などを検索するにはそれぞれ \ でエスケープする必要が生じます。そのことを知らないと「(*.*) がなぜか検索できねー」と混乱することになります。

正規表現を使えてもうれしいことはそんなになさそうなので、gonzui では次のような関数を作って、メタ文字をエスケープしてから検索をかけるようにしました。

 
function quotemeta (string) {
    return string.replace(/(\W)/, "\\$1");
}
quotemeta を使ったインクリメンタル検索のコードは次のようになります。
function isearch (pattern) {
    var regex = new RegExp(quotemeta(pattern), "i");
    var spans = document.getElementsByTagName('span');
    var length = spans.length;
    for (var i = 0; i < length; i++) {
        var e = spans[i];
        if (e.className == "line") {
            if (e.innerHTML.match(regex)) {
                e.style.display = "inline";
            } else {
                e.style.display = "none";
            }
        }
    }
}

isearch: (def などと打ってみてください)

# Ruby 1.8.2 (2004-08-24) に付属の pp.rb から抜粋:
   346        class Struct
   347          def pretty_print(q)
   348            q.group(1, '#<struct ' + self.class.name, '>') {
   349              q.seplist(self.members, lambda { q.text "," }) {|member|
   350                q.breakable
   351                q.text member.to_s
   352                q.text '='
   353                q.group(1) {
   354                  q.breakable ''
   355                  q.pp self[member]
   356                }
   357              }
   358            }
   359          end
   360
   361          def pretty_print_cycle(q)
   362            q.text sprintf("#<struct %s:...>", self.class.name)
   363          end
   364        end
   365
   366        class Range
   367          def pretty_print(q)
   368            q.pp self.begin
   369            q.breakable ''
   370            q.text(self.exclude_end? ? '...' : '..')
   371            q.breakable ''
   372            q.pp self.end
   373          end
   374        end

追記
2005-04-05: for (i in spans) という構文が Safari だと動かないという 指摘をいただいたので length = spans.length; for (i = 0; i < length; i++) に修正しました。