読者です 読者をやめる 読者になる 読者になる

[ruby] p_classtree、改良(Ruby実行中にクラス階層、メソッドを見やすく表示する)

※ 前回記事はコチラ

id:keyesberry さんのありがたいコメントのおかげで、アルファベットと記号の優先を落としてソートする方法が分かりました!group_byってすげー。
はてなブックマークにも別実装を書いてくれた方がいました、ありがとうございます。

p_classtreeという関数にオブジェクトやクラスを渡すと・・。

# インスタンスを渡した場合はその所属するクラスの階層、メソッドを表示
a = [0, 1, 2]
p_classtree(a)
puts

# クラス名を直接渡してもOK
p_classtree(Hash)

結果はこんな感じで表示されます。

Array
|  assoc, at, choice, clear, collect, 
|  collect!, combination, compact, compact!, concat, 
|  count, cycle, delete, delete_at, delete_if, 
|  drop, drop_while, each, each_index, empty?, 
|  eql?, fetch, fill, find_index, first, 
|  flatten, flatten!, frozen?, hash, include?, 
|  index, indexes, indices, insert, inspect, 
|  join, last, length, map, map!, 
|  nitems, pack, permutation, pop, product, 
|  push, rassoc, reject, reject!, replace, 
|  reverse, reverse!, reverse_each, rindex, select, 
|  shift, shuffle, shuffle!, size, slice, 
|  slice!, sort, sort!, take, take_while, 
|  to_a, to_ary, to_s, transpose, uniq, 
|  uniq!, unshift, values_at, zip, 
↓  &, *, +, -, <<, <=>, ==, [], []=, |, 
Object

Fixnum
|  abs, div, divmod, even?, fdiv, 
|  id2name, modulo, odd?, quo, size, 
|  to_f, to_s, to_sym, zero?, 
|  %, &, *, **, +, -, -@, /, <, <<, 
↓  <=, <=>, ==, >, >=, >>, [], ^, |, ~, 
Integer
|  ceil, chr, downto, even?, floor, 
|  integer?, next, odd?, ord, pred, 
|  round, succ, times, to_i, to_int, 
↓  truncate, upto, 
Numeric
|  abs, ceil, coerce, div, divmod, 
|  eql?, fdiv, floor, integer?, modulo, 
|  nonzero?, quo, remainder, round, singleton_method_added, 
|  step, to_int, truncate, zero?, 
↓  +@, -@, <=>, 
Object

ソース

# -*- coding: utf-8 -*-
#
# @file 
# @brief  p_classtree 改良版
# @author ongaeshi
# @date   2010/09/30

# アルファベットと演算子で表示する数を変える
ALPHABET_DISP_NUM = 5
OPERATOR_DISP_NUM = 10

def p_classtree(c)
  unless c.is_a?(Class)
    c = c.class
  end
  
  while (true)
    puts c.name
    break if (c == Object)
    p_classtree_sub(c)
    c = c.superclass
  end
end

def p_classtree_sub(c)
  hash = c.public_instance_methods(false).sort.group_by { |m| m =~ /^[a-z]/ }
  array = hash.values.flatten
  operator_start_index = hash[0].size
  limit = ALPHABET_DISP_NUM

  print (array.size > limit) ? "" :  ""
  
  counter = 0
  array.each_with_index do |v, index|
    if (index == operator_start_index)
      limit = OPERATOR_DISP_NUM
      counter = 0
      puts
      print (array.size - index > limit) ? "" : ""
    end

    if (counter >= limit)
      counter = 0
      puts
      print (array.size - index > limit) ? "" : ""
    end

    print v + ", "
    counter += 1
  end
  puts
end

if __FILE__ == $0
  # インスタンスを渡した場合はその所属するクラスの階層、メソッドを表示
  a = [0, 1, 2]
  p_classtree(a)
  puts

  # クラス名を直接渡してもOK
  p_classtree(Fixnum)
  puts
  p_classtree(Bignum)
end