On Sat, 13 Nov 2004 08:30:44 +0900, Hal Fulton <hal9000 / hypermetrics.com> wrote:
> I was looking at some really complex code today (someone else's) and
> felt a need to see its structure a little better.
>
> You'd be surprised how helpful this is:
>    grep -E "^ *(class|module|attr|def)" file.rb
>
> It shows fairly clearly all the hierarchies, the method signatures,
> and the attributes.
>
> That's making certain assumptions about common coding style.
>
> Below is an example of running it against cgi.rb...
>
> OK, it's not rocket science, but I felt like sharing it.
>
> Hal
>
> class CGI
>    def env_table
>    def stdinput
>    def stdoutput
>    def CGI::escape(string)
>    def CGI::unescape(string)
>    def CGI::escapeHTML(string)
>    def CGI::unescapeHTML(string)
>    def CGI::escapeElement(string, *elements)
>    def CGI::unescapeElement(string, *elements)
>    def CGI::rfc1123_date(time)
>    def header(options = "text/html")
>    def out(options = "text/html") # :yield:
>    def print(*options)
>    class Cookie < SimpleDelegator
>      def initialize(name = "", *value)
>      attr_accessor("name", "value", "path", "domain", "expires")
>      attr_reader("secure")
>      def secure=(val)
>      def to_s
>    def Cookie::parse(raw_cookie)
>    def CGI::parse(query)
>    module QueryExtension
>        define_method(env.sub(/^HTTP_/n, '').downcase) do
>        define_method(env.sub(/^HTTP_/n, '').downcase) do
>      def raw_cookie
>      def raw_cookie2
>      attr_accessor("cookies")
>      attr("params")
>      def params=(hash)
>      def read_multipart(boundary, content_length)
>            define_method(:original_filename) {filename.dup.taint}
>            define_method(:content_type) {content_type.dup.taint}
>      def read_from_cmdline
>      def initialize_query()
>      def multipart?
>      module Value    # :nodoc:
>        def set_params(params)
>        def [](idx, *args)
>        def first
>        def to_a
>      def [](key)
>      def keys(*args)
>      def has_key?(*args)
>    def CGI::pretty(string, shift = "  ")
>    module TagMaker # :nodoc:
>      def nn_element_def(element)
>      def nOE_element_def(element, append = nil)
>      def nO_element_def(element)
>    module HtmlExtension
>      def a(href = "") # :yield:
>        attributes = if href.kind_of?(String)
>      def base(href = "") # :yield:
>        attributes = if href.kind_of?(String)
>      def blockquote(cite = nil)  # :yield:
>        attributes = if cite.kind_of?(String)
>      def caption(align = nil) # :yield:
>        attributes = if align.kind_of?(String)
>      def checkbox(name = "", value = nil, checked = nil)
>        attributes = if name.kind_of?(String)
>      def checkbox_group(name = "", *values)
>      def file_field(name = "", size = 20, maxlength = nil)
>        attributes = if name.kind_of?(String)
>        attributes["MAXLENGTH"] = maxlength.to_s if maxlength
>      def form(method = "post", action = script_name, enctype = 
> "application/x-www-form-urlencoded")
>        attributes = if method.kind_of?(String)
>      def hidden(name = "", value = nil)
>        attributes = if name.kind_of?(String)
>      def html(attributes = {}) # :yield:
>          attributes = {}
>          attributes = { "PRETTY" => true }
>            attributes.delete("DOCTYPE")
>      def image_button(src = "", name = nil, alt = nil)
>        attributes = if src.kind_of?(String)
>      def img(src = "", alt = "", width = nil, height = nil)
>        attributes = if src.kind_of?(String)
>        attributes["WIDTH"] = width.to_s if width
>        attributes["HEIGHT"] = height.to_s if height
>      def multipart_form(action = nil, enctype = "multipart/form-data")
>        attributes = if action == nil
>      def password_field(name = "", value = nil, size = 40, maxlength = nil)
>        attributes = if name.kind_of?(String)
>        attributes["MAXLENGTH"] = maxlength.to_s if maxlength
>      def popup_menu(name = "", *values)
>      def radio_button(name = "", value = nil, checked = nil)
>        attributes = if name.kind_of?(String)
>      def radio_group(name = "", *values)
>      def reset(value = nil, name = nil)
>        attributes = if (not value) or value.kind_of?(String)
>      def submit(value = nil, name = nil)
>        attributes = if (not value) or value.kind_of?(String)
>      def text_field(name = "", value = nil, size = 40, maxlength = nil)
>        attributes = if name.kind_of?(String)
>        attributes["MAXLENGTH"] = maxlength.to_s if maxlength
>      def textarea(name = "", cols = 70, rows = 10)  # :yield:
>        attributes = if name.kind_of?(String)
>    module Html3 # :nodoc:
>      def doctype
>      def element_init
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>    module Html4 # :nodoc:
>      def doctype
>      def element_init
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>    module Html4Tr # :nodoc:
>      def doctype
>      def element_init
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>    module Html4Fr # :nodoc:
>      def doctype
>      def element_init
>            def #{element.downcase}(attributes = {})
>            def #{element.downcase}(attributes = {})
>    def initialize(type = "query")
>

Also useful to fold a Ruby file in just that way in an editor
for the same reason. That's the way your file would be presented by default on
my opening it in vim, ie in folds (other editors i am sure do the same):

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/119595

Though the rc file may be more complicated to fold in this way as set up
is just:

  ,ff

as you say not rocket science but useful... and just as useful for
looking at your own files (in an editor), as those of others.

Ralph