Trivial trick for looking at complex code

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
     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 = {})
   module Html4 # :nodoc:
     def doctype
     def element_init
           def #{element.downcase}(attributes = {})
   module Html4Tr # :nodoc:
     def doctype
     def element_init
           def #{element.downcase}(attributes = {})
   module Html4Fr # :nodoc:
     def doctype
     def element_init
           def #{element.downcase}(attributes = {})
   def initialize(type = "query")

Hal Fulton 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.

Very slick, Hal! I just ran it through my Net::SSH stuff. Handy. :slight_smile: Definately something to remember.

Thanks for sharing. :slight_smile:

- Jamis

···

--
Jamis Buck
jgb3@email.byu.edu
http://www.jamisbuck.org/jamis

Hal Fulton 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.

I can't claim that this is as simple as your technique, but you could also
open the files in FreeRIDE. The navigation pane gives you the same info in a
collapsible tree, plus if you click on any entry (module, class, or method),
the edit pane is scrolled to that spot in the code and displayed with full
syntax highlighting.

Curt

Another method I use is
  
   rdoc -a -S -N -d

This gives a really nice overview, but has the drawback of requiring a browser.

Regards,

Brian

···

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.

--
Brian Schröder
http://www.brian-schroeder.de/

You'd be surprised how helpful this is:

   grep -E "^ *(class|module|attr|def)" file.rb

Oh, excellent! What a great way to outline your ruby code.

OK, it's not rocket science, but I felt like sharing it.

You can also do this in emacs ...

    M-X grep RET grep -n -RE "^ *(class|module|attr|def)" lib RET

And you will get a grep buffer with the tagged outline. Just middle mouse
click on any line in the grep buffer and emacs will automatically go to that
file and line number. Great for browsing code.

Thanks Hal.

···

On Friday 12 November 2004 06:30 pm, Hal Fulton wrote:

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

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

···

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")

I have grown fond of glark

a ruby enhanced grep (probably first read about on this list), so i do:

glark -F "blue bold on black" -T "red on black" -B 0 -A 0 \
  "^\s*(module|class|def|attr_|require|include)" file.rb

rather as that string is faily long, i have the following
function in my shell (zsh):

,glrb() { glark -F "blue bold on black" -T "red on black" -B 0 -A 0 \
  "^\s*(module|class|def|attr_|require|include)" $1 } # ,glrb file.rb

···

On Sat, 13 Nov 2004 19:11:44 +0900, Brian Schröder <ruby@brian-schroeder.de> wrote:

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.

Hello Jim,

···

On Friday 12 November 2004 06:30 pm, Hal Fulton wrote:

You'd be surprised how helpful this is:

   grep -E "^ *(class|module|attr|def)" file.rb

Oh, excellent! What a great way to outline your ruby code.

OK, it's not rocket science, but I felt like sharing it.

You can also do this in emacs ...

And you get this in ArachnoRuby by pressing "Control-W Control-N".
This is immediately updated after code changes and so can help you to
see where an 'end' is missing.

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

Jim Weirich wrote:

···

On Friday 12 November 2004 06:30 pm, Hal Fulton wrote:

You'd be surprised how helpful this is:

  grep -E "^ *(class|module|attr|def)" file.rb

Oh, excellent! What a great way to outline your ruby code.

OK, it's not rocket science, but I felt like sharing it.

You can also do this in emacs ...

    M-X grep RET grep -n -RE "^ *(class|module|attr|def)" lib RET

And you will get a grep buffer with the tagged outline. Just middle mouse click on any line in the grep buffer and emacs will automatically go to that file and line number. Great for browsing code.

In emacs, I like using imenu[1]. I just hold shift while pressing the right mouse button and I get a popup list of all classes and methods.
speedbar[2] is nice also, but it unfortunately doesn't have ruby support.

1. <http://www.emacswiki.org/cgi-bin/wiki/ImenuMode&gt;
2. <http://cedet.sourceforge.net/speedbar.shtml&gt;