class Mkgraph

Example : Mkgraph#new <ruby.rb> - initialise

Mkgraph#run           - process file
Mkgraph#make_image    - create the image file
Mkgraph#show_image    - display the image file

Arguments: The file to be visualised when creating a new instance

Note : A valid mgopts.yml must be in the working directory.

You could copy a template file from the gem installation directory.

Public Class Methods

new(pattern) click to toggle source

Initialise

Params: The name of the file to be processed

    # File lib/mkgraph.rb
 34   def initialize pattern
 35 
 36     begin
 37       $yml = YAML.load_file 'mgopts.yml'
 38     rescue Exception => e
 39       print e.message + "\n"
 40       print "You could use the default \'mgopts.yml\' file in the installation\n"
 41       print "directory as a template.\n"
 42       print "Example:\n"
 43 
 44       tip = <<-EOS
 45         Log Options:
 46           format: brief   # brief or full
 47           output: stderr  # stderr, stdout or file name
 48           level: WARN     # INFO, WARN or FATAL
 49         Labels:
 50           root: Entry Point
 51           root comment: The Root Comment
 52         Output:
 53           image name: view.png      
 54       EOS
 55 
 56       puts "#{tip}"
 57       exit 1
 58     end
 59 
 60     # puts $yml['sectionA']['user'] + "**************\n"
 61     # puts $yml['sectionB']['file'] + "**************\n"
 62     log_fmt = $yml['Log Options']['format']
 63 
 64     log_opt = $yml['Log Options']['output']
 65     case log_opt
 66     when 'stderr'
 67       log_op = $stderr
 68     when 'stdout'
 69       log_op = $stdout
 70     else
 71       log_op = log_opt
 72     end
 73 
 74     loglev = $yml['Log Options']['level']
 75     case loglev
 76     when 'INFO'
 77       ll = Logger::INFO
 78     when 'WARN'
 79       ll = Logger::WARN
 80     else
 81       ll = Logger::FATAL
 82     end
 83 
 84     @file_pattern = pattern
 85 
 86     $LOG = Logger.new(log_op).tap do |log|
 87       log.progname = 'mkgraph'
 88       log.level = ll # Logger::INFO # $yml['Log Options']['level']
 89       if log_fmt == 'brief'
 90         log.formatter = proc do |severity, datetime, progname, msg|
 91           "#{progname}: #{msg}\n"
 92         end
 93       end
 94     end
 95 
 96     $LOG.info "Pattern: " + @file_pattern
 97     # Rough test for OS TODO
 98     if RUBY_PLATFORM.include?("linux") == false
 99       $windows = true
100     else
101       $windows = false
102     end
103   end

Public Instance Methods

make_image() click to toggle source

Use Graphviz to create the image file

    # File lib/mkgraph.rb
278 def make_image 
279   g = GraphViz.new( :G, :rankdir => "TB", :type => :digraph, :bgcolor => "lightgrey", :nodesep => 0.85, :normalize => true, :concentrate => true)
280   root = $root_node
281   g = add_element g, root
282   if $windows != true
283     res = system("rm " + $iname + " > /dev/null")
284   end
285   begin
286     g.output( :png => $iname)
287   rescue Exception => e
288     $LOG.warn e.message + "\n"
289   end
290 end
run() click to toggle source

Does the work. Params: None

    # File lib/mkgraph.rb
109 def run
110   end_count           = 0
111   end_expected        = 0            # how many ends before class end
112   class_end_expected  = 0            # how many class ends we expect (internal definitions)
113   cname               = ""
114   in_class            = false
115   parent_class_name   = nil
116   print_parent        = true
117 
118   $iname = $yml['Output']['image name']
119 
120   $root_node = Tree::TreeNode.new($yml['Labels']['root'], $yml['Labels']['root comment'])
121   tnode = $root_node
122 
123   # Process all file matching @file_pattern
124   Dir.glob(@file_pattern) do |file|
125 
126     $LOG.info "Looking at file - " + file
127     ignore = false
128 
129     next if file == '.' or file == '..'
130 
131     # Process each line in the file
132     File.open(file) do |f|
133       f.each_line do |line|
134 
135         # Ignore =begin/=end blocks
136         if line.match(/^=end/) != nil
137           ignore = false
138         elsif line.match(/^=begin/) != nil
139           ignore = true
140         else
141           nil
142         end
143 
144         next if ignore == true
145 
146         # Process the line read from file
147         case line
148         when /^\s*#/
149           nil
150         when /\s*when.*new/     # only to avoid this situation HERE
151           nil
152         when /\'\.new/          # only to avoid the situation in line.split('.new')
153           nil
154         when /\.new/
155           name = line.split('.new')
156           cname = name[0].split.last
157           if in_class == true
158             $LOG.debug "NEW INSTANCE OF CLASS = [" + cname + "] created in class " + parent_class_name
159             tnode = proc_node tnode, parent_class_name, cname, false, false
160           else
161             if true == print_parent
162               $LOG.debug "NEW INSTANCE OF CLASS = [" + cname + "] created outside any parent class"
163               tnode = proc_node tnode, parent_class_name, cname, true, true
164             end
165           end
166         when /^\s*elsif/
167           nil
168         when /^\s*class[\s]+/
169           parent_class_name = line.split(' ')[1]
170           class_end_expected += 1
171           in_class = true
172           if print_parent == true
173             $LOG.info "Start of class " + parent_class_name
174           end
175           tnode = proc_node tnode, $root_node.name, parent_class_name, true, false
176         when /^\s*begin/
177           end_expected += 1
178         when /^.*if /
179           end_expected += 1
180         when /^\s*def /
181           end_expected += 1
182         when /^.* do/
183           end_expected += 1
184         when /^\s*case/
185           end_expected += 1
186         when /^\s*end[\s.]/
187           if end_expected == 0
188             if class_end_expected > 0
189               class_end_expected -= 1
190               in_class = false
191               if print_parent == true && parent_class_name != nil
192                 $LOG.info "End of class " + parent_class_name
193               end
194               parent_class_name = nil
195             end
196           else
197             end_expected -= 1
198           end
199         end      # case
200       end
201     end
202   end    
203 end
show_image() click to toggle source

Display the image file

    # File lib/mkgraph.rb
293 def show_image 
294   begin
295     if $windows != true
296       res = system("pkill eog; " + $yml['Osdep']['viewer'] + " " + $iname + " > /dev/null 2>&1")
297     else
298       res = system("call " + $yml['Osdep']['viewer'] + " " + $iname)
299     end
300     if res == false
301       raise "Bad Command"
302     end
303   rescue Exception => e
304     $LOG.info e.message
305   end
306 end

Private Instance Methods

add_element(g, root) click to toggle source

Recursive method to add elements from the Tree to the GraphViz Tree

    # File lib/mkgraph.rb
251 def add_element g, root
252   if root.hasChildren? == true
253     root.children { |child|
254       add_element g, child
255     }
256   end
257 
258   if root.isRoot?
259     g.add_node root.name, {:label => "{{" + root.name + "|" + root.content + "}|" + "Root}", :style => "filled", :fillcolor => "lightblue", :shape => "record", :color =>"black"}
260   else
261     g.add_node root.name , {:shape => "egg", :color =>"violet"}
262   end
263 
264   if ! root.isRoot?
265     # Add an edge to the parent
266     if root.content == "orphan"
267       g.add_edge(root.parent.name, root.name, :label => root.parent.name + " contains " + root.name, :color => "red", :fontcolor => "red")
268     else
269       g.add_edge(root.parent.name, root.name, :label => root.parent.name + " uses " + root.name, :color => "blue", :fontcolor => "blue")
270     end
271 
272   end
273   g
274 end
find_leaf(root, sname) click to toggle source

Recursive method used to find a name (ID) in the Tree object

    # File lib/mkgraph.rb
207 def find_leaf root, sname
208 
209   $LOG.debug "find_leaf searching for: [" + sname + "] This Root is " + root.name
210   r = root
211 
212   if root != nil && root.name != sname
213     root.children { |child|
214       r = find_leaf child, sname
215       break if r.name == sname
216     }
217   else
218     $LOG.info "NIL OR FOUND [" + root.name + "]"
219     r = root
220   end
221   $LOG.info "find_leaf returning: [" + r.name + "]"
222   r
223 end
proc_node(root, par, child, join_to_root, used) click to toggle source

Process a line of interest i.e. when a class is being defined or instanciated etc. Called from the ‘run’ method

    # File lib/mkgraph.rb
227 def proc_node root, par, child, join_to_root, used
228   begin
229     if join_to_root == true
230       if true == used
231          $root_node << Tree::TreeNode.new(child, "child")
232       else
233          $root_node << Tree::TreeNode.new(child, "orphan")
234       end
235     else
236       $LOG.info "NEED TO ATTACH " + child + " TO: " + par
237       r = find_leaf root, par
238       $LOG.info "AFTER FIND_LEAF: " + r.name
239       r << Tree::TreeNode.new(child, "used")
240     end
241   rescue Exception => e
242     $LOG.info e.message
243     $LOG.info "***** Processing node " + "None" + " --> " + child.to_s
244   end
245   # $root_node.printTree
246 
247   root
248 end