Trivial trick for looking at complex code

H

Hal Fulton

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

Jamis Buck

Hal said:
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. :)
Definately something to remember.

Thanks for sharing. :)

- Jamis
 
C

Curt Hibbs

Hal said:
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
 
B

Brian Schröder

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.

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
 
R

Ralph Amissah

I have grown fond of glark
http://glark.sourceforge.net/
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
 
J

Jim Weirich

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.
 
L

Lothar Scholz

Hello Jim,


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

JW> 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.
 
R

Randy W. Sims

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




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>
2. <http://cedet.sourceforge.net/speedbar.shtml>
 
R

Ralph Amissah

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,141
Messages
2,570,817
Members
47,364
Latest member
Stevanida

Latest Threads

Top