├── .gemrc ├── lib ├── ruby-graphviz.rb ├── graphviz │ ├── family_tree │ │ ├── sibling.rb │ │ ├── generation.rb │ │ ├── couple.rb │ │ └── person.rb │ ├── types │ │ ├── html_string.rb │ │ ├── esc_string.rb │ │ ├── color_list.rb │ │ ├── arrow_type.rb │ │ ├── gv_double.rb │ │ ├── lbl_string.rb │ │ ├── rect.rb │ │ ├── gv_bool.rb │ │ ├── color.rb │ │ └── spline_type.rb │ ├── ext.rb │ ├── types.rb │ ├── elements.rb │ ├── core_ext.rb │ ├── dsl.rb │ ├── nothugly.rb │ ├── dot2ruby.rb │ ├── attrs.rb │ ├── dot_script.rb │ ├── utils.rb │ ├── family_tree.rb │ └── xml.rb └── ext │ └── gvpr │ └── dot2ruby.g ├── examples ├── dot │ ├── hello.dot │ ├── rank.dot │ ├── test_parse.rb │ ├── test.dot │ ├── cluster.dot │ ├── so-sample002.gv │ ├── so-sample001.gv │ ├── fsm.dot │ ├── hello_test.rb │ ├── balanced.dot │ ├── dotgraph.dot │ ├── JSP.dot │ ├── this_crach_with_dot_2.20.dot │ ├── so-sample003.gv │ ├── genetic.dot │ ├── lion_share.dot │ └── psg.dot ├── hello.png ├── sample66.rb ├── sdlshapes │ └── README ├── sample26.rb ├── sample27.rb ├── sample65.rb ├── sample47.rb ├── sample61.rb ├── sample59.rb ├── sample60.rb ├── sample31.rb ├── sample41.rb ├── sample24.rb ├── sample57.rb ├── sample16.rb ├── sample29.rb ├── sample49.rb ├── sample56.rb ├── sample39.rb ├── sample67.rb ├── sample25.rb ├── sample38.rb ├── sample55.rb ├── sample70.rb ├── sample21.rb ├── sample32.rb ├── sample28.rb ├── sample23.rb ├── sample22.rb ├── rgv │ ├── test_rgv.rb │ └── rgv.ps ├── sample74.rb ├── sample30.rb ├── sample40.rb ├── sample71.rb ├── sample73.rb ├── sample72.rb ├── sample69.rb ├── graphml │ ├── attributes.ext.graphml │ ├── hyper.graphml │ ├── port.graphml │ ├── simple.graphml │ ├── attributes.graphml │ ├── nested.graphml │ └── cluster.graphml ├── sample54.rb ├── sample34.rb ├── sample15.rb ├── sample53.rb ├── sample62.rb ├── sample04.rb ├── sample68.rb ├── sample63.rb ├── sample07.rb ├── sample64.rb ├── sample45.rb ├── sample01.rb ├── sample51.rb ├── sample58.rb ├── sample03.rb ├── sample05.rb ├── sample36.rb ├── test.xml ├── sample18.rb ├── sample11.rb ├── sample33.rb ├── sample43.rb ├── sample42.rb ├── sample06.rb ├── sample14.rb ├── sample02.rb ├── sample46.rb ├── sample35.rb ├── sample08.rb ├── sample12.rb ├── sample48.rb ├── theory │ ├── pert.rb │ └── tests.rb ├── sample13.rb ├── sample09.rb ├── sample10.rb ├── sample19.rb ├── sample44.rb ├── sample20.rb ├── sample99.rb ├── sample37.rb ├── sample52.rb └── sample17.rb ├── Gemfile ├── .travis.yml ├── .gitignore ├── test ├── helper.rb ├── test_subgraph.rb ├── test_search.rb ├── test_dot_script.rb ├── test_utils_colors.rb ├── test_types.rb ├── test_theory.rb ├── test_graph.rb └── test_examples.rb ├── .yardopts ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── man ├── xml2gv.1.ronn ├── git2gv.1.ronn ├── gem2gv.1.ronn ├── ruby2gv.1.ronn ├── git2gv.1 ├── xml2gv.1 ├── gem2gv.1 ├── ruby2gv.1 ├── dot2ruby.1.ronn └── dot2ruby.1 ├── Rakefile ├── ruby-graphviz.gemspec └── bin ├── dot2ruby ├── xml2gv ├── git2gv └── gem2gv /.gemrc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/ruby-graphviz.rb: -------------------------------------------------------------------------------- 1 | require 'graphviz' 2 | -------------------------------------------------------------------------------- /examples/dot/hello.dot: -------------------------------------------------------------------------------- 1 | digraph G {Hello->World;} -------------------------------------------------------------------------------- /examples/hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/glejeune/Ruby-Graphviz/HEAD/examples/hello.png -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in ruby-graphviz.gemspec 4 | gemspec -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | 3 | rvm: 4 | - 2.4.9 5 | - 2.5.7 6 | - 2.6.5 7 | - 2.7.0 8 | - jruby-9.2.9.0 9 | -------------------------------------------------------------------------------- /examples/sample66.rb: -------------------------------------------------------------------------------- 1 | $:.unshift("../lib") 2 | 3 | require 'graphviz' 4 | GraphViz.generate(30, 44, true, (1..8)).output(:png => "#{$0}.png") 5 | -------------------------------------------------------------------------------- /examples/sdlshapes/README: -------------------------------------------------------------------------------- 1 | PostScript library for SDL node shapes (http://www.sdl-forum.org/SDL/index.htm) 2 | by Mark Rison of Cambridge Silicon Radio Ltd. 3 | -------------------------------------------------------------------------------- /examples/dot/rank.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | subgraph { rank = same; "node1"; "node2"; } 3 | subgraph { rank = same; "nodeA"; "nodeB"; } 4 | node1 -> nodeA; 5 | node2 -> nodeB; 6 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | *.iml 4 | doc 5 | pkg 6 | test/output/ 7 | .rake_tasks 8 | .rbx 9 | Gemfile.lock 10 | .yardoc/ 11 | node_modules/ 12 | package-lock.json 13 | -------------------------------------------------------------------------------- /examples/sample26.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:G){ |g| 7 | (g.hello - g.world) [:style => :bold, :label => " axgle says"] 8 | }.save( :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample27.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | puts GraphViz.new(:G){ |g| 7 | (g.hello - g.none) [:style => :bold, :label => " dburt says"] 8 | }.save( :none => String ) 9 | -------------------------------------------------------------------------------- /examples/sample65.rb: -------------------------------------------------------------------------------- 1 | $:.unshift("../lib") 2 | 3 | require 'graphviz/dsl' 4 | digraph :G do 5 | world[:label => "World"] << hello[:label => "Hello"] 6 | #world << hello 7 | 8 | output :png => "#{$0}.png" 9 | end 10 | -------------------------------------------------------------------------------- /examples/sample47.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require 'graphviz/xml' 5 | 6 | gvxml = GraphViz::XML::new( File.join( File.dirname(__FILE__), "test.xml" ), :text => true, :attrs => true ) 7 | gvxml.graph.output( :png => "#{$0}.png", :use => "dot" ) 8 | -------------------------------------------------------------------------------- /examples/sample61.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | asm = GraphViz::new( "" ) 7 | 8 | my = asm.add_nodes("My") 9 | asmn = asm.add_nodes("ASM") 10 | asm.add_edges(my, asmn) 11 | 12 | asm.output( :png => "#{$0}.png" ) 13 | -------------------------------------------------------------------------------- /examples/sample59.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require "graphviz" 3 | 4 | graph = { 5 | "a" => { 6 | "b" => "d", 7 | "c" => ["e", "f", "a"] 8 | }, 9 | "g" => "e", 10 | } 11 | 12 | g = GraphViz::new( "G" ) 13 | g.add(graph) 14 | g.output( :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample60.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | asm = GraphViz::new( "My ASM" ) 7 | 8 | my = asm.add_nodes("My") 9 | asmn = asm.add_nodes("ASM") 10 | asm.add_edges(my, asmn) 11 | 12 | asm.output( :png => "#{$0}.png" ) 13 | -------------------------------------------------------------------------------- /examples/sample31.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:g){ |g| 7 | a = g.add_nodes( "A:B:C", :shape => :record ) 8 | b = g.add_nodes( "D:E:F", :shape => :ellipse ) 9 | a << b 10 | }.save( :png => "#{$0}.png" ) 11 | -------------------------------------------------------------------------------- /examples/dot/test_parse.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../../lib" ); 4 | require "graphviz" 5 | 6 | Dir.glob( "*.dot" ) { |f| 7 | puts "#{f} : " 8 | begin 9 | puts GraphViz.parse(f) 10 | rescue SyntaxError => e 11 | puts "Error #{e.message}" 12 | end 13 | } 14 | -------------------------------------------------------------------------------- /examples/sample41.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | GraphViz::new( "G" ) { |g| 7 | g.hello(:style => :filled, :fillcolor => :lightblue) << g.world(:style => :filled, :fillcolor => :lightgrey) 8 | }.output( :svg => "#{$0}.svg", :nothugly => true ) 9 | -------------------------------------------------------------------------------- /examples/sample24.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G" ) { |g| 7 | g.hello << g.world 8 | g.bonjour - g.monde 9 | g.hola > g.mundo 10 | g.holla >> g.welt 11 | }.output( :path => "/usr/local/bin", :png => "#{$0}.png" ) 12 | -------------------------------------------------------------------------------- /examples/sample57.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | 3 | require 'graphviz/graphml' 4 | 5 | graphml = File.join( File.dirname( File.expand_path( __FILE__ ) ), "graphml", "port.graphml" ) 6 | g = GraphViz::GraphML.new( graphml ) 7 | g.graph.output( :png => "#{$0}.png" ) 8 | puts g.graph.output( :none => String ) 9 | -------------------------------------------------------------------------------- /examples/sample16.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G", :type => "graph", :rankdir => "LR" ) { |graph| 7 | graph.add_edges( [graph.a, graph.b, graph.c], [ graph.d, graph.e, graph.f ] ) 8 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) 9 | -------------------------------------------------------------------------------- /examples/sample29.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:G){ |g| 7 | g.add_nodes("\"Hello.\"\nHow are you ?", :href => "https://www.example.com/", :tooltip => "\"Hello.\"\nHow are you ?", :shape => "ellipse", :color => "#FF0000") 8 | }.save( :svg => "#{$0}.svg" ) 9 | -------------------------------------------------------------------------------- /examples/sample49.rb: -------------------------------------------------------------------------------- 1 | # http://www.graphviz.org/Gallery/directed/hello.html 2 | # 3 | # digraph G {Hello->World} 4 | 5 | $:.unshift( "../lib" ); 6 | require "graphviz" 7 | 8 | GraphViz::new( :G, :type => :digraph ) { |g| 9 | g.world( :label => "World" ) << g.hello( :label => "Hello" ) 10 | }.output( :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample56.rb: -------------------------------------------------------------------------------- 1 | # http://www.graphviz.org/Gallery/directed/hello.html 2 | # 3 | # digraph G {Hello->World} 4 | 5 | $:.unshift( "../lib" ); 6 | require "graphviz" 7 | 8 | GraphViz::new( :G, :type => :digraph ) { |g| 9 | g.world( :label => " "Hello>" ) 10 | }.output( :svg => "#{$0}.svg" ) -------------------------------------------------------------------------------- /examples/sample39.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require "graphviz" 3 | 4 | g = GraphViz::new( "G", :type => "graph" ) 5 | n1 = g.add_nodes( "A" ) 6 | n2 = g.add_nodes( "B" ) 7 | n3 = g.add_nodes( "C" ) 8 | e1 = g.add_edges( n1, n2 ) 9 | e1[:dir] = 'forward' 10 | e2 = g.add_edges( n1, n3 ) 11 | g.output( :png => "#{$0}.png" ) 12 | -------------------------------------------------------------------------------- /examples/sample67.rb: -------------------------------------------------------------------------------- 1 | $:.unshift("../lib") 2 | 3 | require 'graphviz' 4 | graph = GraphViz.graph(:G) 5 | graph.add_nodes(["A", "B", "C", "D", "E", "F", "G"]) 6 | graph.add_edges("A", ["B", "C", "E"]) 7 | graph.add_edges("B", ["D", "F"]) 8 | graph.add_edges("C", "G") 9 | graph.add_edges("F", "E") 10 | graph.output(:png => "#{$0}.png") 11 | -------------------------------------------------------------------------------- /examples/sample25.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G" ) { |g| 7 | g.hello << g.world 8 | g.bonjour( :label => '"Bonjour"' ) - g.monde( :label => "Le\nmonde") 9 | g.hola > g.mundo 10 | g.holla >> g.welt 11 | }.output( :path => "/usr/local/bin", :png => "#{$0}.png" ) 12 | -------------------------------------------------------------------------------- /lib/graphviz/family_tree/sibling.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class FamilyTree 3 | class Sibling 4 | def initialize( bns, parents ) 5 | @brothers_and_sisters = bns 6 | @brothers_and_sisters.each do |person| 7 | person.sibling = self 8 | end 9 | @parents = parents 10 | end 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /examples/sample38.rb: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | $:.unshift( "../lib" ) 3 | require "graphviz" 4 | 5 | g = GraphViz::new( :G ) { |_g| 6 | _g.a[:label => "ε"] 7 | _g.add_nodes( "b", :label => "ε" ) 8 | _g.c[:label => 'ε'] 9 | _g.add_nodes( "d", :label => 'ε' ) 10 | } 11 | 12 | puts g.output( :none => String, :png => "#{$0}.png", :path => "/usr/local/bin" ) 13 | -------------------------------------------------------------------------------- /test/helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'test/unit' 4 | require 'pathname' 5 | 6 | cur = Pathname.new(File.expand_path("..", __FILE__)) 7 | lib = cur.join('..', 'lib') 8 | 9 | $LOAD_PATH.unshift(lib.to_s, cur.to_s) 10 | require 'graphviz' 11 | require 'graphviz/theory' 12 | require 'graphviz/math/matrix' 13 | require 'graphviz/utils/colors' 14 | -------------------------------------------------------------------------------- /examples/sample55.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz' 3 | 4 | puts GraphViz.graph( :G ) { |g| 5 | g[:label] = "<This is a test>" 6 | n1 = g.add_nodes( "N1", :label => '<node 1>') 7 | n2 = g.add_nodes( "N2", :label => '<node 2>') 8 | g.add_edges( n1, n2, :label => '<edge>') 9 | }.output( :png => "#{$0}.png", :none => String ) 10 | -------------------------------------------------------------------------------- /examples/sample70.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz' 3 | 4 | puts GraphViz.graph( :G ) { |g| 5 | g[:label] = "<This is a test>" 6 | n1 = g.add_nodes( "N1", :label => '<node 1>') 7 | n2 = g.add_nodes( "N2", :label => '<node 2>') 8 | g.add_edges( n1, n2, :label => '<edge>') 9 | }.output( :svg => "#{$0}.svg", :none => String ) 10 | -------------------------------------------------------------------------------- /lib/graphviz/types/html_string.rb: -------------------------------------------------------------------------------- 1 | # TODO: Remove 2 | class GraphViz 3 | class Types 4 | class HtmlString < Common 5 | def check(data) 6 | return data 7 | end 8 | 9 | def output 10 | return "<"+@data+">" 11 | end 12 | 13 | alias :to_gv :output 14 | alias :to_s :output 15 | alias :to_ruby :output 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /examples/sample21.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | {"png" => "#{$0}.png", "imap" => "#{$0}.html"}.each do |format, file| 7 | GraphViz::new( "G" ) { |g| 8 | g.command(:URL => "http://www.research.att.com/base.html") 9 | g._output(:label => "output", :URL => "colors.html") 10 | g.command << g._output 11 | }.output( format => file ) 12 | end -------------------------------------------------------------------------------- /examples/sample32.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:G){ |g| 7 | g.edge[:arrowsize => 0.5] 8 | g.graph[:bb => "0,0,638,256"] 9 | g.person[:shape => :record]; 10 | g.driver[:shape => :ellipse]; 11 | g.owner[:shape => :ellipse]; 12 | g.passenger[:shape => :ellipse]; 13 | g.vehicle[:shape => :record]; 14 | }.save( :png => "#{$0}.png" ) 15 | -------------------------------------------------------------------------------- /examples/sample28.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:G){ |g| 7 | g[:ratio => "auto", :label => "I love the world!"] 8 | 9 | g.hello( :label => "Hello", :color => "blue" ) # You can do this 10 | g.none[ :label => "World", :color => "green" ] # or that 11 | (g.hello - g.none)[:style => :bold, :label => " I say"] 12 | }.save( :png => "#{$0}.png" ) 13 | -------------------------------------------------------------------------------- /examples/sample23.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | r = GraphViz::new( "mainmap" ) { |graph| 7 | graph[:URL] = "http://www.research.att.com/base.html" 8 | graph.command( :URL => "http://www.research.att.com/command.html" ) 9 | (graph.command << graph._output( :label => "output" ))[:URL] = "colors.html" 10 | } 11 | puts r.output( :cmapx => String, :png => "#{$0}.png" ) 12 | -------------------------------------------------------------------------------- /lib/graphviz/types/esc_string.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class Types 3 | class EscString < Common 4 | def check(data) 5 | return data 6 | end 7 | 8 | def output 9 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 10 | end 11 | 12 | alias :to_gv :output 13 | alias :to_s :output 14 | 15 | def to_ruby 16 | @data 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /examples/sample22.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "mainmap" ) { |graph| 7 | graph[:URL] = "http://www.research.att.com/base.html" 8 | graph.command( :URL => "http://www.research.att.com/command.html" ) 9 | (graph.command << graph._output( :label => "output" ))[:URL] = "colors.html" 10 | }.output( :canon => nil, :cmapx => "#{$0}.html", :png => "#{$0}.png" ) 11 | -------------------------------------------------------------------------------- /lib/graphviz/ext.rb: -------------------------------------------------------------------------------- 1 | require 'find' 2 | 3 | class GraphViz 4 | class Ext 5 | def self.find( ext = nil ) 6 | myPath = File.join( File.dirname( File.expand_path( __FILE__ ) ), "..", "ext" ) 7 | found = myPath 8 | unless ext.nil? 9 | Find.find(myPath) do |path| 10 | found = path if File.basename( path ) == ext 11 | end 12 | end 13 | 14 | File.expand_path( found ) 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /examples/rgv/test_rgv.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:g){ |g| 7 | g[:center] = true 8 | a = g.add_nodes("A", :shape => "rgv_box", :peripheries => 0) 9 | b = g.add_nodes("Bonjour le monde\nComment va tu ?", :shape => "rgv_cloud", :peripheries => 0) 10 | c = g.add_nodes("C", :shape => "rgv_flower", :peripheries => 0) 11 | a << b << c 12 | }.save( :ps => "#{$0}.ps", :extlib => "rgv.ps" ) 13 | -------------------------------------------------------------------------------- /examples/dot/test.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | fontsize=12; 3 | node [style=filled ,fontsize=10]; Hello; 4 | edge[style=dotted]; 5 | graph [ bgcolor = "#ABCDEF"]; 6 | 7 | monde [color=blue, style= filled]; 8 | node[color=white ] ; 9 | Hello ->World [color=red, style = filled]; 10 | Bonjour-> monde -> Chose; 11 | Coucou -> "Les Gens" [color=blue]; 12 | subgraph X { 13 | bgcolor = white; 14 | label="Sub Graph"; 15 | toto -> titi; 16 | } 17 | } -------------------------------------------------------------------------------- /examples/sample74.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.add_nodes "english", label: 'hello' 14 | g.add_nodes "chinese", label: '你好' 15 | g.add_nodes "korean", label: '안녕하세요' 16 | g.add_nodes "arabic", label: 'مرحبا' 17 | g.add_nodes "russian", label: 'Алло' 18 | 19 | g.output( :png => "#{$0}.png" ) 20 | -------------------------------------------------------------------------------- /examples/sample30.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz.new(:g){ |g| 7 | g[:center] = true 8 | a = g.add_nodes("A", :shape => "sdl_procedure_start", :peripheries => 0 ) 9 | b = g.add_nodes("B", :shape => "sdl_save", :peripheries => 0) 10 | c = g.add_nodes("n", :shape => "box", :label => "\\G::\\N\\r") 11 | a << b << c 12 | }.save( :ps => "#{$0}.ps", :extlib => File.join( File.dirname(__FILE__), "sdlshapes", "sdl.ps" ) ) 13 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --no-private 3 | --embed-mixin ClassMethods 4 | --title "Ruby/GraphViz, the Documentation" 5 | - 6 | README.md 7 | CHANGELOG.md 8 | COPYING.md 9 | lib/graphviz.rb 10 | lib/graphviz/node.rb 11 | lib/graphviz/edge.rb 12 | lib/graphviz/constants.rb 13 | lib/graphviz/xml.rb 14 | lib/graphviz/graphml.rb 15 | lib/graphviz/family_tree.rb 16 | lib/graphviz/family_tree/couple.rb 17 | lib/graphviz/family_tree/generation.rb 18 | lib/graphviz/family_tree/person.rb 19 | lib/graphviz/family_tree/sibling.rb 20 | -------------------------------------------------------------------------------- /examples/sample40.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require "graphviz" 3 | 4 | graph = GraphViz.new( :G, :type => :digraph ) 5 | 6 | node1 = graph.add_nodes("hello:world", 7 | "shape" => "record", 8 | "label" => "| 1|" ) 9 | 10 | node2 = graph.add_nodes("2", 11 | "shape" => "record", 12 | "label" => "| 2|" ) 13 | 14 | graph.add_edges( {node1 => :left}, node2 ) 15 | graph.add_edges( {node2 => :right}, node1 ) 16 | 17 | puts graph.output( :none => String, :png => "#{$0}.png" ) 18 | -------------------------------------------------------------------------------- /examples/sample71.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.add_edges("noDe", "graph") 14 | g.add_edges("node", "graph") 15 | g.add_edges("node", "Graph") 16 | g.add_edges("graph", "subgraph") 17 | g.add_edges("edge", "node") 18 | g.add_edges("subgraph", "digraph") 19 | g.add_edges("subgraph", "strict") 20 | 21 | g.output( :png => "#{$0}.png" ) 22 | -------------------------------------------------------------------------------- /examples/sample73.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.add_nodes "HtmlOne", label: '<This is an
HTML Node>' 14 | g.add_nodes "HtmlTwo", label: 'an HTML node>' 15 | g.add_nodes "NotHtmlOne", label: '' 16 | g.add_nodes "NotHtmlTwo", label: 'this is not an HTML node, too!' 17 | 18 | g.output( :png => "#{$0}.png" ) 19 | -------------------------------------------------------------------------------- /examples/sample72.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node[:color] = "#FF0000:#FFFFFF" 14 | g.add_edges("noDe", "graph") 15 | g.add_edges("node", "graph") 16 | g.add_edges("node", "Graph") 17 | g.add_edges("graph", "subgraph") 18 | g.add_edges("edge", "node") 19 | g.add_edges("subgraph", "digraph") 20 | g.add_edges("subgraph", "strict") 21 | 22 | g.output( :png => "#{$0}.png" ) 23 | -------------------------------------------------------------------------------- /lib/graphviz/types.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class Types 3 | class Common 4 | def initialize( data ) 5 | @data = check(data) 6 | end 7 | 8 | def output 9 | return @data 10 | end 11 | 12 | def source 13 | return @data 14 | end 15 | end 16 | 17 | Dir.glob( File.dirname( File.expand_path(__FILE__) )+"/types/*.rb" ).each do |f| 18 | #autoload File.basename(f).gsub(File.extname(f), "").split( "_" ).map{|n| n.capitalize }.join.to_sym, f 19 | require f 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /examples/sample69.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = GraphViz::new( "G", :type => "graph" ) 7 | g[:compound] = true 8 | g[:rankdir] = "LR" 9 | 10 | c0 = g.add_graph( "cluster0", "label" => "cluster #1" ) 11 | a0 = c0.add_nodes( "a0" ) 12 | 13 | c1 = g.add_graph( "cluster1", "label" => "cluster #2" ) 14 | b0 = c1.add_nodes( "b0" ) 15 | 16 | e1 = g.add_edges(a0,b0) 17 | e1[:lhead] = c1.id 18 | e1[:ltail] = c0.id 19 | 20 | e2 = g.add_edges(a0,b0) 21 | e2[:lhead] = c1.id 22 | 23 | g.output( :png => "#{$0}.png" ) 24 | -------------------------------------------------------------------------------- /examples/dot/cluster.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | subgraph cluster_0 { 3 | style=filled; 4 | color=lightgrey; 5 | node [style=filled,color=white]; 6 | a0 -> a1; 7 | a1 -> a2; 8 | a2 -> a3; 9 | label = "process #1"; 10 | } 11 | 12 | subgraph cluster_1 { 13 | node [style=filled]; 14 | b0 -> b1; 15 | b1 -> b2; 16 | b2 -> b3; 17 | label = "process #2"; 18 | color=blue; 19 | } 20 | start -> a0; 21 | start -> b0; 22 | a1 -> b3; 23 | b2 -> a3; 24 | a3 -> a0; 25 | a3 -> end; 26 | b3 -> end; 27 | 28 | start [shape=Mdiamond]; 29 | end [shape=Msquare]; 30 | } -------------------------------------------------------------------------------- /examples/graphml/attributes.ext.graphml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/graphviz/types/color_list.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class Types 3 | class ColorList < Common 4 | def check(data) 5 | data = data.to_s if data.is_a?(Symbol) 6 | return nil if data.empty? 7 | 8 | @to_ruby = data.split(/\s*:\s*/).map { |c| GraphViz::Types::Color.new(c).to_ruby } 9 | return data 10 | end 11 | 12 | def output 13 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 14 | end 15 | 16 | alias :to_gv :output 17 | alias :to_s :output 18 | 19 | def to_ruby 20 | @data 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /examples/sample54.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz' 3 | 4 | class Array 5 | def rotate 6 | ## Solution #1 by greg 7 | # self.push(r = self.shift) 8 | # return r 9 | 10 | ## Solution #2 by madx 11 | # shift.tap {|e| push e } 12 | 13 | ## Solution #3 by greg 14 | push(shift)[-1] 15 | end 16 | end 17 | 18 | type = ["box", "point"] 19 | 20 | GraphViz.graph( :G, :use => :neato ) { |g| 21 | (1..5).each do |x| 22 | (1..5).each do |y| 23 | g.add_nodes( "n#{x}x#{y}", :pos => "#{x},#{y}!", :shape => type.rotate ) 24 | end 25 | end 26 | }.output( :png => "#{$0}.png" ) 27 | -------------------------------------------------------------------------------- /examples/dot/so-sample002.gv: -------------------------------------------------------------------------------- 1 | 2 | //{:category1 => 3 | // {:subcategory1 => 4 | // [ 5 | // {:article => "some article", :date => "2010-04-04"}, 6 | // ... 7 | // ], 8 | // :subc2 => [...] 9 | // }, 10 | // :category2 => {...}, 11 | // ... 12 | //} 13 | 14 | graph G { 15 | rankdir=LR 16 | category1 17 | 18 | subgraph clusterC { 19 | node[shape="box"] 20 | subcategory1 21 | subc2 22 | 23 | subgraph clusterS { 24 | article -- "somme article" 25 | date -- "2010-04-04" 26 | } 27 | 28 | subcategory1 -- clusterS 29 | subc2 -- "..." 30 | } 31 | 32 | category1 -- clusterC 33 | } -------------------------------------------------------------------------------- /examples/dot/so-sample001.gv: -------------------------------------------------------------------------------- 1 | digraph G { 2 | layout="neato" 3 | // scale things down for example 4 | size="5,5" 5 | rankdir=TD 6 | ranksep=1 7 | nodesep=1 8 | 9 | node [shape=box] 10 | 11 | top[pos="5,10!", width=5, height=2] 12 | 13 | left1[pos="3.5,7!", width=2, height=2] 14 | left2[pos="3.5,4!", width=2, height=2] 15 | 16 | right[pos="6.5,5.5!", width=2, height=5] 17 | 18 | bottom[pos="5,1!", width=5, height=2] 19 | 20 | 21 | top->left1 22 | top->right 23 | 24 | left1->left2 25 | left1->right 26 | left2->right 27 | 28 | left2->bottom 29 | right->bottom 30 | } -------------------------------------------------------------------------------- /examples/sample34.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | GraphViz.new(:G) { |g| 7 | g[:color] = "black" 8 | 9 | g.one :label => "1" 10 | 11 | # This is an anonymous graph 12 | c = g.add_graph( :rank => "same" ) { |c| 13 | c.two :label => "2" 14 | c.three :label => "3" 15 | c.two << c.three 16 | } 17 | 18 | # And this is not! 19 | k = g.add_graph( "Hello" ) { |k| 20 | k.four :label => "4" 21 | k.five :label => "5" 22 | k.four << k.five 23 | } 24 | 25 | g.one << c.two 26 | g.one << c.three 27 | c.two << k.four 28 | c.three << k.five 29 | }.output( :canon => String ) 30 | -------------------------------------------------------------------------------- /examples/sample15.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # fdp example 4 | # see : http://www.graphviz.org/Gallery/undirected/fdpclust.html 5 | 6 | $:.unshift( "../lib" ); 7 | require "graphviz" 8 | 9 | g = GraphViz::new( "G", :type => "graph", :use => "fdp" ) { |graph| 10 | graph.e 11 | graph.clusterA { |cA| 12 | cA.a << cA.b 13 | cA.clusterC { |cC| 14 | cC._c( :label => "C" ) << cC._d( :label => "D" ) 15 | } 16 | } 17 | graph.clusterB { |cB| 18 | cB.d << cB.f 19 | } 20 | graph.clusterB.d << graph.clusterA.clusterC._d 21 | graph.e << graph.clusterB 22 | graph.clusterA.clusterC << graph.clusterB 23 | } 24 | 25 | g.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) 26 | -------------------------------------------------------------------------------- /examples/sample53.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz/family_tree' 3 | 4 | tree = GraphViz::FamilyTree.new do 5 | generation do 6 | benoist.is_a_man( "Benoist" ) 7 | nathalie.is_a_woman( "Nathalie" ) 8 | 9 | benoist.is_maried_with nathalie 10 | end 11 | 12 | generation do 13 | charlotte.is_a_woman( "Charlotte" ) 14 | amelie.is_a_woman( "Amelie" ) 15 | clement.is_a_man( "Clement" ) 16 | gregoire.is_a_man( "Gregoire" ) 17 | 18 | muriel.is_a_woman( "Muriel" ) 19 | 20 | gregoire.is_maried_with muriel 21 | end 22 | 23 | couple( benoist, nathalie ).kids( charlotte, amelie, clement, gregoire ) 24 | end 25 | 26 | tree.graph.save( :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample62.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | hello_world = GraphViz::new( "" ) 7 | 8 | hello = hello_world.add_nodes("Hello") 9 | world = hello_world.add_nodes("World") 10 | hello_world.add_edges(hello, world) 11 | 12 | # final_graph = GraphViz.parse_string( hello_world.output( :dot => String ) ) 13 | # final_graph.each_node do |_, node| 14 | # puts "Node #{node.id} : position = #{node[:pos]}" 15 | # end 16 | 17 | hello_world = hello_world.complete 18 | hello_world.each_node do |_, node| 19 | puts "Node #{node.id} : position = " ; p node[:pos].point 20 | end 21 | 22 | puts "---------" 23 | 24 | puts hello_world.output( :canon => String ) 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /examples/dot/fsm.dot: -------------------------------------------------------------------------------- 1 | digraph finite_state_machine { 2 | rankdir=LR; 3 | size="8,5"; 4 | node [shape = doublecircle]; LR_0; LR_3; LR_4; LR_8; 5 | node [shape = circle]; 6 | LR_0 -> LR_2 [ label = "SS(B)" ]; 7 | LR_0 -> LR_1 [ label = "SS(S)" ]; 8 | LR_1 -> LR_3 [ label = "S($end)" ]; 9 | LR_2 -> LR_6 [ label = "SS(b)" ]; 10 | LR_2 -> LR_5 [ label = "SS(a)" ]; 11 | LR_2 -> LR_4 [ label = "S(A)" ]; 12 | LR_5 -> LR_7 [ label = "S(b)" ]; 13 | LR_5 -> LR_5 [ label = "S(a)" ]; 14 | LR_6 -> LR_6 [ label = "S(b)" ]; 15 | LR_6 -> LR_5 [ label = "S(a)" ]; 16 | LR_7 -> LR_8 [ label = "S(b)" ]; 17 | LR_7 -> LR_5 [ label = "S(a)" ]; 18 | LR_8 -> LR_6 [ label = "S(b)" ]; 19 | LR_8 -> LR_5 [ label = "S(a)" ]; 20 | } -------------------------------------------------------------------------------- /examples/dot/hello_test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../../lib" ); 4 | require "graphviz" 5 | 6 | g = GraphViz.parse( "hello.dot", :path => "/usr/local/bin" ) { |g| 7 | g.graph[:color] = "blue" 8 | g.node[:color] = "red" 9 | g.edge[:color] = "yellow" 10 | g.get_node("Hello") { |n| 11 | n.label = "Bonjour" 12 | } 13 | g.get_node("World") { |n| 14 | n.label = "Le Monde" 15 | } 16 | } 17 | 18 | g.graph.each do |k, v| 19 | puts "graph : #{k} => #{v}" 20 | end 21 | 22 | g.node.each do |k, v| 23 | puts "node : #{k} => #{v}" 24 | end 25 | 26 | g.edge.each do |k, v| 27 | puts "edge : #{k} => #{v}" 28 | end 29 | 30 | puts "-----------" 31 | 32 | puts g.output(:none => String) 33 | 34 | -------------------------------------------------------------------------------- /examples/sample04.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "structs", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "structs" ) 11 | end 12 | 13 | g.node["shape"] = "record" 14 | 15 | struct1 = g.add_nodes( "struct1", "shape" => "record", "label" => " left| mid\ dle| right" ) 16 | struct2 = g.add_nodes( "struct2", "shape" => "record", "label" => " one| two" ) 17 | struct3 = g.add_nodes( "struct3", "shape" => "record", "label" => 'hello\nworld |{ b |{c| d|e}| f}| g | h' ) 18 | 19 | g.add_edges( struct1, struct2 ) 20 | g.add_edges( struct1, struct3 ) 21 | 22 | g.output( :png => "#{$0}.png" ) 23 | -------------------------------------------------------------------------------- /examples/sample68.rb: -------------------------------------------------------------------------------- 1 | $:.unshift("../lib") 2 | 3 | require 'graphviz' 4 | require 'graphviz/theory' 5 | g = GraphViz.graph(:G) 6 | g.add_nodes(["A", "B", "C", "D", "E", "F", "G"]) 7 | g.add_edges("A", ["B", "C", "E"]) 8 | g.add_edges("B", ["D", "F"]) 9 | g.add_edges("C", "G") 10 | g.add_edges("F", "E") 11 | g.output(:png => "#{$0}000.png") 12 | 13 | t = GraphViz::Theory.new(g) 14 | i = 1 15 | t.dfs("A") { |node| 16 | name = sprintf("%s%03d.png", $0, i) 17 | node[:color => :lightblue, :style => :filled] 18 | g.output(:png => name) 19 | i = i + 1 20 | } 21 | 22 | t.bfs("A") { |node| 23 | name = sprintf("%s%03d.png", $0, i) 24 | node[:color => :red, :style => :filled] 25 | g.output(:png => name) 26 | i = i + 1 27 | } 28 | -------------------------------------------------------------------------------- /lib/graphviz/types/arrow_type.rb: -------------------------------------------------------------------------------- 1 | # >> x = "hello\n\t\\l\"world\"" 2 | # => "hello\n\t\\l\"world\"" 3 | # >> puts x.inspect.gsub( "\\\\", "\\" ) 4 | # "hello\n\t\l\"world\"" 5 | # 6 | # OR 7 | # 8 | # >> x = 'hello\n\t\l"world"' 9 | # => "hello\\n\\t\\l\"world\"" 10 | # >> puts x.inspect.gsub( "\\\\", "\\" ) 11 | # "hello\n\t\l\"world\"" 12 | 13 | class GraphViz 14 | class Types 15 | class ArrowType < Common 16 | def check(data) 17 | return data 18 | end 19 | 20 | def output 21 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 22 | end 23 | 24 | alias :to_gv :output 25 | alias :to_s :output 26 | 27 | def to_ruby 28 | @data 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/test_subgraph.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class GraphVizSubGraphTest < Test::Unit::TestCase 4 | def test_subgraph 5 | master1 = GraphViz::new(:G) 6 | master1.add_graph('cluster_cl1') 7 | 8 | master2 = GraphViz::new(:G) 9 | cl2 = GraphViz::new('cluster_cl1') 10 | master2.add_graph cl2 11 | 12 | assert_equal(master1.to_s, master2.to_s, "Wrong subgraph") 13 | end 14 | 15 | def test_to_graph 16 | m = GraphViz.new(:G) 17 | m.add_edges("m1", "m2") 18 | c = m.add_graph('c') 19 | c.add_edges("c1", "c2") 20 | 21 | assert_equal true, c.has_parent_graph? 22 | assert_equal false, m.has_parent_graph? 23 | 24 | ci = c.to_graph 25 | assert_equal false, ci.has_parent_graph? 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /examples/sample63.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz/dsl' 3 | 4 | digraph :G do 5 | cluster_0 do 6 | graph[:style => :filled, :color => :lightgrey] 7 | node[:style => :filled, :color => :white] 8 | a0 << a1 << a2 << a3 9 | graph[:label => "process #1"] 10 | end 11 | 12 | cluster_1 do 13 | node[:style => :filled] 14 | b0 << b1 << b2 << b3 15 | graph[:label => "process #2", :color => :blue] 16 | end 17 | 18 | start << a0 19 | start << b0 20 | a1 << b3 21 | b2 << a3 22 | a3 << a0 23 | a3 << _end 24 | b3 << _end 25 | 26 | start[:shape] = :Mdiamond 27 | _end[:label] = "end" 28 | _end[:shape] = :Mdiamond 29 | 30 | output(:png => "#{$0}.png") 31 | end 32 | 33 | -------------------------------------------------------------------------------- /examples/sample07.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::options( :use => "dot" ) 7 | 8 | if ARGV[0] 9 | GraphViz::options( :path => ARGV[0] ) 10 | end 11 | 12 | g = GraphViz::new( "structs" ) 13 | 14 | g.node["shape"] = "record" 15 | 16 | g.add_nodes( "struct1", "shape" => "record", "label" => " left| middle| right" ) 17 | g.add_nodes( "struct2", "shape" => "record", "label" => " one| two" ) 18 | g.add_nodes( "struct3", "shape" => "record", "label" => 'hello\nworld |{ b |{c| d|e}| f}| g | h' ) 19 | 20 | g.add_edges( { "struct1" => :f1}, {"struct2" => :f0} ) 21 | g.add_edges( {"struct1" => :f2}, {"struct3" => :here} ) 22 | 23 | g.output( :png => "#{$0}.png", :canon => nil ) 24 | -------------------------------------------------------------------------------- /examples/sample64.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require 'graphviz/dsl' 3 | 4 | digraph :G do 5 | 6 | node[:color => :lightblue, :style => :filled, :shape => :egg] 7 | edge[:color => :gray, :arrowhead => :vee] 8 | 9 | e "C/C++", "Java" 10 | 11 | java do 12 | n("Java") << n("Groovy") 13 | n("Java") << n("Clojure") 14 | n("Java") << n("JRuby") 15 | graph[:label => "Java", :color => :blue] 16 | end 17 | 18 | e "C/C++", "Perl" 19 | e "Perl", "PHP" 20 | e "Perl", "Ruby" 21 | e "Ruby", "Rubinius" 22 | e "Ruby", "MacRuby" 23 | e "Ruby", "JRuby" 24 | 25 | %w{ Ruby JRuby MacRuby Rubinius }.each do |ruby| 26 | n(ruby)[:color => :tomato] 27 | end 28 | 29 | output :png => "#{$0}.png" 30 | end 31 | 32 | -------------------------------------------------------------------------------- /examples/sample45.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node["shape"] = "ellipse" 14 | 15 | [ "box", "polygon", "ellipse", "circle", "point", 16 | "egg", "triangle", "plaintext", "diamond", "trapezium", 17 | "parallelogram", "house", "pentagon", "hexagon", "septagon", "octagon", "doublecircle", 18 | "doubleoctagon", "tripleoctagon", "invtriangle", "invtrapezium", "invhouse", 19 | "Mdiamond", "Msquare", "Mcircle", "rect", "rectangle", "none", "note", "tab", "folder", 20 | "box3d", "component" ].each { |s| 21 | g.add_nodes( s, "shape" => s ) 22 | } 23 | 24 | g.output( :png => "#{$0}.png") 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Environment (please complete the following information):** 24 | - OS: [e.g. Ubuntu] 25 | - Version [e.g. 18.04] 26 | - Ruby Manager [e.g. rbenv] 27 | - Ruby Manager Version [e.g. 1.1.1] 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /lib/graphviz/types/gv_double.rb: -------------------------------------------------------------------------------- 1 | class DoubleException < RuntimeError 2 | end 3 | 4 | class GraphViz 5 | class Types 6 | class GvDouble < Common 7 | FLOAT_MASK = /[-+]?(?:[0-9]*\.[0-9]+|[0-9]+)/ 8 | 9 | def check(data) 10 | if data.kind_of?(Numeric) or (data.is_a?(String) and FLOAT_MASK.match(data)) 11 | return data 12 | end 13 | 14 | return nil if data.is_a?(String) and data.empty? 15 | 16 | raise DoubleException, "Invalid double value for `#{data}`" 17 | end 18 | 19 | def output 20 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 21 | end 22 | 23 | def to_f 24 | @data.to_f 25 | end 26 | 27 | alias :to_gv :output 28 | alias :to_s :output 29 | alias :to_ruby :to_f 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/test_search.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class GraphVizSearch < Test::Unit::TestCase 4 | def setup 5 | @graph = GraphViz.graph(:G) 6 | @graph.add_nodes(["A", "B", "C", "D", "E", "F", "G"]) 7 | @graph.add_edges("A", ["B", "C", "E"]) 8 | @graph.add_edges("B", ["D", "F"]) 9 | @graph.add_edges("C", "G") 10 | @graph.add_edges("F", "E") 11 | @theory = GraphViz::Theory.new(@graph) 12 | end 13 | 14 | def test_dfs 15 | order = [] 16 | @theory.dfs("A") { |node| 17 | order << node.id 18 | } 19 | assert_equal order, ["A", "B", "D", "F", "E", "C", "G"] 20 | end 21 | 22 | def test_bfs 23 | order = [] 24 | @theory.bfs("A") { |node| 25 | order << node.id 26 | } 27 | assert_equal order, ["A", "B", "C", "E", "D", "F", "G"] 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /examples/sample01.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | main = g.add_nodes( "main" ) 14 | parse = g.add_nodes( "parse" ) 15 | execute = g.add_nodes( "execute" ) 16 | init = g.add_nodes( "init" ) 17 | cleanup = g.add_nodes( "cleanup" ) 18 | make_string = g.add_nodes( "make_string" ) 19 | printf = g.add_nodes( "printf" ) 20 | compare = g.add_nodes( "compare" ) 21 | 22 | g.add_edges( main, parse ) 23 | g.add_edges( parse, execute ) 24 | g.add_edges( main, init ) 25 | g.add_edges( main, cleanup ) 26 | g.add_edges( execute, make_string ) 27 | g.add_edges( execute, printf ) 28 | g.add_edges( init, make_string ) 29 | g.add_edges( main, printf ) 30 | g.add_edges( execute, compare ) 31 | 32 | g.output( :png => "#{$0}.png" ) 33 | -------------------------------------------------------------------------------- /examples/sample51.rb: -------------------------------------------------------------------------------- 1 | # http://www.graphviz.org/Gallery/undirected/process.html 2 | # 3 | # graph G { 4 | # run -- intr; 5 | # intr -- runbl; 6 | # runbl -- run; 7 | # run -- kernel; 8 | # kernel -- zombie; 9 | # kernel -- sleep; 10 | # kernel -- runmem; 11 | # sleep -- swap; 12 | # swap -- runswap; 13 | # runswap -- new; 14 | # runswap -- runmem; 15 | # new -- runmem; 16 | # sleep -- runmem; 17 | # } 18 | 19 | $:.unshift( "../../lib" ); 20 | require "graphviz" 21 | 22 | GraphViz::new( :G, :type => :graph ) { |g| 23 | g._new[:label] = "new" 24 | g.run << g.intr 25 | g.intr << g.runbl 26 | g.runbl << g.run 27 | g.run << g.kernel 28 | g.kernel << g.zombie 29 | g.kernel << g.sleep 30 | g.kernel << g.runmem 31 | g.sleep << g.swap 32 | g.swap << g.runswap 33 | g.runswap << g._new 34 | g.runswap << g.runmem 35 | g._new << g.runmem 36 | g.sleep << g.runmem 37 | }.output( :png => "#{$0}.png", :use => :fdp ) -------------------------------------------------------------------------------- /examples/sample58.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # By Jonas Elfström - https://github.com/jonelf 4 | $:.unshift( "../lib" ) 5 | require 'graphviz' 6 | 7 | @min_level=1 8 | @max_level=12 9 | @max_depth=10 10 | start_level=6 11 | 12 | @g = GraphViz.new(:G, :type => "strict digraph") 13 | # or @g = GraphViz.new(:G, :type => "digraph", :strict => true) 14 | # or @g = GraphViz.digraph(:G, :strict => true) 15 | # or @g = GraphViz.strict_digraph(:G) 16 | 17 | def add_nodes(level, depth, parent) 18 | if depth<@max_depth 19 | current=[level, depth].join(",") 20 | 21 | sub=level<=>@min_level 22 | add=@max_level<=>level 23 | add_nodes(level-sub, depth+1, current) 24 | add_nodes(level+add, depth+1, current) 25 | 26 | @g.add_nodes(current).label=level.to_s 27 | @g.add_edges(parent, current) unless parent=="00" 28 | end 29 | end 30 | 31 | add_nodes(start_level, 0, "00") 32 | 33 | @g.output( :png => "#{$0}.png" ) 34 | -------------------------------------------------------------------------------- /examples/dot/balanced.dot: -------------------------------------------------------------------------------- 1 | graph G 2 | { 3 | n1 [label="+"]; 4 | n2 [label="/"]; 5 | n1 -- n2; 6 | n1b1 [label="", width=.1, style=invis] 7 | n1 -- n1b1 [style=invis] 8 | n1b2 [label="", width=.1, style=invis] 9 | n1 -- n1b2 [style=invis] 10 | n1b3 [label="", width=.1, style=invis] 11 | n1 -- n1b3 [style=invis] 12 | n7 [label="**"]; 13 | n1 -- n7; 14 | { rank=same n2 -- n1b1 -- n1b2 -- n1b3 -- n7 [style=invis] } 15 | 16 | n3 [label="*"]; 17 | n2 -- n3; 18 | n2b1 [label="", width=.1, style=invis] 19 | n2 -- n2b1 [style=invis] 20 | n6 [label="3"]; 21 | n2 -- n6; 22 | { rank=same n3 -- n2b1 -- n6 [style=invis] } 23 | 24 | n8 [label="4"]; 25 | n7 -- n8; 26 | n7b1 [label="", width=.1, style=invis] 27 | n7 -- n7b1 [style=invis] 28 | n9 [label="5"]; 29 | n7 -- n9; 30 | { rank=same n8 -- n7b1 -- n9 [style=invis] } 31 | 32 | n3 -- n4; 33 | n4 [label="1"]; 34 | n3 -- n5; 35 | n5 [label="2"]; 36 | } -------------------------------------------------------------------------------- /lib/graphviz/elements.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class Elements 3 | def initialize 4 | @elements = Array.new 5 | @elements_hash_by_type = Hash.new 6 | end 7 | 8 | def push( obj ) 9 | @elements.push( obj ) 10 | if @elements_hash_by_type[obj['type']].nil? 11 | @elements_hash_by_type[obj['type']] = Array.new 12 | end 13 | 14 | @elements_hash_by_type[obj['type']].push( obj ) 15 | end 16 | 17 | def each( &b ) 18 | @elements.each do |e| 19 | yield( e ) 20 | end 21 | end 22 | 23 | def size_of( type ) 24 | if @elements_hash_by_type[type].nil? 25 | return 0 26 | else 27 | return @elements_hash_by_type[type].size 28 | end 29 | end 30 | 31 | def []( index, type = nil ) 32 | if type.nil? 33 | return @elements[index] 34 | else 35 | return @elements_hash_by_type[type][index] 36 | end 37 | end 38 | end 39 | end -------------------------------------------------------------------------------- /lib/graphviz/types/lbl_string.rb: -------------------------------------------------------------------------------- 1 | require "rexml/document" 2 | 3 | class GraphViz 4 | class Types 5 | class LblString < Common 6 | def check(data) 7 | return data 8 | end 9 | 10 | def output 11 | html = /^<(.*)>$/m.match(@data.to_s) 12 | if html != nil 13 | xml = "" + html[1].to_s + "" 14 | begin 15 | doc = REXML::Document.new(xml) 16 | unless doc.root.text == html[1].to_s 17 | "<#{html[1]}>" 18 | else 19 | @data.to_s.inspect.gsub( "\\\\", "\\" ) 20 | end 21 | rescue REXML::ParseException => _ 22 | @data.to_s.inspect.gsub( "\\\\", "\\" ) 23 | end 24 | else 25 | @data.to_s.inspect.gsub( "\\\\", "\\" ) 26 | end 27 | end 28 | 29 | alias :to_gv :output 30 | alias :to_s :output 31 | alias :to_ruby :output 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /examples/sample03.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node["shape"] = "ellipse" 14 | g.node["sides"] = "4" 15 | g.node["peripheries"] = "" 16 | g.node["color"] = "black" 17 | g.node["style"] = "" 18 | g.node["skew"] = "0.0" 19 | g.node["distortion"] = "0.0" 20 | 21 | a = g.add_nodes( "a", "shape" => "polygon", "sides" => "5", "peripheries" => "3", "color" => "lightblue", "style" => "filled" ) 22 | b = g.add_nodes( "b" ) 23 | c = g.add_nodes( "c", "shape" => "polygon", "sides" => "4", "skew" => ".4", "label" => "hello world" ) 24 | d = g.add_nodes( "d", "shape" => "invtriangle" ) 25 | e = g.add_nodes( "e", "shape" => "polygon", "sides" => "4", "distortion" => ".7" ) 26 | 27 | g.add_edges( a, b ) 28 | g.add_edges( b, c ) 29 | g.add_edges( b, d ) 30 | 31 | g.output( :png => "#{$0}.png" ) 32 | -------------------------------------------------------------------------------- /examples/sample05.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "structs", "type" => "graph", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "structs", "type" => "graph" ) 11 | end 12 | 13 | main = g.add_nodes( "main" ) 14 | parse = g.add_nodes( "parse" ) 15 | execute = g.add_nodes( "execute" ) 16 | init = g.add_nodes( "init" ) 17 | cleanup = g.add_nodes( "cleanup" ) 18 | make_string = g.add_nodes( "make_string" ) 19 | printf = g.add_nodes( "printf" ) 20 | compare = g.add_nodes( "compare" ) 21 | 22 | g.add_edges( main, parse ) 23 | g.add_edges( parse, execute ) 24 | g.add_edges( main, init ) 25 | g.add_edges( main, cleanup ) 26 | g.add_edges( execute, make_string ) 27 | g.add_edges( execute, printf ) 28 | g.add_edges( init, make_string ) 29 | g.add_edges( main, printf ) 30 | g.add_edges( execute, compare ) 31 | 32 | g.output( :png => "#{$0}.png" ) 33 | -------------------------------------------------------------------------------- /examples/dot/dotgraph.dot: -------------------------------------------------------------------------------- 1 | digraph G { 2 | graph [truecolor=true, bgcolor=transparent]; 3 | rankdir="LR"; 4 | subgraph { 5 | rank = same; 6 | mygraph [label = "# mygraph.dot\ldigraph G {\l Hello -> World;\l}\l", shape = note, fontname = "Courier", fontsize=10]; 7 | image [image = "./hello.png", label = "", shape = note]; 8 | } 9 | subgraph { 10 | rank = same; 11 | mysite [label = "\nexample.com\n ", shape = "component", fontname = "Arial"]; 12 | dotgraph [label = "\ndotgraph.net\n ", shape = "component", fontname = "Arial"]; 13 | } 14 | subgraph cluster_0 { 15 | label = "my_page.html"; 16 | fontname = "Courier"; 17 | fontsize = 10; 18 | color = black; 19 | zeimage [image = "./hello.png", label = "", shape = note] 20 | } 21 | 22 | mygraph -> mysite [color = blue]; 23 | dotgraph -> image [color = red]; 24 | dotgraph -> mysite [color = red]; 25 | mysite -> dotgraph [color = blue]; 26 | image -> dotgraph [color = red]; 27 | mysite -> zeimage [color = red]; 28 | } -------------------------------------------------------------------------------- /lib/graphviz/types/rect.rb: -------------------------------------------------------------------------------- 1 | class RectException < RuntimeError 2 | end 3 | 4 | class GraphViz 5 | class Types 6 | class Rect < Common 7 | FLOAT_MASK = /[-+]?(?:[0-9]*\.[0-9]+|[0-9]+)/ 8 | RECT_FINAL_MASK = /#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}/ 9 | 10 | def check(data) 11 | if data.is_a?(String) and RECT_FINAL_MASK.match(data) 12 | @to_ruby = data.split(",").map{ |e| e.to_f } 13 | return data 14 | end 15 | if data.is_a?(Array) 16 | return check(data.join(",")) 17 | end 18 | return nil if data.is_a?(String) and data.empty? 19 | 20 | raise RectException, "Invalid rect value" 21 | end 22 | 23 | def output 24 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 25 | end 26 | 27 | alias :to_gv :output 28 | alias :to_s :output 29 | 30 | def to_ruby 31 | @to_ruby 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /man/xml2gv.1.ronn: -------------------------------------------------------------------------------- 1 | xml2gv(1) - show your xml files graphically 2 | =========================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `xml2gv` [`-T`] [`-o`] [`-h`] [`-V`] _script_ 7 | 8 | ## DESCRIPTION 9 | 10 | `xml2gv` is a tool that allows you to show a xml file as a graph. 11 | 12 | See for more details. 13 | 14 | ## OPTIONS 15 | 16 | * `-T`, `--output-format` []: 17 | Output format (default: png) 18 | 19 | * `-o`, `--output-file` []: 20 | Output file (default: STDOUT) 21 | 22 | * `-p`, `--path`: 23 | Graphviz path 24 | 25 | * `-u`, `--use` []: 26 | Program to use (default: dot) 27 | 28 | * `-V`, `--version`: 29 | Show version 30 | 31 | * `-h`, `--help`: 32 | Show this usage message 33 | 34 | ## AUTHOR 35 | 36 | Copyright 2004-2018 Gregoire Lejeune 37 | 38 | This manual page is written by Praveen Arimbrathodiyl for 39 | Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd). 40 | -------------------------------------------------------------------------------- /examples/graphml/hyper.graphml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /lib/graphviz/family_tree/generation.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class FamilyTree 3 | class Generation 4 | def initialize( graph, persons, tree, gen_number ) #:nodoc: 5 | @graph = graph 6 | @all_persons = persons 7 | @persons = {} 8 | @tree = tree 9 | @gen_number = gen_number 10 | end 11 | 12 | def all_persons #:nodoc: 13 | @all_persons 14 | end 15 | 16 | def persons 17 | @persons 18 | end 19 | 20 | def make( &block ) #:nodoc: 21 | instance_eval(&block) if block 22 | end 23 | 24 | def method_missing(sym, *args, &block) #:nodoc: 25 | all_persons[sym.to_s] ||= (persons[sym.to_s] ||= GraphViz::FamilyTree::Person.new( @graph, @tree, self, sym.to_s )) 26 | end 27 | 28 | # Generation number 29 | def number 30 | @gen_number 31 | end 32 | 33 | # Generation size 34 | def size 35 | @persons.size 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /man/git2gv.1.ronn: -------------------------------------------------------------------------------- 1 | git2gv(1) - show your git commits graphically 2 | ============================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `git2gv` [`-T`] [`-o`] [`-h`] [`-V`] 7 | 8 | ## DESCRIPTION 9 | 10 | `git2gv` is a tool that allows you to show your git commits 11 | graphically. 12 | 13 | See for more details. 14 | 15 | ## OPTIONS 16 | 17 | * `-T`, `--output-format` []: 18 | Output format (default: png) 19 | 20 | * `--nothugly`: 21 | Use nothugly if SVG output 22 | 23 | * `-o`, `--output-file` []: 24 | Path to output image file (default: STDOUT) 25 | 26 | * `-p`, `--path`: 27 | Graphviz path 28 | 29 | * `-V`, `--version`: 30 | Show version 31 | 32 | * `-h`, `--help`: 33 | Show this usage message 34 | 35 | ## AUTHOR 36 | 37 | Copyright 2004-2018 Gregoire Lejeune 38 | 39 | This manual page is written by Praveen Arimbrathodiyl for 40 | Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd). 41 | -------------------------------------------------------------------------------- /examples/dot/JSP.dot: -------------------------------------------------------------------------------- 1 | digraph fig7 { 2 | node [shape=rect] 3 | edge [dir=none] 4 | 5 | subgraph compound1 { 6 | a [label="LFILE"] 7 | b [label="*\rLREC"] 8 | c [label="o\rMATCHED LREC"] 9 | d [label="o\rUNMATCHED LREC"] 10 | 11 | a -> {b} 12 | b -> {c d} 13 | } 14 | 15 | subgraph compound2 { 16 | e [label="RFILE"] 17 | f [label="*\rRREC"] 18 | g [label="o\rMATCHED RREC"] 19 | h [label="o\rUNMATCHED RREC"] 20 | 21 | e -> {f} 22 | f -> {g h} 23 | } 24 | 25 | subgraph compound3 { 26 | i [label="REPORT"] 27 | j [label="*\rLINE"] 28 | k [label="o\rTYPE 1"] 29 | l [label="o\rTYPE 2"] 30 | m [label="o\rTYPE 3"] 31 | n [label="o\rTYPE 4"] 32 | 33 | i -> {j} 34 | j -> {k l m n} 35 | } 36 | 37 | {rank=same a e i} 38 | {rank=same b f j} 39 | {rank=same c d g h k l m n} 40 | 41 | subgraph correspondences { 42 | edge [dir=both] 43 | 44 | a -> e 45 | e -> i 46 | 47 | c -> g:s 48 | d -> l:s 49 | g -> k:s 50 | h -> m:s 51 | } 52 | } -------------------------------------------------------------------------------- /examples/sample36.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | GraphViz.graph( :G ) { |g| 7 | last_line = [] 8 | node_number = 0 9 | 10 | 100.times do |j| 11 | # New_Line 12 | new_line = [] 13 | c = g.subgraph( :rank => "same" ) 14 | 15 | 100.times do |i| 16 | current_node = c.add_nodes( "N#{node_number}", :shape => "point", :label => "" ) 17 | last_node = new_line[-1] 18 | unless last_node.nil? 19 | c.add_edges( last_node, current_node ) 20 | end 21 | new_line << current_node 22 | top_first_node = last_line.shift 23 | unless top_first_node.nil? 24 | g.add_edges( top_first_node, current_node ) 25 | top_second_node = last_line.shift 26 | unless top_second_node.nil? 27 | g.add_edges( top_second_node, current_node ) 28 | last_line.unshift( top_second_node ) 29 | end 30 | end 31 | node_number = node_number + 1 32 | end 33 | last_line = new_line 34 | end 35 | }.output( :png => "#{$0}.png" ) 36 | -------------------------------------------------------------------------------- /examples/test.xml: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | Invisibility Cream 5 | 14.50 6 | Makes you invisible 7 | 8 | 9 | Levitation Salve 10 | 23.99 11 | Levitate yourself for up to 3 hours per application 12 | 13 |
14 |
15 | 16 | Blork and Freen Instameal 17 | 4.95 18 | A tasty meal in a tablet; just add water 19 | 20 | 21 | Grob winglets 22 | 3.56 23 | Tender winglets of Grob. Just add water 24 | 25 |
26 |
27 | -------------------------------------------------------------------------------- /examples/sample18.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G", :rankdir => "LR", :size => "8,5" ) { |graph| 7 | graph.node[:shape] = "doublecircle" 8 | graph._LR_0; graph._LR_3; graph._LR_4; graph._LR_8 9 | graph.node[:shape] = "circle" 10 | (graph._LR_0 << graph._LR_2)[:label] = "SS(B)" 11 | (graph._LR_0 << graph._LR_1)[:label] = "SS(S)" 12 | (graph._LR_1 << graph._LR_3)[:label] = "S($end)" 13 | (graph._LR_2 << graph._LR_6)[:label] = "SS(b)" 14 | (graph._LR_2 << graph._LR_5)[:label] = "SS(a)" 15 | (graph._LR_2 << graph._LR_4)[:label] = "S(A)" 16 | (graph._LR_5 << graph._LR_7)[:label] = "S(b)" 17 | (graph._LR_5 << graph._LR_5)[:label] = "S(a)" 18 | (graph._LR_6 << graph._LR_6)[:label] = "S(b)" 19 | (graph._LR_6 << graph._LR_5)[:label] = "S(a)" 20 | (graph._LR_7 << graph._LR_8)[:label] = "S(b)" 21 | (graph._LR_7 << graph._LR_5)[:label] = "S(a)" 22 | (graph._LR_8 << graph._LR_6)[:label] = "S(b)" 23 | (graph._LR_8 << graph._LR_5)[:label] = "S(a)" 24 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample11.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | graph = nil 7 | if ARGV[0] 8 | graph = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | graph = GraphViz::new( "G" ) 11 | end 12 | 13 | graph["compound"] = "true" 14 | graph.edge["lhead"] = "" 15 | graph.edge["ltail"] = "" 16 | 17 | c0 = graph.add_graph( "cluster0" ) 18 | a = c0.add_nodes( "a" ) 19 | b = c0.add_nodes( "b" ) 20 | c = c0.add_nodes( "c" ) 21 | d = c0.add_nodes( "d" ) 22 | c0.add_edges( a, b ) 23 | c0.add_edges( a, c ) 24 | c0.add_edges( b, d ) 25 | c0.add_edges( c, d ) 26 | 27 | c1 = graph.add_graph( "cluster1" ) 28 | e = c1.add_nodes( "e" ) 29 | f = c1.add_nodes( "f" ) 30 | g = c1.add_nodes( "g" ) 31 | c1.add_edges( e, g ) 32 | c1.add_edges( e, f ) 33 | 34 | h = graph.add_nodes( "h" ) 35 | 36 | graph.add_edges( b, f, "lhead" => "cluster1" ) 37 | graph.add_edges( d, e ) 38 | graph.add_edges( c, g, "ltail" => "cluster0", "lhead" => "cluster1" ) 39 | graph.add_edges( c, e, "ltail" => "cluster0" ) 40 | graph.add_edges( d, h ) 41 | 42 | graph.output( :png => "#{$0}.png" ) 43 | -------------------------------------------------------------------------------- /examples/sample33.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require 'graphviz/family_tree' 3 | 4 | tree = GraphViz::FamilyTree.new do 5 | generation do 6 | abraham.is_a_man( "Abraham" ) 7 | mona.is_a_woman( "Mona" ) 8 | 9 | abraham.is_maried_with mona 10 | 11 | clancy.is_a_man( "Clancy" ) 12 | jackeline.is_a_woman( "Jackeline" ) 13 | 14 | clancy.is_maried_with jackeline 15 | end 16 | 17 | generation do 18 | herb.is_a_man( "Herb" ) 19 | homer.is_a_man( "Homer" ) 20 | 21 | marge.is_a_woman( "Marge" ) 22 | patty.is_a_woman( "Patty" ) 23 | selma.is_a_woman( "Selma" ) 24 | 25 | homer.is_maried_with marge 26 | end 27 | 28 | couple( abraham, mona ).kids( herb, homer ) 29 | couple( clancy, jackeline ).kids( marge, patty, selma ) 30 | 31 | generation do 32 | bart.is_a_boy( "Bart" ) 33 | lisa.is_a_girl( "Lisa" ) 34 | maggie.is_a_girl( "Maggie" ) 35 | ling.is_a_boy( "Ling" ) 36 | end 37 | 38 | couple( homer, marge ).kids( bart, lisa, maggie ) 39 | 40 | ling.kids( selma ) 41 | end 42 | 43 | puts tree.graph.save( :none => String ) 44 | -------------------------------------------------------------------------------- /examples/sample43.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require "graphviz" 3 | 4 | g = GraphViz::new( "structs" ) 5 | 6 | g.node["shape"] = "plaintext" 7 | 8 | g.add_nodes( "HTML" ) 9 | 10 | g.add_nodes( "struct1", "label" => '< 11 | 12 | 13 | 14 | 15 | 16 |
leftmid dleright
>' ) 17 | 18 | g.add_nodes( "struct2", "label" => '<
onetwo
>' ) 19 | g.add_nodes( "struct3", "label" => '<
hello
world
b g h
cde
f
>' ) 20 | 21 | g.add_edges( {"struct1" => :f1}, {"struct2" => :f0} ) 22 | g.add_edges( {"struct1" => :f2}, {"struct3" => :here} ) 23 | 24 | g.add_edges( "HTML", "struct1" ) 25 | 26 | g.output( :path => ARGV[0], :png => "#{$0}.png" ) 27 | -------------------------------------------------------------------------------- /examples/dot/this_crach_with_dot_2.20.dot: -------------------------------------------------------------------------------- 1 | graph A 2 | { 3 | graph [nodesep="0.10", size="7,5", bb="0,0,737,832"]; 4 | node [fontsize="12.00", shape=circle, height = 0.4 width = 0.4 fixedsize="true"]; 5 | 779 -- 780 [label = 6.5 style = "bold" ]; 6 | 522 -- 523 [label = 6.2 style = "bold" ]; 7 | 527 -- 528 [label = 6.0 style = "bold" ]; 8 | 752 -- 753 [label = 5.1 style = "solid"]; 9 | 576 -- 577 [label = 5.1 style = "solid"]; 10 | 578 -- 579 [label = 4.8 style = "dashed"]; 11 | 757 -- 758 [label = 4.6 style = "dashed"]; 12 | 696 -- 697 [label = 4.5 style = "dashed"]; 13 | 542 -- 543 [label = 4.4 style = "dashed"]; 14 | 723 -- 724 [label = 4.4 style = "dashed"]; 15 | 495 -- 496 [label = 4.4 style = "dashed"]; 16 | 459 -- 460 [label = 4.3 style = "dashed"]; 17 | 784 -- 785 [label = 4.2 style = "dashed"]; 18 | 518 -- 519 [label = 4.2 style = "dashed"]; 19 | 894 -- 895 [label = 4.1 style = "dashed"]; 20 | 435 -- 436 [label = 4.1 style = "dashed"]; 21 | 322 -- 323 [label = 4.1 style = "dashed"]; 22 | 545 -- 546 [label = 4.1 style = "dashed"]; 23 | 513 -- 514 [label = 4.0 style = "dashed"]; 24 | } -------------------------------------------------------------------------------- /examples/sample42.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0], :use => "circo" ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | c0 = g.add_graph( "cluster0" ) 14 | c0["label"] = "Environnement de Brad !" 15 | c0["style"] = "filled" 16 | c0["color"] = "blue" 17 | 18 | ja = c0.add_nodes( "Jennifer_Aniston", :style => "filled", :color => "red" ) 19 | bp = c0.add_nodes( "Brad_Pitt", :style => "filled", :color => "white" ) 20 | aj = c0.add_nodes( "Angelina_Jolie", :style => "filled", :color => "green" ) 21 | 22 | c0.add_edges( ja, bp ) # On ete mariés 23 | c0.add_edges( bp, aj ) # Sont ensemble 24 | 25 | jv = g.add_nodes( "John_Voight", :label => "John Voight", :shape => "rectangle" ) 26 | md = g.add_nodes( "Madonna" ) 27 | gr = g.add_nodes( "Guy_Ritchie" ) 28 | 29 | g.add_edges( aj, jv ) # est la fille de 30 | g.add_edges( jv, aj ) # est le pere de 31 | g.add_edges( bp, jv, :color => "red", :label => "Est le beau fils de" ) # Beau fils 32 | g.add_edges( bp, gr ) 33 | g.add_edges( gr, md ) 34 | 35 | g.output( :png => "#{$0}.png" ) 36 | -------------------------------------------------------------------------------- /examples/dot/so-sample003.gv: -------------------------------------------------------------------------------- 1 | 2 | //{:category1 => 3 | // {:subcategory1 => 4 | // [ 5 | // {:article => "some article", :date => "2010-04-04"}, 6 | // ... 7 | // ], 8 | // :subc2 => [...] 9 | // }, 10 | // :category2 => {...}, 11 | // ... 12 | //} 13 | 14 | graph G { 15 | layout="fdp" 16 | 17 | category1[label=":category1", shape="box"] 18 | 19 | subgraph cluster_category1 { 20 | subcategory1[label=":subcategory1", shape="box"] 21 | subc2[label=":subc2", shape="box"] 22 | 23 | subgraph cluster_subcategory1 { 24 | subgraph cluster_subcategory1_Array0 { 25 | article0[label=":article", shape="box"] 26 | date0[label=":date", shape="box"] 27 | 28 | article0 -- "somme article" 29 | date0 -- "2010-04-04" 30 | } 31 | subgraph cluster_subcategory1_Array1 { 32 | article1[label=":article", shape="box"] 33 | date1[label=":date", shape="box"] 34 | 35 | article1 -- "an other article" 36 | date1 -- "2010-09-09" 37 | } 38 | } 39 | 40 | subcategory1 -- cluster_subcategory1 41 | subc2 -- "..." 42 | } 43 | 44 | category1 -- cluster_category1 45 | } -------------------------------------------------------------------------------- /examples/graphml/port.graphml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/graphml/simple.graphml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /man/gem2gv.1.ronn: -------------------------------------------------------------------------------- 1 | gem2gv(1) - create a dependency graph between gems 2 | ================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `gem2gv` [`-T`] [`-o`] [`-h`] [`-V`] 7 | 8 | ## DESCRIPTION 9 | 10 | `gem2gv` is a tool that allows you to create a dependency graph 11 | between gems. 12 | 13 | See for more details. 14 | 15 | ## OPTIONS 16 | 17 | * `-T`, `--output-format` []: 18 | Output format (default: png) 19 | 20 | * `-o`, `--output-file` []: 21 | Path to output image file (default: STDOUT) 22 | 23 | * `-p`, `--path`: 24 | Graphviz path 25 | 26 | * `-u`, `--use` []: 27 | Program to use (default: dot) 28 | 29 | * `-s`, `--stop` [,[, ...]]: 30 | Stop on libs 31 | 32 | * `-V`, `--version`: 33 | Show version 34 | 35 | * `-h`, `--help`: 36 | Show this usage message 37 | 38 | ## EXAMPLE 39 | 40 | gem2gv -Tpng -oruby-graphviz.png ruby-graphviz 41 | 42 | ## AUTHOR 43 | 44 | Copyright 2004-2018 Gregoire Lejeune 45 | 46 | This manual page is written by Praveen Arimbrathodiyl for 47 | Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd). 48 | -------------------------------------------------------------------------------- /man/ruby2gv.1.ronn: -------------------------------------------------------------------------------- 1 | ruby2gv(1) - create a dependency graph from a ruby script 2 | ========================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `ruby2gv` [`-T`] [`-o`] [`-h`] [`-V`] _script_ 7 | 8 | ## DESCRIPTION 9 | 10 | `ruby2gv` is a simple tool that allows you to create a dependency graph 11 | from a ruby script. 12 | 13 | See for more details. 14 | 15 | ## OPTIONS 16 | 17 | * `-T`, `--output-format` []: 18 | Output format (default: png) 19 | 20 | * `-o`, `--output-file` []: 21 | Path to output image file (default: STDOUT) 22 | 23 | * `-p`, `--path`: 24 | Graphviz path 25 | 26 | * `-u`, `--use` []: 27 | Program to use (default: dot) 28 | 29 | * `-s`, `--stop` [,[, ...]]: 30 | Stop on libs 31 | 32 | * `-V`, `--version`: 33 | Show version 34 | 35 | * `-h`, `--help`: 36 | Show this usage message 37 | 38 | ## EXAMPLE 39 | 40 | ruby2gv -Tpng -oruby2gv.png /usr/bin/ruby2gv 41 | 42 | ## AUTHOR 43 | 44 | Copyright 2004-2018 Gregoire Lejeune 45 | 46 | This manual page is written by Praveen Arimbrathodiyl for 47 | Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd). 48 | -------------------------------------------------------------------------------- /man/git2gv.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" https://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "GIT2GV" "1" "April 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBgit2gv\fR \- show your git commits graphically 8 | . 9 | .SH "SYNOPSIS" 10 | \fBgit2gv\fR [\fB\-T\fR\fIformat\fR] [\fB\-o\fR\fIfile\fR] [\fB\-h\fR] [\fB\-V\fR] 11 | . 12 | .SH "DESCRIPTION" 13 | \fBgit2gv\fR is a tool that allows you to show your git commits graphically\. 14 | . 15 | .P 16 | See for more details\. 17 | . 18 | .SH "OPTIONS" 19 | . 20 | .TP 21 | \fB\-T\fR, \fB\-\-output\-format\fR [\fIformat\fR] 22 | Output format (default: png) 23 | . 24 | .TP 25 | \fB\-\-nothugly\fR 26 | Use nothugly if SVG output 27 | . 28 | .TP 29 | \fB\-o\fR, \fB\-\-output\-file\fR [\fIfile\fR] 30 | Path to output image file (default: STDOUT) 31 | . 32 | .TP 33 | \fB\-p\fR, \fB\-\-path\fR 34 | Graphviz path 35 | . 36 | .TP 37 | \fB\-V\fR, \fB\-\-version\fR 38 | Show version 39 | . 40 | .TP 41 | \fB\-h\fR, \fB\-\-help\fR 42 | Show this usage message 43 | . 44 | .SH "AUTHOR" 45 | Copyright 2004\-2013 Gregoire Lejeune 46 | . 47 | .P 48 | This manual page is written by Praveen Arimbrathodiyl \fIpraveen@debian\.org\fR for Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd)\. 49 | -------------------------------------------------------------------------------- /man/xml2gv.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" https://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "XML2GV" "1" "April 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBxml2gv\fR \- show your xml files graphically 8 | . 9 | .SH "SYNOPSIS" 10 | \fBxml2gv\fR [\fB\-T\fR\fIformat\fR] [\fB\-o\fR\fIfile\fR] [\fB\-h\fR] [\fB\-V\fR] \fIscript\fR 11 | . 12 | .SH "DESCRIPTION" 13 | \fBxml2gv\fR is a tool that allows you to show a xml file as a graph\. 14 | . 15 | .P 16 | See for more details\. 17 | . 18 | .SH "OPTIONS" 19 | . 20 | .TP 21 | \fB\-T\fR, \fB\-\-output\-format\fR [\fIformat\fR] 22 | Output format (default: png) 23 | . 24 | .TP 25 | \fB\-o\fR, \fB\-\-output\-file\fR [\fIfile\fR] 26 | Output file (default: STDOUT) 27 | . 28 | .TP 29 | \fB\-p\fR, \fB\-\-path\fR 30 | Graphviz path 31 | . 32 | .TP 33 | \fB\-u\fR, \fB\-\-use\fR [\fIPROGRAM\fR] 34 | Program to use (default: dot) 35 | . 36 | .TP 37 | \fB\-V\fR, \fB\-\-version\fR 38 | Show version 39 | . 40 | .TP 41 | \fB\-h\fR, \fB\-\-help\fR 42 | Show this usage message 43 | . 44 | .SH "AUTHOR" 45 | Copyright 2004\-2013 Gregoire Lejeune 46 | . 47 | .P 48 | This manual page is written by Praveen Arimbrathodiyl \fIpraveen@debian\.org\fR for Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd)\. 49 | -------------------------------------------------------------------------------- /examples/sample06.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require "graphviz" 3 | 4 | GraphViz::new( "G", :rankdir => "LR", :type => "graph" ) { |graph| 5 | graph.cluster0 { |cluster| 6 | cluster[:label] = "Back Office" 7 | 8 | cluster.fatman.set { |n| 9 | n.label = "FatMan" 10 | n.shape = "rect" 11 | } 12 | cluster.grobil.set { |n| 13 | n.label = "GroBil" 14 | n.shape = "rect" 15 | } 16 | } 17 | 18 | graph.cluster1 { |cluster| 19 | cluster[:label] = "DMZ" 20 | 21 | cluster.dupont.set { |n| 22 | n.label = "Dupont" 23 | n.shape = "rect" 24 | } 25 | cluster.dupond.set { |n| 26 | n.label = "Dupond" 27 | n.shape = "rect" 28 | } 29 | } 30 | 31 | graph.cluster2() { |cluster| 32 | cluster[:label] = "Front Office" 33 | 34 | cluster.door.set { |n| 35 | n.label = "Door" 36 | n.shape = "rect" 37 | } 38 | } 39 | 40 | graph.cluster0.fatman << graph.cluster1.dupont 41 | graph.cluster0.fatman << graph.cluster1.dupond 42 | graph.cluster0.grobil << graph.cluster1.dupont 43 | graph.cluster0.grobil << graph.cluster1.dupond 44 | graph.cluster1.dupont << graph.cluster2.door 45 | graph.cluster1.dupond << graph.cluster2.door 46 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample14.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G" ) { |graph| 7 | graph.node[:shape] = "ellipse" 8 | graph.node[:color] = "black" 9 | 10 | graph[:color] = "black" 11 | 12 | graph.cluster0( ) do |cluster| 13 | cluster[:label] = "process #1" 14 | cluster[:style] = "filled" 15 | cluster[:color] = "lightgrey" 16 | 17 | cluster.node[:style] = "filled" 18 | cluster.node[:color] = "white" 19 | 20 | cluster.a0 << cluster.a1 21 | cluster.a1 << cluster.a2 22 | cluster.a2 << cluster.a3 23 | end 24 | 25 | graph.cluster1( :label => "process #2", :color => "blue" ) do |cluster| 26 | cluster.node[:style] = "filled" 27 | cluster.node[:color] = "lightgrey" 28 | 29 | cluster.b0 << cluster.b1 30 | cluster.b1 << cluster.b2 31 | cluster.b2 << cluster.b3 32 | end 33 | 34 | graph.start :shape => "Mdiamond" 35 | graph.endn :shape => "Msquare", :label => "end" 36 | 37 | graph.start << graph.cluster0.a0 38 | graph.start << graph.cluster1.b0 39 | graph.cluster0.a1 << graph.cluster1.b3 40 | graph.cluster1.b2 << graph.cluster0.a3 41 | graph.cluster0.a3 << graph.cluster0.a0 42 | graph.cluster0.a3 << graph.endn 43 | graph.cluster1.b3 << graph.endn 44 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample02.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", :path => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node[:shape] = "ellipse" 14 | g.node[:color] = "black" 15 | 16 | g.edge[:color] = "black" 17 | g.edge[:weight] = "1" 18 | g.edge[:style] = "filled" 19 | g.edge[:label] = "" 20 | 21 | g[:size] = "4,4" 22 | 23 | main = g.add_nodes( "main", :shape => "box" ) 24 | parse = g.add_nodes( "parse" ) 25 | execute = g.add_nodes( "execute" ) 26 | init = g.add_nodes( "init" ) 27 | cleanup = g.add_nodes( "cleanup" ) 28 | make_string = g.add_nodes( "make_string", :label => 'make a\nstring' ) 29 | printf = g.add_nodes( "printf" ) 30 | compare = g.add_nodes( "compare", :shape => "box", :style => "filled", :color => ".7 .3 1.0" ) 31 | 32 | g.add_edges( main, parse, :weight => "8" ) 33 | g.add_edges( parse, execute ) 34 | g.add_edges( main, init, :style => "dotted" ) 35 | g.add_edges( main, cleanup ) 36 | g.add_edges( execute, make_string ) 37 | g.add_edges( execute, printf ) 38 | g.add_edges( init, make_string ) 39 | g.add_edges( main, printf, :color => "red", :style => "bold", :label => "100 times" ) 40 | g.add_edges( execute, compare, :color => "red" ) 41 | 42 | g.output( :png => "#{$0}.png" ) 43 | -------------------------------------------------------------------------------- /examples/sample46.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node["color"] = "black" 14 | 15 | g.edge["color"] = "black" 16 | g.edge["weight"] = "1" 17 | g.edge["style"] = "filled" 18 | g.edge["label"] = "" 19 | 20 | g["size"] = "4,4" 21 | 22 | g.node["shape"] = "box" 23 | main = g.add_nodes( "main" ) 24 | g.node["shape"] = "ellipse" 25 | parse = g.add_nodes( "parse" ) 26 | execute = g.add_nodes( "execute" ) 27 | init = g.add_nodes( "init" ) 28 | cleanup = g.add_nodes( "cleanup" ) 29 | make_string = g.add_nodes( "make_string", "label" => 'make a\nstring' ) 30 | printf = g.add_nodes( "printf" ) 31 | compare = g.add_nodes( "compare", "shape" => "box", "style" => "filled", "color" => ".7 .3 1.0" ) 32 | 33 | g.add_edges( main, parse, "weight" => "8" ) 34 | g.add_edges( parse, execute ) 35 | g.add_edges( main, init, "style" => "dotted" ) 36 | g.add_edges( main, cleanup ) 37 | g.add_edges( execute, make_string ) 38 | g.add_edges( execute, printf ) 39 | g.add_edges( init, make_string ) 40 | g.add_edges( main, printf, "color" => "red", "style" => "bold", "label" => "100 times" ) 41 | g.add_edges( execute, compare, "color" => "red" ) 42 | 43 | g.output( :png => "#{$0}.png" ) 44 | -------------------------------------------------------------------------------- /test/test_dot_script.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class GraphVizDOTScriptTest < Test::Unit::TestCase 4 | def setup 5 | @script = GraphViz::DOTScript.new 6 | end 7 | 8 | def test_appends_a_newline_character_if_it_is_missing 9 | str = "Test without newline" 10 | @script.append(str) 11 | assert_equal @script.to_s, str + "\n" 12 | end 13 | 14 | def test_does_not_append_a_newline_if_already_present 15 | str = "Linebreak follows at my tail:\n" 16 | @script.append(str) 17 | assert_equal @script.to_s, str 18 | end 19 | 20 | def test_can_prepend_lines_to_its_content 21 | start_content = "I want to be at the top!\n" 22 | additional_content = "No way!\n" 23 | 24 | @script.append(start_content) 25 | @script.prepend(additional_content) 26 | 27 | assert_equal @script.to_s, additional_content + start_content 28 | end 29 | 30 | def test_can_add_types_with_data 31 | data = "some random data" 32 | @script.add_type("node_attr", data) 33 | assert_match(/\s*node\s*\[\s*#{data}\s*\]\s*/, @script.to_s) 34 | end 35 | 36 | def test_does_nothing_if_data_is_empty 37 | @script.add_type("anything", "") 38 | assert_equal true, @script.to_s.empty? 39 | end 40 | 41 | def test_raises_an_argument_error_on_unknown_types 42 | assert_raise ArgumentError do 43 | @script.add_type("invalid", "some data") 44 | end 45 | end 46 | end 47 | 48 | -------------------------------------------------------------------------------- /examples/sample35.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ) 4 | require "graphviz" 5 | 6 | GraphViz.digraph( :G ) { |g| 7 | g[:truecolor => true, :bgcolor => "transparent", :rankdir => "LR"] 8 | g.node[:label => "\N"] 9 | 10 | c1 = g.subgraph { |c| 11 | c[:rank => "same"] 12 | c.mygraph[ 13 | :label => '# mygraph.dot\ldigraph G {\l Hello -> World\l}\l', 14 | :shape => "note", 15 | :fontname => "Courier", 16 | :fontsize => 10 17 | ] 18 | c.image[ :label => "", :shape => "note", :image => "./hello.png"] 19 | } 20 | 21 | c2 = g.subgraph { |c| 22 | c[:rank => "same"] 23 | c.mysite[:label => "\nexample.com\n ", :shape => "component", :fontname => "Arial"] 24 | c.dotgraph[:label => "\ndotgraph.net\n ", :shape => "component", :fontname => "Arial"] 25 | } 26 | 27 | g.cluster_0 { |c| 28 | c[ 29 | :label => "my_page.html", 30 | :fontname => "Courier", 31 | :fontsize => 10, 32 | :color => "black" 33 | ] 34 | c.zeimage[:label => "", :shape => "note", :image => "./hello.png"] 35 | } 36 | 37 | (c1.mygraph << c2.mysite)[:color => "blue"] 38 | (c2.dotgraph << c1.image)[:color => "red"] 39 | (c2.dotgraph << c2.mysite)[:color => "red"] 40 | (c2.mysite << c2.dotgraph)[:color => "blue"] 41 | (c1.image << c2.dotgraph)[:color => "red"] 42 | (c2.mysite << g.cluster_0.zeimage)[:color => "red"] 43 | }.output( :png => "#{$0}.png", :none => "#{$0}.gv" ) 44 | -------------------------------------------------------------------------------- /lib/graphviz/types/gv_bool.rb: -------------------------------------------------------------------------------- 1 | class BoolException < RuntimeError 2 | end 3 | 4 | # bool 5 | # 6 | # For the bool type, 7 | # - TRUE values are represented by "true" or "yes" (case-insensitive), true and any non-zero integer 8 | # - FALSE values by "false", "no" or empty string (case-insensitive), false and zero. 9 | # 10 | # Example 11 | # 12 | # graph[:center] = "true" 13 | # or 14 | # graph[:center] = true 15 | # or 16 | # graph[:center] = 23 17 | class GraphViz 18 | class Types 19 | class GvBool < Common 20 | BOOL_TRUE = ["true", "yes"] 21 | BOOL_FALSE = ["false", "no", ""] 22 | 23 | def check(data) 24 | if true == data or (data.is_a?(Integer) and data != 0) or (data.is_a?(String) and !BOOL_FALSE.include?(data.downcase)) 25 | @to_ruby = true 26 | return data 27 | end 28 | 29 | if false == data or (data.is_a?(Integer) and data == 0) or (data.is_a?(String) and BOOL_FALSE.include?(data.downcase)) 30 | @to_ruby = false 31 | return data 32 | end 33 | 34 | raise BoolException, "Invalid bool value" 35 | end 36 | 37 | def output 38 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 39 | end 40 | 41 | alias :to_gv :output 42 | alias :to_s :output 43 | 44 | def to_ruby 45 | @to_ruby 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /examples/sample08.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G" "nodesep" => ".05", "rankdir" => "LR", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G", "nodesep" => ".05", "rankdir" => "LR" ) 11 | end 12 | 13 | g.node["shape"] = "record" 14 | g.node["width"] = ".1" 15 | g.node["height"] = ".1" 16 | 17 | g.add_nodes( "node0", "label" => " | | | | | | | | ", "height" => "2.5" ) 18 | g.add_nodes( "node1", "label" => "{ n14 | 719 |

}", "width" => "1.5" ) 19 | g.add_nodes( "node2", "label" => "{ a1 | 805 |

}", "width" => "1.5" ) 20 | g.add_nodes( "node3", "label" => "{ i9 | 718 |

}", "width" => "1.5" ) 21 | g.add_nodes( "node4", "label" => "{ e5 | 989 |

}", "width" => "1.5" ) 22 | g.add_nodes( "node5", "label" => "{ t20 | 959 |

}", "width" => "1.5" ) 23 | g.add_nodes( "node6", "label" => "{ o15 | 794 |

}", "width" => "1.5" ) 24 | g.add_nodes( "node7", "label" => "{ s19 | 659 |

}", "width" => "1.5" ) 25 | 26 | g.add_edges( {"node0" => :f0}, {"node1" => :n} ) 27 | g.add_edges( {"node0" => :f1}, {"node2" => :n} ) 28 | g.add_edges( {"node0" => :f2}, {"node3" => :n} ) 29 | g.add_edges( {"node0" => :f5}, {"node4" => :n} ) 30 | g.add_edges( {"node0" => :f6}, {"node5" => :n} ) 31 | g.add_edges( {"node2" => :p}, {"node6" => :n} ) 32 | g.add_edges( {"node4" => :p}, {"node7" => :n} ) 33 | 34 | g.output( :png => "#{$0}.png" ) 35 | -------------------------------------------------------------------------------- /man/gem2gv.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" https://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "GEM2GV" "1" "April 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBgem2gv\fR \- create a dependency graph between gems 8 | . 9 | .SH "SYNOPSIS" 10 | \fBgem2gv\fR [\fB\-T\fR\fIformat\fR] [\fB\-o\fR\fIfile\fR] [\fB\-h\fR] [\fB\-V\fR] \fIgemname\fR 11 | . 12 | .SH "DESCRIPTION" 13 | \fBgem2gv\fR is a tool that allows you to create a dependency graph between gems\. 14 | . 15 | .P 16 | See for more details\. 17 | . 18 | .SH "OPTIONS" 19 | . 20 | .TP 21 | \fB\-T\fR, \fB\-\-output\-format\fR [\fIformat\fR] 22 | Output format (default: png) 23 | . 24 | .TP 25 | \fB\-o\fR, \fB\-\-output\-file\fR [\fIfile\fR] 26 | Path to output image file (default: STDOUT) 27 | . 28 | .TP 29 | \fB\-p\fR, \fB\-\-path\fR 30 | Graphviz path 31 | . 32 | .TP 33 | \fB\-u\fR, \fB\-\-use\fR [\fIPROGRAM\fR] 34 | Program to use (default: dot) 35 | . 36 | .TP 37 | \fB\-s\fR, \fB\-\-stop\fR \fILIB\fR[,\fILIB\fR[, \.\.\.]] 38 | Stop on libs 39 | . 40 | .TP 41 | \fB\-V\fR, \fB\-\-version\fR 42 | Show version 43 | . 44 | .TP 45 | \fB\-h\fR, \fB\-\-help\fR 46 | Show this usage message 47 | . 48 | .SH "EXAMPLE" 49 | . 50 | .nf 51 | 52 | gem2gv \-Tpng \-oruby\-graphviz\.png ruby\-graphviz 53 | . 54 | .fi 55 | . 56 | .SH "AUTHOR" 57 | Copyright 2004\-2013 Gregoire Lejeune 58 | . 59 | .P 60 | This manual page is written by Praveen Arimbrathodiyl \fIpraveen@debian\.org\fR for Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd)\. 61 | -------------------------------------------------------------------------------- /examples/graphml/attributes.graphml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | yellow 7 | 8 | 9 | 10 | 11 | green 12 | 13 | 14 | 15 | blue 16 | 17 | 18 | red 19 | 20 | 21 | 22 | turquoise 23 | 24 | 25 | 1.0 26 | 27 | 28 | 1.0 29 | 30 | 31 | 2.0 32 | 33 | 34 | 35 | 36 | 37 | 1.1 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /examples/sample12.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node[:shape] = "ellipse" 14 | g.node[:color] = "black" 15 | 16 | g[:color] = "black" 17 | 18 | g.cluster0( ) do |cluster| 19 | cluster[:label] = "process #1" 20 | cluster[:style] = "filled" 21 | cluster[:color] = "lightgrey" 22 | 23 | cluster.a0 :style => "filled", :color => "white" 24 | cluster.a1 :style => "filled", :color => "white" 25 | cluster.a2 :style => "filled", :color => "white" 26 | cluster.a3 :style => "filled", :color => "white" 27 | 28 | cluster.a0 << cluster.a1 29 | cluster.a1 << cluster.a2 30 | cluster.a2 << cluster.a3 31 | end 32 | 33 | g.cluster1( :label => "process #2" ) do |cluster| 34 | cluster.b0 :style => "filled", :color => "blue" 35 | cluster.b1 :style => "filled", :color => "blue" 36 | cluster.b2 :style => "filled", :color => "blue" 37 | cluster.b3 :style => "filled", :color => "blue" 38 | 39 | cluster.b0 << cluster.b1 40 | cluster.b1 << cluster.b2 41 | cluster.b2 << cluster.b3 42 | end 43 | 44 | g.start :shape => "Mdiamond" 45 | g.endn :shape => "Msquare", :label => "end" 46 | 47 | g.start << g.cluster0.a0 48 | g.start << g.cluster1.b0 49 | g.cluster0.a1 << g.cluster1.b3 50 | g.cluster1.b2 << g.cluster0.a3 51 | g.cluster0.a3 << g.cluster0.a0 52 | g.cluster0.a3 << g.endn 53 | g.cluster1.b3 << g.endn 54 | 55 | g.output( :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /man/ruby2gv.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" https://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "RUBY2GV" "1" "April 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBruby2gv\fR \- create a dependency graph from a ruby script 8 | . 9 | .SH "SYNOPSIS" 10 | \fBruby2gv\fR [\fB\-T\fR\fIformat\fR] [\fB\-o\fR\fIfile\fR] [\fB\-h\fR] [\fB\-V\fR] \fIscript\fR 11 | . 12 | .SH "DESCRIPTION" 13 | \fBruby2gv\fR is a simple tool that allows you to create a dependency graph from a ruby script\. 14 | . 15 | .P 16 | See for more details\. 17 | . 18 | .SH "OPTIONS" 19 | . 20 | .TP 21 | \fB\-T\fR, \fB\-\-output\-format\fR [\fIformat\fR] 22 | Output format (default: png) 23 | . 24 | .TP 25 | \fB\-o\fR, \fB\-\-output\-file\fR [\fIfile\fR] 26 | Path to output image file (default: STDOUT) 27 | . 28 | .TP 29 | \fB\-p\fR, \fB\-\-path\fR 30 | Graphviz path 31 | . 32 | .TP 33 | \fB\-u\fR, \fB\-\-use\fR [\fIPROGRAM\fR] 34 | Program to use (default: dot) 35 | . 36 | .TP 37 | \fB\-s\fR, \fB\-\-stop\fR \fILIB\fR[,\fILIB\fR[, \.\.\.]] 38 | Stop on libs 39 | . 40 | .TP 41 | \fB\-V\fR, \fB\-\-version\fR 42 | Show version 43 | . 44 | .TP 45 | \fB\-h\fR, \fB\-\-help\fR 46 | Show this usage message 47 | . 48 | .SH "EXAMPLE" 49 | . 50 | .nf 51 | 52 | ruby2gv \-Tpng \-oruby2gv\.png /usr/bin/ruby2gv 53 | . 54 | .fi 55 | . 56 | .SH "AUTHOR" 57 | Copyright 2004\-2013 Gregoire Lejeune 58 | . 59 | .P 60 | This manual page is written by Praveen Arimbrathodiyl \fIpraveen@debian\.org\fR for Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd)\. 61 | -------------------------------------------------------------------------------- /examples/sample48.rb: -------------------------------------------------------------------------------- 1 | # http://www.graphviz.org/Gallery/directed/cluster.html 2 | # 3 | # digraph G { 4 | # 5 | # subgraph cluster_0 { 6 | # style=filled; 7 | # color=lightgrey; 8 | # node [style=filled,color=white]; 9 | # a0 -> a1 -> a2 -> a3; 10 | # label = "process #1"; 11 | # } 12 | # 13 | # subgraph cluster_1 { 14 | # node [style=filled]; 15 | # b0 -> b1 -> b2 -> b3; 16 | # label = "process #2"; 17 | # color=blue 18 | # } 19 | # start -> a0; 20 | # start -> b0; 21 | # a1 -> b3; 22 | # b2 -> a3; 23 | # a3 -> a0; 24 | # a3 -> end; 25 | # b3 -> end; 26 | # 27 | # start [shape=Mdiamond]; 28 | # end [shape=Msquare]; 29 | # } 30 | 31 | $:.unshift( "../lib" ); 32 | require "graphviz" 33 | 34 | GraphViz.new( :G, :type => :digraph ) { |g| 35 | g.cluster_0 { |c| 36 | c[:style] = :filled 37 | c[:color] = :lightgrey 38 | c.node[:style] = :filled 39 | c.node[:color] = :white 40 | c.a0 << c.a1 << c.a2 << c.a3 41 | c[:label] = "process #1" 42 | } 43 | 44 | g.cluster_1 { |c| 45 | c.node[:style] = :filled 46 | c.b0 << c.b1 << c.b2 << c.b3 47 | c[:label] = "process #1" 48 | c[:color] = :blue 49 | } 50 | 51 | g.start << g.cluster_0.a0 52 | g.start << g.cluster_1.b0 53 | g.cluster_0.a1 << g.cluster_1.b3 54 | g.cluster_1.b2 << g.cluster_0.a3 55 | g.cluster_0.a3 << g.cluster_0.a0 56 | g.cluster_0.a3 << g._end 57 | g.cluster_1.b3 << g._end 58 | 59 | g.start[:shape] = :Mdiamond 60 | g._end[:label] = "end" 61 | g._end[:shape] = :Mdiamond 62 | }.output( :png => "#{$0}.png" ) 63 | -------------------------------------------------------------------------------- /examples/theory/pert.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../../lib" ) 2 | require 'graphviz' 3 | require 'graphviz/theory' 4 | 5 | g = GraphViz.digraph( "G", :path => "/usr/local/bin", :use => "fdp" ) do |g| 6 | g.node[:shape => "record"] 7 | 8 | g.start[:label => "Start"] 9 | g.task_1[:label => "Task #1 - Duration : 4d"] 10 | g.task_2[:label => "Task #2 - Duration : 5.25d"] 11 | g.task_3[:label => "Task #3 - Duration : 5.17d"] 12 | g.task_4[:label => "Task #4 - Duration : 6.33d"] 13 | g.task_5[:label => "Task #5 - Duration : 5.17d"] 14 | g.task_6[:label => "Task #6 - Duration : 4.5d"] 15 | g.task_7[:label => "Task #7 - Duration : 5.17d"] 16 | g.finish[:label => "End"] 17 | 18 | (g.start << g.task_1)[:weight => 0.0] 19 | (g.start << g.task_2)[:weight => 0.0] 20 | (g.task_1 << g.task_3)[:weight => 4.0] 21 | (g.task_1 << g.task_4)[:weight => 4.0] 22 | (g.task_2 << g.task_5)[:weight => 5.25] 23 | (g.task_3 << g.task_5)[:weight => 5.17] 24 | (g.task_4 << g.task_6)[:weight => 6.33] 25 | (g.task_5 << g.task_7)[:weight => 5.17] 26 | (g.task_6 << g.finish)[:weight => 4.5] 27 | (g.task_7 << g.finish)[:weight => 5.17] 28 | end 29 | g.output( :png => "PERT.png" ) 30 | 31 | t = GraphViz::Theory.new( g ) 32 | 33 | print "Ranges : " 34 | rr = t.range 35 | p rr 36 | puts "Your graph contains circuits" if rr.include?(nil) 37 | 38 | puts "Critical path : " 39 | rrr = t.critical_path 40 | print "\tPath :" 41 | _ = "" 42 | rrr[:path].each do |i| 43 | print _ + g.get_node_at_index(i-1).id 44 | _ = " -> " 45 | end 46 | puts 47 | puts "\tDistance : #{rrr[:distance]}" -------------------------------------------------------------------------------- /examples/sample13.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G" ) { |graph| 7 | graph.node[:shape] = "ellipse" 8 | graph.node[:color] = "black" 9 | 10 | graph[:color] = "black" 11 | 12 | graph.cluster0( ) do |cluster| 13 | cluster[:label] = "process #1" 14 | cluster[:style] = "filled" 15 | cluster[:color] = "lightgrey" 16 | 17 | cluster.a0 :style => "filled", :color => "white" 18 | cluster.a1 :style => "filled", :color => "white" 19 | cluster.a2 :style => "filled", :color => "white" 20 | cluster.a3 :style => "filled", :color => "white" 21 | 22 | cluster.a0 << cluster.a1 23 | cluster.a1 << cluster.a2 24 | cluster.a2 << cluster.a3 25 | end 26 | 27 | graph.cluster1( :label => "process #2" ) do |cluster| 28 | cluster.b0 :style => "filled", :color => "blue" 29 | cluster.b1 :style => "filled", :color => "blue" 30 | cluster.b2 :style => "filled", :color => "blue" 31 | cluster.b3 :style => "filled", :color => "blue" 32 | 33 | cluster.b0 << cluster.b1 34 | cluster.b1 << cluster.b2 35 | cluster.b2 << cluster.b3 36 | end 37 | 38 | graph.start :shape => "Mdiamond" 39 | graph.endn :shape => "Msquare", :label => "end" 40 | 41 | graph.start << graph.cluster0.a0 42 | graph.start << graph.cluster1.b0 43 | graph.cluster0.a1 << graph.cluster1.b3 44 | graph.cluster1.b2 << graph.cluster0.a3 45 | graph.cluster0.a3 << graph.cluster0.a0 46 | graph.cluster0.a3 << graph.endn 47 | graph.cluster1.b3 << graph.endn 48 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /examples/sample09.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node["shape"] = "ellipse" 14 | g.node["color"] = "black" 15 | 16 | g["color"] = "black" 17 | 18 | c0 = g.add_graph( "cluster0" ) 19 | c0["label"] = "process #1" 20 | c0["style"] = "filled" 21 | c0["color"] = "lightgrey" 22 | a0 = c0.add_nodes( "a0", "style" => "filled", "color" => "white" ) 23 | a1 = c0.add_nodes( "a1", "style" => "filled", "color" => "white" ) 24 | a2 = c0.add_nodes( "a2", "style" => "filled", "color" => "white" ) 25 | a3 = c0.add_nodes( "a3", "style" => "filled", "color" => "white" ) 26 | c0.add_edges( a0, a1 ) 27 | c0.add_edges( a1, a2 ) 28 | c0.add_edges( a2, a3 ) 29 | 30 | c1 = g.add_graph( "cluster1", "label" => "process #2" ) 31 | b0 = c1.add_nodes( "b0", "style" => "filled", "color" => "blue" ) 32 | b1 = c1.add_nodes( "b1", "style" => "filled", "color" => "blue" ) 33 | b2 = c1.add_nodes( "b2", "style" => "filled", "color" => "blue" ) 34 | b3 = c1.add_nodes( "b3", "style" => "filled", "color" => "blue" ) 35 | c1.add_edges( b0, b1 ) 36 | c1.add_edges( b1, b2 ) 37 | c1.add_edges( b2, b3 ) 38 | 39 | start = g.add_nodes( "start", "shape" => "Mdiamond" ) 40 | endn = g.add_nodes( "end", "shape" => "Msquare" ) 41 | 42 | g.add_edges( start, a0 ) 43 | g.add_edges( start, b0 ) 44 | g.add_edges( a1, b3 ) 45 | g.add_edges( b2, a3 ) 46 | g.add_edges( a3, a0 ) 47 | g.add_edges( a3, endn ) 48 | g.add_edges( b3, endn ) 49 | 50 | g.output( :png => "#{$0}.png" ) 51 | -------------------------------------------------------------------------------- /examples/sample10.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g.node["shape"] = "ellipse" 14 | g.node["color"] = "black" 15 | 16 | g["color"] = "black" 17 | 18 | c0 = g.add_graph( "cluster0" ) 19 | c0["label"] = "process #1" 20 | c0["style"] = "filled" 21 | c0["color"] = "lightgrey" 22 | a0 = c0.add_nodes( "a0", "style" => "filled", "color" => "white" ) 23 | a1 = c0.add_nodes( "a1", "style" => "filled", "color" => "white" ) 24 | a2 = c0.add_nodes( "a2", "style" => "filled", "color" => "white" ) 25 | a3 = c0.add_nodes( "a3", "style" => "filled", "color" => "white" ) 26 | c0.add_edges( a0, a1 ) 27 | c0.add_edges( a1, a2 ) 28 | c0.add_edges( a2, a3 ) 29 | 30 | c1 = g.add_graph( "cluster1", "label" => "process #2" ) 31 | b0 = c1.add_nodes( "b0", "style" => "filled", "color" => "blue" ) 32 | b1 = c1.add_nodes( "b1", "style" => "filled", "color" => "blue" ) 33 | b2 = c1.add_nodes( "b2", "style" => "filled", "color" => "blue" ) 34 | b3 = c1.add_nodes( "b3", "style" => "filled", "color" => "blue" ) 35 | c1.add_edges( b0, b1 ) 36 | c1.add_edges( b1, b2 ) 37 | c1.add_edges( b2, b3 ) 38 | 39 | start = g.add_nodes( "start", "shape" => "Mdiamond" ) 40 | endn = g.add_nodes( "end", "shape" => "Msquare" ) 41 | 42 | g.add_edges( start, a0 ) 43 | g.add_edges( start, b0 ) 44 | g.add_edges( a1, b3 ) 45 | g.add_edges( b2, a3 ) 46 | g.add_edges( a3, a0 ) 47 | g.add_edges( a3, endn ) 48 | g.add_edges( b3, endn ) 49 | 50 | g.output( :png => "#{$0}.png" ) 51 | -------------------------------------------------------------------------------- /examples/sample19.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "ER", :type => "graph", :use => "neato" ) { |graph| 7 | graph.node[:shape] = "box" 8 | graph.course; graph.institute; graph.student 9 | 10 | graph.node[:shape] = "ellipse" 11 | graph.name0(:label => "name") 12 | graph.name1(:label => "name") 13 | graph.name2(:label => "name") 14 | graph.code; graph.grade; graph.number 15 | 16 | graph.node[:shape] = "diamond" 17 | graph.node[:style] = "filled" 18 | graph.node[:color] = "lightgrey" 19 | graph.ci( :label => "C-I" ) 20 | graph.sc( :label => "S-C" ) 21 | graph.si( :label => "S-I" ) 22 | 23 | graph.name0 << graph.course; 24 | graph.code << graph.course; 25 | 26 | (graph.course << graph.ci).set { |e| 27 | e.label = "n" 28 | e.len = "1.00" 29 | } 30 | 31 | e = (graph.ci << graph.institute) 32 | e.label = "1" 33 | e[:len] = "1.00" 34 | 35 | graph.institute << graph.name1; 36 | 37 | e = (graph.institute << graph.si) 38 | e[:label] = "1" 39 | e[:len] = "1.00" 40 | 41 | e = (graph.si << graph.student) 42 | e[:label] = "n" 43 | e[:len] = "1.00" 44 | 45 | graph.student << graph.grade 46 | graph.student << graph.name2 47 | graph.student << graph.number 48 | 49 | e = (graph.student << graph.sc) 50 | e[:label] = "m" 51 | e[:len] = "1.00" 52 | 53 | e = (graph.sc << graph.course) 54 | e[:label] = "n" 55 | e[:len] = "1.00" 56 | 57 | graph[:label] = "\\n\\nEntity Relation Diagram\\ndrawn by NEATO"; 58 | graph[:fontsize] = "20"; 59 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | $:.unshift( "lib" ) 2 | require "graphviz/constants" 3 | 4 | require 'rubygems' 5 | require 'rake/clean' 6 | require 'bundler' 7 | require 'rubygems/package_task' 8 | require 'rake/testtask' 9 | require 'fileutils' 10 | require 'open-uri' 11 | require 'yard' 12 | include FileUtils 13 | 14 | CLEAN.include ['**/.*.sw?', '*.gem', '.config', 'test/test.log'] 15 | 16 | desc "Packages up Ruby/GraphViz." 17 | task :default => [:test, :package] 18 | task :package => [:clean] 19 | 20 | task :doc => :yard 21 | 22 | YARD::Rake::YardocTask.new do |t| 23 | end 24 | 25 | Rake::TestTask.new(:test) do |t| 26 | t.libs << 'lib' << 'test' 27 | t.verbose = true 28 | 29 | require 'graphviz/utils' 30 | include GraphViz::Utils 31 | test_files = FileList['test/test_*.rb'] 32 | test_files.exclude("test/test_examples.rb") unless find_executable("dot", nil) 33 | 34 | p test_files 35 | t.test_files = test_files 36 | end 37 | 38 | desc "Generate man pages" 39 | task :man do 40 | unless RUBY_PLATFORM == 'java' 41 | require 'ronn' 42 | chdir 'man' do 43 | sh "ronn -r *.ronn" 44 | end 45 | else 46 | puts "Can't generate man pages with JRuby" 47 | end 48 | end 49 | 50 | namespace :changelog do 51 | desc "Update CHANGELOG" 52 | task :update do 53 | require "github_changelog_generator" 54 | GitHubChangelogGenerator::ChangelogGenerator.new.run 55 | end 56 | end 57 | 58 | Bundler::GemHelper.install_tasks 59 | 60 | namespace :contributors do 61 | desc "Install all-contributors-cli" 62 | task :install do 63 | sh "npm install --save-dev all-contributors-cli" 64 | end 65 | 66 | desc "Run" 67 | task :run do 68 | sh "npx all-contributors" 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /examples/sample44.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | g = nil 7 | if ARGV[0] 8 | g = GraphViz::new( "G", "path" => ARGV[0] ) 9 | else 10 | g = GraphViz::new( "G" ) 11 | end 12 | 13 | g["rankdir"] = "LR" 14 | g.node["shape"] = "ellipse" 15 | g.edge["arrowhead"] = "normal" 16 | 17 | [ 18 | "box", 19 | "boxbox", 20 | "lbox", 21 | "lboxlbox", 22 | "rbox", 23 | "rboxrbox", 24 | "olbox", 25 | "olboxolbox", 26 | "orbox", 27 | "orboxorbox", 28 | "obox", 29 | "oboxobox", 30 | "crow", 31 | "crowcrow", 32 | "lcrow", 33 | "lcrowlcrow", 34 | "rcrow", 35 | "rcrowrcrow", 36 | "diamond", 37 | "diamonddiamond", 38 | "ldiamond", 39 | "ldiamondldiamond", 40 | "rdiamond", 41 | "rdiamondrdiamond", 42 | "oldiamond", 43 | "oldiamondoldiamond", 44 | "ordiamond", 45 | "ordiamondordiamond", 46 | "odiamond", 47 | "odiamondodiamond", 48 | "dot", 49 | "dotdot", 50 | "odot", 51 | "odotodot", 52 | "inv", 53 | "invinv", 54 | "linv", 55 | "linvlinv", 56 | "rinv", 57 | "rinvrinv", 58 | "olinv", 59 | "olinvolinv", 60 | "orinv", 61 | "orinvorinv", 62 | "oinv", 63 | "oinvoinv", 64 | "none", 65 | "nonenone", 66 | "normal", 67 | "normalnormal", 68 | "lnormal", 69 | "lnormallnormal", 70 | "rnormal", 71 | "rnormalrnormal", 72 | "olnormal", 73 | "olnormalolnormal", 74 | "ornormal", 75 | "ornormalornormal", 76 | "onormal", 77 | "onormalonormal", 78 | "tee", 79 | "teetee", 80 | "ltee", 81 | "lteeltee", 82 | "rtee", 83 | "rteertee", 84 | "vee", 85 | "veevee", 86 | "lvee", 87 | "lveelvee", 88 | "rvee", 89 | "rveervee" 90 | ].each { |s| 91 | p = String.new("p_") << s 92 | g.add_nodes( p, "shape" => "point" ) 93 | g.add_nodes( s ) 94 | g.add_edges( p, s, "arrowhead" => s ) 95 | } 96 | 97 | g.output( :png => "#{$0}.png" ) 98 | -------------------------------------------------------------------------------- /man/dot2ruby.1.ronn: -------------------------------------------------------------------------------- 1 | dot2ruby(1) - create a ruby script from a graphviz script 2 | ========================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `dot2ruby` [`-o`] [`-T`] [`-h`] [`-V`] _script_ 7 | 8 | ## DESCRIPTION 9 | 10 | **dot2ruby** is a tool that allows you to create a ruby script from 11 | a graphviz script. 12 | 13 | See for more details. 14 | 15 | ## OPTIONS 16 | 17 | * `-o`, `--output-file` []: 18 | Path to output image file (default STDOUT) 19 | 20 | * `-T`, `--output-format` []: 21 | Output format (default: png) 22 | 23 | * `-p`, `--path`: 24 | Graphviz path 25 | 26 | * `-V`, `--version`: 27 | Show version 28 | 29 | * `-h`, `--help`: 30 | Show this usage message 31 | 32 | ## EXAMPLE 33 | 34 | $ cat hello.dot 35 | digraph G {Hello->World;} 36 | 37 | $ dot2ruby hello.dot 38 | # This code was generated by dot2ruby.g 39 | 40 | require 'rubygems' 41 | require 'graphviz' 42 | graph_g = GraphViz.digraph( "G" ) { |graph_g| 43 | graph_g[:bb] = '0,0,70,108' 44 | node_hello = graph_g.add_nodes( "Hello", :height => '0.5', :label => '\N', :pos => '35,90', :width => '0.88889' ) 45 | graph_g.add_edges( "Hello", "World", :pos => 'e,35,36.413 35,71.831 35,64.131 35,54.974 35,46.417' ) 46 | node_world = graph_g.add_nodes( "World", :height => '0.5', :label => '\N', :pos => '35,18', :width => '0.97222' ) 47 | } 48 | puts graph_g.output( :canon => String ) 49 | 50 | ## AUTHOR 51 | 52 | Copyright 2004-2018 Gregoire Lejeune 53 | 54 | This manual page is written by Praveen Arimbrathodiyl for 55 | Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd). 56 | -------------------------------------------------------------------------------- /test/test_utils_colors.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class TypesTest < Test::Unit::TestCase 4 | def setup 5 | @brown_txt = GraphViz::Utils::Colors.name("brown") 6 | @brown_hsv = GraphViz::Utils::Colors.hsv(0.0, 0.745454545454545, 0.647058823529412) 7 | @brown_rgb = GraphViz::Utils::Colors.rgb("a5", "2a", "2a") 8 | end 9 | 10 | def test_color 11 | assert @brown_txt 12 | assert @brown_hsv 13 | assert @brown_rgb 14 | end 15 | 16 | def test_color_by_name 17 | assert_equal "brown", @brown_txt.name 18 | assert_equal "brown", @brown_hsv.name 19 | assert_equal "brown", @brown_rgb.name 20 | end 21 | 22 | def test_color_by_rgb 23 | assert_equal "a5", @brown_txt.r 24 | assert_equal "2a", @brown_txt.g 25 | assert_equal "2a", @brown_txt.b 26 | assert_equal "#a52a2a", @brown_txt.rgba_string("#") 27 | 28 | assert_equal "a5", @brown_hsv.r 29 | assert_equal "2a", @brown_hsv.g 30 | assert_equal "2a", @brown_hsv.b 31 | assert_equal "#a52a2a", @brown_hsv.rgba_string("#") 32 | 33 | assert_equal "a5", @brown_rgb.r 34 | assert_equal "2a", @brown_rgb.g 35 | assert_equal "2a", @brown_rgb.b 36 | assert_equal "#a52a2a", @brown_rgb.rgba_string("#") 37 | end 38 | 39 | def test_color_by_hsv 40 | assert_equal @brown_rgb.h, @brown_txt.h 41 | assert_equal @brown_rgb.s, @brown_txt.s 42 | assert_equal @brown_rgb.v, @brown_txt.v 43 | 44 | assert_equal @brown_rgb.hsv_string, @brown_txt.hsv_string 45 | 46 | assert_equal 0.0.to_s, @brown_hsv.h.to_s 47 | assert_equal 0.745454545454545.to_s, @brown_hsv.s.to_s 48 | assert_equal 0.647058823529412.to_s, @brown_hsv.v.to_s 49 | 50 | assert_equal "0.0, 0.745454545454545, 0.647058823529412", @brown_hsv.hsv_string 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/graphviz/core_ext.rb: -------------------------------------------------------------------------------- 1 | class String 2 | def self.random(size) 3 | s = String.new 4 | d = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a 5 | size.times { 6 | s << d[rand(d.size)] 7 | } 8 | return s 9 | end 10 | 11 | def convert_base(from, to) 12 | self.to_i(from).to_s(to) 13 | end 14 | end 15 | 16 | class Object 17 | def to_ruby 18 | begin 19 | eval self 20 | rescue 21 | self 22 | end 23 | end 24 | end 25 | 26 | # From : http://www.geekmade.co.uk/2008/09/ruby-tip-normalizing-hash-keys-as-symbols/ 27 | class Hash 28 | def symbolize_keys 29 | inject({}) do |options, (key, value)| 30 | options[(key.to_sym rescue key) || key] = value 31 | options 32 | end 33 | end 34 | 35 | # x = { 36 | # :none => String, 37 | # :png => "file.png", 38 | # :svg => "file.svg" 39 | # } 40 | # 41 | # x.each_except( :key => [:none], :value => [/\.png$/] ) do |k, v| 42 | # puts "#{k} -> #{v}" 43 | # end 44 | # 45 | # => svg -> file.svg 46 | def each_except( e, &b ) 47 | key_table = (e[:key]||[]).clone.delete_if {|i| i.kind_of? Regexp } 48 | key_regexp = (e[:key]||[]).clone.delete_if {|i| key_table.include? i }.map {|i| i.to_s }.join("|") 49 | 50 | value_table = (e[:value]||[]).clone.delete_if {|i| i.kind_of? Regexp } 51 | value_regexp = (e[:value]||[]).clone.delete_if {|i| value_table.include? i }.map {|i| i.to_s }.join("|") 52 | 53 | self.each do |k, v| 54 | yield( k, v ) unless (key_table.size > 0 and key_table.include?(k)) or (key_regexp.size > 0 and k.to_s.match(key_regexp)) or (value_table.size > 0 and value_table.include?(v)) or (value_regexp.size > 0 and v.to_s.match(value_regexp)) 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/graphviz/family_tree/couple.rb: -------------------------------------------------------------------------------- 1 | class GraphViz 2 | class FamilyTree 3 | class Couple 4 | def initialize( graph, node, persons ) #:nodoc: 5 | @graph = graph 6 | @node = node 7 | @kids = [] 8 | @persons = persons 9 | end 10 | 11 | def node #:nodoc: 12 | @node 13 | end 14 | 15 | # Add kids to a couple 16 | def kids( *z ) 17 | @kids = GraphViz::FamilyTree::Sibling.new( z, @persons ) 18 | 19 | return 20 | 21 | if z.size == 1 22 | @graph.add_edges( @node, z[0].node, "dir" => "none" ) 23 | else 24 | cluster = @graph.add_graph( "#{@node.id}Kids" ) 25 | cluster["rank"] = "same" 26 | 27 | last = nil 28 | count = 0 29 | add = (z.size-1)%2 * z.size/2 + (z.size-1)%2 30 | link = (z.size/2)+1 31 | 32 | z.each do |person| 33 | count = count + 1 34 | if count == add 35 | middle = cluster.add_nodes( "#{@node.id}Kids", "shape" => "point" ) 36 | @graph.add_edges( @node, middle, "dir" => "none" ) 37 | unless last.nil? 38 | cluster.add_edges( last, middle, "dir" => "none" ) 39 | end 40 | last = middle 41 | end 42 | 43 | kid = cluster.add_nodes( "#{person.node.id}Kid", "shape" => "point" ) 44 | @graph.add_edges( kid, person.node, "dir" => "none" ) 45 | 46 | if add == 0 and count == link 47 | @graph.add_edges( @node, kid, "dir" => "none" ) 48 | end 49 | 50 | unless last.nil? 51 | cluster.add_edges( last, kid, "dir" => "none" ) 52 | end 53 | last = kid 54 | end 55 | end 56 | end 57 | 58 | def getKids 59 | @kids 60 | end 61 | end 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /test/test_types.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class TypesTest < Test::Unit::TestCase 4 | def test_gv_bool 5 | bool = nil 6 | 7 | assert_block "Create true GvBool failed." do 8 | bool = GraphViz::Types::GvBool.new(true) 9 | end 10 | assert bool 11 | assert_equal true, bool.to_ruby 12 | 13 | assert_block "Create \"true\" GvBool failed." do 14 | bool = GraphViz::Types::GvBool.new("true") 15 | end 16 | assert bool 17 | assert_equal true, bool.to_ruby 18 | 19 | assert_block "Create \"Yes\" GvBool failed." do 20 | bool = GraphViz::Types::GvBool.new("Yes") 21 | end 22 | assert bool 23 | assert_equal true, bool.to_ruby 24 | 25 | assert_block "Create 1 GvBool failed." do 26 | bool = GraphViz::Types::GvBool.new(1) 27 | end 28 | assert bool 29 | assert_equal true, bool.to_ruby 30 | 31 | assert_block "Create false GvBool failed." do 32 | bool = GraphViz::Types::GvBool.new(false) 33 | end 34 | assert bool 35 | assert_equal false, bool.to_ruby 36 | 37 | assert_block "Create \"false\" GvBool failed." do 38 | bool = GraphViz::Types::GvBool.new("false") 39 | end 40 | assert bool 41 | assert_equal false, bool.to_ruby 42 | 43 | assert_block "Create \"NO\" GvBool failed." do 44 | bool = GraphViz::Types::GvBool.new("NO") 45 | end 46 | assert bool 47 | assert_equal false, bool.to_ruby 48 | 49 | assert_block "Create 0 GvBool failed." do 50 | bool = GraphViz::Types::GvBool.new(0) 51 | end 52 | assert bool 53 | assert_equal false, bool.to_ruby 54 | 55 | assert_raise BoolException, "Wrong bool value" do 56 | GraphViz::Types::GvBool.new(:toto) 57 | end 58 | 59 | assert_block "Create GvBool with empty string failed." do 60 | bool = GraphViz::Types::GvBool.new("") 61 | end 62 | assert bool 63 | assert_equal false, bool.to_ruby 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /examples/sample20.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::options( :use => "dot" ) 7 | 8 | if ARGV[0] 9 | GraphViz::options( :path => ARGV[0] ) 10 | end 11 | 12 | GraphViz::new( "g", :rankdir => "LR", :type => "digraph" ) { |g| 13 | g.node[:fontsize] = "16" 14 | g.node[:shape] = "record" 15 | 16 | g.node0( :label => " 0x10ba8| " ) 17 | g.node1( :label => " 0xf7fc4380| | |-1" ) 18 | g.node2( :label => " 0xf7fc44b8| | |2" ) 19 | g.node3( :label => " 3.43322790286038071e-06|44.79998779296875|0" ) 20 | g.node4( :label => " 0xf7fc4380| | |2" ) 21 | g.node5( :label => " (nil)| | |-1" ) 22 | g.node6( :label => " 0xf7fc4380| | |1" ) 23 | g.node7( :label => " 0xf7fc4380| | |2" ) 24 | g.node8( :label => " (nil)| | |-1" ) 25 | g.node9( :label => " (nil)| | |-1" ) 26 | g.node10( :label => " (nil)| | |-1" ) 27 | g.node11( :label => " (nil)| | |-1" ) 28 | g.node12( :label => " 0xf7fc43e0| | |1" ) 29 | 30 | g.add_edges( g.node0(:f0), g.node1(:f0) ) 31 | g.add_edges( g.node0(:f1), g.node2(:f0) ) 32 | g.add_edges( g.node1(:f0), g.node3(:f0) ) 33 | g.add_edges( g.node1(:f1), g.node4(:f0) ) 34 | g.add_edges( g.node1(:f2), g.node5(:f0) ) 35 | g.add_edges( g.node4(:f0), g.node3(:f0) ) 36 | g.add_edges( g.node4(:f1), g.node6(:f0) ) 37 | g.add_edges( g.node4(:f2), g.node10(:f0) ) 38 | g.add_edges( g.node6(:f0), g.node3(:f0) ) 39 | g.add_edges( g.node6(:f1), g.node7(:f0) ) 40 | g.add_edges( g.node6(:f2), g.node9(:f0) ) 41 | g.add_edges( g.node7(:f0), g.node3(:f0) ) 42 | g.add_edges( g.node7(:f1), g.node1(:f0) ) 43 | g.add_edges( g.node7(:f2), g.node8(:f0) ) 44 | g.add_edges( g.node10(:f1), g.node11(:f0) ) 45 | g.add_edges( g.node10(:f2), g.node12(:f0) ) 46 | g.add_edges( g.node11(:f2), g.node1(:f0) ) 47 | }.output( :png => "#{$0}.png" ) 48 | -------------------------------------------------------------------------------- /ruby-graphviz.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | 4 | require "graphviz/constants" 5 | 6 | Gem::Specification.new do |s| 7 | s.name = "ruby-graphviz" 8 | s.version = GraphViz::Constants::RGV_VERSION 9 | s.platform = Gem::Platform::RUBY 10 | s.license = "GPL-2.0" 11 | 12 | s.authors = ["Gregoire Lejeune"] 13 | s.summary = "Interface to the GraphViz graphing tool" 14 | s.email = "gregoire.lejeune@free.fr" 15 | s.homepage = "https://github.com/glejeune/Ruby-Graphviz" 16 | s.description = "Ruby/Graphviz provides an interface to layout and generate images of directed graphs in a variety of formats (PostScript, PNG, etc.) using GraphViz." 17 | 18 | s.files = `git ls-files`.split("\n") 19 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 20 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 21 | s.require_paths = ["lib"] 22 | 23 | s.extra_rdoc_files = ["README.md", "COPYING.md", "CHANGELOG.md"] 24 | s.rdoc_options = ["--title", "Ruby/GraphViz", "--main", "README.md"] 25 | s.post_install_message = %{ 26 | You need to install GraphViz (https://graphviz.org) to use this Gem. 27 | 28 | For more information about Ruby-Graphviz : 29 | * Doc: https://rdoc.info/github/glejeune/Ruby-Graphviz 30 | * Sources: https://github.com/glejeune/Ruby-Graphviz 31 | * Issues: https://github.com/glejeune/Ruby-Graphviz/issues 32 | } 33 | 34 | s.add_dependency "rexml" 35 | 36 | s.add_development_dependency 'rake' 37 | s.add_development_dependency 'rdoc' 38 | s.add_development_dependency 'yard' 39 | s.add_development_dependency 'github_changelog_generator' 40 | s.add_development_dependency 'bundler' 41 | s.add_development_dependency 'ronn' unless RUBY_PLATFORM == 'java' 42 | s.add_development_dependency 'test-unit' 43 | 44 | s.required_ruby_version = '>= 2.4.0' 45 | 46 | s.requirements << 'GraphViz' 47 | end 48 | -------------------------------------------------------------------------------- /examples/sample99.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ); 2 | require 'graphviz/family_tree' 3 | 4 | tree = GraphViz::FamilyTree.new do 5 | generation do 6 | chantale.is_a_woman( "Chantale" ) 7 | jacques.is_a_man( "Jacques" ) 8 | 9 | jacques.is_dead 10 | jacques.is_maried_with chantale 11 | 12 | rose.is_a_woman( "Rose Marie" ) 13 | andre.is_a_man( "Andre" ) 14 | 15 | andre.is_maried_with rose 16 | andre.is_dead 17 | end 18 | 19 | generation do 20 | benoist.is_a_man( "Benoist" ) 21 | nathalie.is_a_woman( "Nathalie" ) 22 | 23 | benoist.is_maried_with nathalie 24 | 25 | michel.is_a_man( "Michel" ) 26 | brigitte.is_a_woman( "Brigitte" ) 27 | 28 | michel.is_maried_with brigitte 29 | end 30 | 31 | couple( chantale, jacques ).kids( nathalie ) 32 | couple( rose, andre ).kids( benoist ) 33 | 34 | generation do 35 | charlotte.is_a_woman( "Charlotte" ) 36 | amelie.is_a_woman( "Amelie" ) 37 | clement.is_a_man( "Clement" ) 38 | gregoire.is_a_man( "Gregoire" ) 39 | 40 | muriel.is_a_woman( "Muriel" ) 41 | gilles.is_a_man( "Gilles" ) 42 | 43 | morgane.is_a_woman( "Morgane" ) 44 | gregoire.is_divorced_with morgane 45 | 46 | pascal.is_a_man( "Pascal" ) 47 | muriel.is_divorced_with pascal 48 | 49 | gregoire.is_maried_with muriel 50 | end 51 | 52 | couple( michel, brigitte ).kids( muriel, gilles ) 53 | couple( benoist, nathalie ).kids( charlotte, amelie, clement, gregoire ) 54 | 55 | generation do 56 | arthur.is_a_boy( "Arthur" ) 57 | colyne.is_a_girl( "Colyne" ) 58 | benedict.is_a_boy( "Benedict" ) 59 | maia.is_a_girl( "Maia" ) 60 | enaitz.is_a_boy( "Enaitz" ) 61 | milo.is_a_boy( "Milo" ) 62 | end 63 | 64 | couple( gregoire, morgane ).kids( arthur, colyne, benedict ) 65 | couple( gregoire, muriel ).kids( maia ) 66 | couple( muriel, pascal ).kids( milo ) 67 | muriel.kids( enaitz ) 68 | end 69 | 70 | tree.graph.save( :png => "#{$0}.png" ) 71 | -------------------------------------------------------------------------------- /man/dot2ruby.1: -------------------------------------------------------------------------------- 1 | .\" generated with Ronn/v0.7.3 2 | .\" https://github.com/rtomayko/ronn/tree/0.7.3 3 | . 4 | .TH "DOT2RUBY" "1" "April 2013" "" "" 5 | . 6 | .SH "NAME" 7 | \fBdot2ruby\fR \- create a ruby script from a graphviz script 8 | . 9 | .SH "SYNOPSIS" 10 | \fBdot2ruby\fR [\fB\-o\fR\fIfile\fR] [\fB\-T\fR\fIformat\fR] [\fB\-h\fR] [\fB\-V\fR] \fIscript\fR 11 | . 12 | .SH "DESCRIPTION" 13 | \fBdot2ruby\fR is a tool that allows you to create a ruby script from a graphviz script\. 14 | . 15 | .P 16 | See for more details\. 17 | . 18 | .SH "OPTIONS" 19 | . 20 | .TP 21 | \fB\-o\fR, \fB\-\-output\-file\fR [\fIfile\fR] 22 | Path to output image file (default STDOUT) 23 | . 24 | .TP 25 | \fB\-T\fR, \fB\-\-output\-format\fR [\fIformat\fR] 26 | Output format (default: png) 27 | . 28 | .TP 29 | \fB\-p\fR, \fB\-\-path\fR 30 | Graphviz path 31 | . 32 | .TP 33 | \fB\-V\fR, \fB\-\-version\fR 34 | Show version 35 | . 36 | .TP 37 | \fB\-h\fR, \fB\-\-help\fR 38 | Show this usage message 39 | . 40 | .SH "EXAMPLE" 41 | . 42 | .nf 43 | 44 | $ cat hello\.dot 45 | digraph G {Hello\->World;} 46 | 47 | $ dot2ruby hello\.dot 48 | # This code was generated by dot2ruby\.g 49 | 50 | require \'rubygems\' 51 | require \'graphviz\' 52 | graph_g = GraphViz\.digraph( "G" ) { |graph_g| 53 | graph_g[:bb] = \'0,0,70,108\' 54 | node_hello = graph_g\.add_nodes( "Hello", :height => \'0\.5\', :label => \'\eN\', :pos => \'35,90\', :width => \'0\.88889\' ) 55 | graph_g\.add_edges( "Hello", "World", :pos => \'e,35,36\.413 35,71\.831 35,64\.131 35,54\.974 35,46\.417\' ) 56 | node_world = graph_g\.add_nodes( "World", :height => \'0\.5\', :label => \'\eN\', :pos => \'35,18\', :width => \'0\.97222\' ) 57 | } 58 | puts graph_g\.output( :canon => String ) 59 | . 60 | .fi 61 | . 62 | .SH "AUTHOR" 63 | Copyright 2004\-2013 Gregoire Lejeune 64 | . 65 | .P 66 | This manual page is written by Praveen Arimbrathodiyl \fIpraveen@debian\.org\fR for Debian GNU System (GNU/Linux, GNU/kFreeBSD, GNU/Hurd)\. 67 | -------------------------------------------------------------------------------- /lib/graphviz/types/color.rb: -------------------------------------------------------------------------------- 1 | require 'graphviz/utils/colors' 2 | 3 | class ColorException < RuntimeError 4 | end 5 | 6 | class GraphViz 7 | class Types 8 | class Color < Common 9 | HEX_FOR_COLOR = /[0-9a-fA-F]{2}/ 10 | RGBA = /^#(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})(#{HEX_FOR_COLOR})?$/ 11 | 12 | def check(data) 13 | data = data.to_s if data.is_a?(Symbol) 14 | return nil if data.empty? 15 | 16 | if data[0].chr == "#" 17 | m = RGBA.match(data) 18 | if m.nil? 19 | raise ColorException, "Wrong color definition RGBA #{data}" 20 | end 21 | @to_ruby = GraphViz::Utils::Colors.rgb(m[1], m[2], m[3], m[4]) 22 | return data 23 | elsif data.include?(",") or data.include?(" ") 24 | m = data.split(/(?:\s*,\s*|\s+)/).map { |x| x.to_f } 25 | if m.size != 3 26 | raise ColorException, "Wrong color definition HSV #{data}" 27 | end 28 | @to_ruby = GraphViz::Utils::Colors.hsv(m[0], m[1], m[2]) 29 | return data 30 | elsif data.is_a?(Array) 31 | if data.all? { |x| x.is_a?(String) and x =~ /^#{HEX_FOR_COLOR}$/ } and [3,4].include?(data.size) 32 | @to_ruby = GraphViz::Utils::Colors.rgb(data[0], data[1], data[2], data[3]) 33 | return data 34 | elsif data.all? { |x| x.kind_of?(Numeric) } and data.size == 3 35 | @to_ruby = GraphViz::Utils::Colors.hsv(data[0], data[1], data[2]) 36 | return data 37 | end 38 | 39 | raise ColorException, "Wrong color definition Array #{data}" 40 | else 41 | @to_ruby = GraphViz::Utils::Colors.name(data) 42 | return data 43 | end 44 | end 45 | 46 | def output 47 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 48 | end 49 | 50 | alias :to_gv :output 51 | alias :to_s :output 52 | 53 | def to_ruby 54 | @to_ruby 55 | end 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/graphviz/dsl.rb: -------------------------------------------------------------------------------- 1 | require 'graphviz' 2 | 3 | class GraphViz::DSL 4 | attr_accessor :graph 5 | 6 | # Create a new graph 7 | def initialize(name, options = {}, &block) 8 | @graph = GraphViz.new(name, options) 9 | instance_eval(&block) if block 10 | end 11 | 12 | def method_missing(sym, *args, &block) #:nodoc: 13 | return @graph.get_graph(sym.to_s) unless @graph.get_graph(sym.to_s).nil? 14 | return @graph.get_node(sym.to_s) unless @graph.get_node(sym.to_s).nil? 15 | if(@graph.respond_to?(sym, true)) 16 | @graph.send(sym, *args) 17 | elsif(block) 18 | @graph.add_graph(GraphViz::DSL.new(sym, { :parent => @graph, :type => @graph.type }, &block).graph) 19 | else 20 | @graph.add_nodes(sym.to_s, *args) 21 | end 22 | end 23 | 24 | # Add a new node 25 | def n(name) 26 | return @graph.get_node(name) unless @graph.get_node(name.to_s).nil? 27 | @graph.add_nodes(name) 28 | end 29 | 30 | # Create edges 31 | def e(*args) 32 | e = nil 33 | last = args.shift 34 | while current = args.shift 35 | e = @graph.add_edges(last, current) 36 | last = current 37 | end 38 | return e 39 | end 40 | 41 | # Add a subgraph 42 | def subgraph(name, &block) 43 | @graph.add_graph(GraphViz::DSL.new(name, { :parent => @graph, :type => @graph.type }, &block).graph) 44 | end 45 | alias :cluster :subgraph 46 | 47 | # Generate output 48 | def output(options = {}) 49 | @graph.output(options) 50 | end 51 | end 52 | 53 | # Create a new undirected graph 54 | def graph(name, options = {}, &block) 55 | GraphViz::DSL.new(name, options.merge( { :type => "graph" } ), &block).graph 56 | end 57 | 58 | # Create a new directed graph 59 | def digraph(name, options = {}, &block) 60 | GraphViz::DSL.new(name, options.merge( { :type => "digraph" } ), &block).graph 61 | end 62 | 63 | # Create a new strict directed graph 64 | def strict(name, options = {}, &block) 65 | GraphViz::DSL.new(name, options.merge( { :type => "strict digraph" } ), &block).graph 66 | end 67 | 68 | -------------------------------------------------------------------------------- /examples/sample37.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../lib" ) 2 | require "graphviz" 3 | 4 | # The goal is to set each planet to its own orbit + set some (earth+moon) to the same orbit 5 | 6 | g = GraphViz::new( "Solarsys", 7 | :type => "digraph", 8 | :use => "twopi" 9 | ) 10 | 11 | # the star 12 | sun = g.add_nodes( 13 | 'Sun', 14 | :shape => "circle", 15 | :penwidth => 2, 16 | :fontsize => 12, 17 | :style => :filled, 18 | :fillcolor => "orange", 19 | :label => "Sun\n" 20 | ) 21 | 22 | planets = Hash.new 23 | 24 | # The Earth and the Moon - in the same subgraph\rank 25 | g.subgraph { |c| 26 | c[:rank => 'same'] 27 | planets['Moon'] = c.add_nodes( 28 | 'Moon', 29 | :shape => "circle", 30 | :penwidth => 2, 31 | :fontsize => 12, 32 | :style => :filled, 33 | :fillcolor => "red", 34 | :label => "Moon\n" 35 | ) 36 | planets['Earth'] = c.add_nodes( 37 | 'Earth', 38 | :shape => "circle", 39 | :penwidth => 2, 40 | :fontsize => 12, 41 | :style => :filled, 42 | :fillcolor => "blue", 43 | :label => "Earth\n" 44 | ) 45 | c.add_edges( planets['Moon'], planets['Earth'], 46 | :penwidth => 2, 47 | :labeltooltip => "distance", 48 | :color => "black" 49 | ) 50 | 51 | 52 | } 53 | 54 | g.add_edges( sun, planets['Earth'], 55 | :penwidth => 2, 56 | :labeltooltip => "distance", 57 | :color => "black" 58 | ) 59 | 60 | i = 0 61 | # some more planets - each supposed having its own orbit - im trying to do it with rank 62 | ['Mercury','Venus','Mars','Jupiter','Saturn','Uranus','Neptune','Pluto'].each { |p| 63 | i = i + 1 64 | # set each to its own orbit 65 | # that doesnt seem to work ... 66 | g.subgraph { |c| 67 | c[:rank => "same"] 68 | planets[p] = c.add_nodes( 69 | p, 70 | :shape => "circle", 71 | :penwidth => 2, 72 | :fontsize => 12, 73 | :fillcolor => "green", 74 | :style => :filled, 75 | :label => "#{p}\n" 76 | ) 77 | c.add_edges( sun, planets[p], 78 | :penwidth => 2, 79 | :label => "distance", 80 | :color => "black" 81 | ) 82 | } 83 | 84 | } 85 | 86 | g.output( :png => "#{$0}.png" ) 87 | g.output( :none => "#{$0}.dot" ) 88 | -------------------------------------------------------------------------------- /lib/graphviz/nothugly.rb: -------------------------------------------------------------------------------- 1 | # This file use notugly.xsl: An XSL transform to pretty up the SVG output from Graphviz 2 | # 3 | # See: http://hokstad.com/making-graphviz-output-pretty-with-xsl 4 | # And: http://hokstad.com/making-graphviz-output-pretty-with-xsl-updated 5 | # 6 | # By Vidar Hokstad and Ryan Shea; Contributions by Jonas Tingborn, 7 | # Earl Cummings, Michael Kennedy (Graphviz 2.20.2 compatibility, bug fixes, 8 | # testing, lots of gradients) 9 | 10 | require 'rubygems' 11 | begin 12 | require 'xml/xslt' 13 | XSLT_METHOD = :xml_xslt_transform 14 | rescue LoadError => e 15 | require 'libxml' 16 | require 'libxslt' 17 | XSLT_METHOD = :libxslt_transform 18 | end 19 | 20 | class GraphViz 21 | # Transform to pretty up the SVG output 22 | # 23 | # For more information, see http://hokstad.com/making-graphviz-output-pretty-with-xsl 24 | # and http://hokstad.com/making-graphviz-output-pretty-with-xsl-updated 25 | # 26 | # You can use the :nothugly option to GraphViz#output : 27 | # 28 | # graph.output( :svg => "myGraph.svg", :nothugly => true ) 29 | # 30 | # Or directly on an SVG output graph : 31 | # 32 | # GraphViz.nothugly( "myGraph.svg" ) 33 | def self.nothugly( file, save = true ) 34 | xsl = File.join( File.dirname(File.expand_path(__FILE__)), "nothugly", "nothugly.xsl" ) 35 | out = self.send(XSLT_METHOD, file, xsl) 36 | 37 | if save 38 | fname = File.join( File.dirname(File.expand_path(file)), File.basename(file)) 39 | File.open( fname, "w" ) { |io| 40 | io.print out 41 | } 42 | else 43 | return out 44 | end 45 | end 46 | 47 | def self.xml_xslt_transform(xml, xsl) 48 | xslt = XML::XSLT.new() 49 | xslt.xml = xml 50 | xslt.xsl = xsl 51 | xslt.serve() 52 | end 53 | 54 | def self.libxslt_transform(xml, xsl) 55 | LibXML::XML.default_load_external_dtd = false 56 | LibXML::XML.default_substitute_entities = false 57 | 58 | stylesheet_doc = LibXML::XML::Document.file(xsl) 59 | stylesheet = LibXSLT::XSLT::Stylesheet.new(stylesheet_doc) 60 | xml_doc = LibXML::XML::Document.file(xml) 61 | stylesheet.apply(xml_doc).to_s 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /lib/graphviz/dot2ruby.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (C) 2010 Gregoire Lejeune 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | require 'graphviz/ext' 19 | require 'graphviz/utils' 20 | 21 | class Dot2Ruby #:nodoc: 22 | include GraphViz::Utils 23 | 24 | def initialize( xGVPath, xOutFile, xOutFormat = nil ) #:nodoc: 25 | paths = (xGVPath.nil?) ? [] : [xGVPath] 26 | @xGvprPath = find_executable( 'gvpr', paths ) 27 | if(@xGvprPath.nil?) 28 | raise Exception, "GraphViz is not installed. Please be sure that 'gvpr' is on the search path'" 29 | end 30 | @xOutFile = xOutFile 31 | @xOutFormat = xOutFormat || "_" 32 | @gvprScript = GraphViz::Ext.find( "dot2ruby.g" ) 33 | end 34 | 35 | def run( xFile ) #:nodoc: 36 | xCmd = [@xGvprPath, '-f', @gvprScript, '-a', @xOutFormat, xFile] 37 | xOutput = output_from_command( xCmd ) 38 | if @xOutFile.nil? 39 | puts xOutput 40 | else 41 | File.open( @xOutFile, "w" ) do |io| 42 | io.print xOutput 43 | end 44 | end 45 | end 46 | 47 | def eval( xFile ) #:nodoc: 48 | xCmd = [@xGvprPath, '-f', @gvprScript, '-a', '-', xFile] 49 | xOutput = output_from_command( xCmd ) 50 | instance_eval(xOutput) 51 | return @_graph_eval 52 | end 53 | 54 | def eval_string( data ) #:nodoc: 55 | t = Tempfile::open( File.basename(__FILE__) ) 56 | t.print( data ) 57 | t.close 58 | result = self.eval(t.path) 59 | t.close 60 | return result 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /examples/sample52.rb: -------------------------------------------------------------------------------- 1 | # http://www.graphviz.org/Gallery/directed/traffic_lights.gv.txt 2 | # 3 | # digraph TrafficLights { 4 | # node [shape=box]; gy2; yr2; rg2; gy1; yr1; rg1; 5 | # node [shape=circle,fixedsize=true,width=0.9]; green2; yellow2; red2; safe2; safe1; green1; yellow1; red1; 6 | # gy2->yellow2; 7 | # rg2->green2; 8 | # yr2->safe1; 9 | # yr2->red2; 10 | # safe2->rg2; 11 | # green2->gy2; 12 | # yellow2->yr2; 13 | # red2->rg2; 14 | # gy1->yellow1; 15 | # rg1->green1; 16 | # yr1->safe2; 17 | # yr1->red1; 18 | # safe1->rg1; 19 | # green1->gy1; 20 | # yellow1->yr1; 21 | # red1->rg1; 22 | # 23 | # overlap=false 24 | # label="PetriNet Model TrafficLights\nExtracted from ConceptBase and layed out by Graphviz" 25 | # fontsize=12; 26 | # } 27 | 28 | $:.unshift( "../../lib" ); 29 | require "graphviz" 30 | 31 | GraphViz::new( "TrafficLights", :type => :digraph ) { |g| 32 | g.gy2[:shape] = :box; g.yr2[:shape] = :box; g.rg2[:shape] = :box; g.gy1[:shape] = :box; g.yr1[:shape] = :box; g.rg1[:shape] = :box; 33 | g.green2.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 34 | g.yellow2.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 35 | g.red2.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 36 | g.safe2.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 37 | g.safe1.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 38 | g.green1.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 39 | g.yellow1.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 40 | g.red1.set { |n| n[:shape] = :circle; n[:fixedsize] = :true; n[:width] = 0.9 } 41 | 42 | g.gy2 << g.yellow2 43 | g.rg2 << g.green2 44 | g.yr2 << g.safe1 45 | g.yr2 << g.red2 46 | g.safe2 << g.rg2 47 | g.green2 << g.gy2 48 | g.yellow2 << g.yr2 49 | g.red2 << g.rg2 50 | g.gy1 << g.yellow1 51 | g.rg1 << g.green1 52 | g.yr1 << g.safe2 53 | g.yr1 << g.red1 54 | g.safe1 << g.rg1 55 | g.green1 << g.gy1 56 | g.yellow1 << g.yr1 57 | g.red1 << g.rg1 58 | 59 | g[:overlap] = :false 60 | g[:label] = 'PetriNet Model TrafficLights\nExtracted from ConceptBase and layed out by Graphviz' 61 | g[:fontsize] = 12; 62 | }.output( :errors => 1, :png => "#{$0}.png" ) -------------------------------------------------------------------------------- /lib/graphviz/types/spline_type.rb: -------------------------------------------------------------------------------- 1 | class SplineTypeException < RuntimeError 2 | end 3 | 4 | # spliteType or point 5 | # 6 | # spline ( ';' spline )* 7 | # where spline = (endp)? (startp)? point (triple)+ 8 | # and triple = point point point 9 | # and endp = "e,%f,%f" 10 | # and startp = "s,%f,%f" 11 | # 12 | # If a spline has points p1 p2 p3 ... pn, (n = 1 (mod 3)), the points correspond 13 | # to the control points of a B-spline from p1 to pn. If startp is given, it touches 14 | # one node of the edge, and the arrowhead goes from p1 to startp. If startp is not 15 | # given, p1 touches a node. Similarly for pn and endp. 16 | class GraphViz 17 | class Types 18 | class SplineType < Common 19 | FLOAT_MASK = /[-+]?(?:[0-9]*\.[0-9]+|[0-9]+)/ 20 | ENDP_MASK = /e\s*,\s*#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}/ 21 | STARTP_MASK = /s\s*,\s*#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}/ 22 | POINT_MASK = /#{FLOAT_MASK}\s*,\s*#{FLOAT_MASK}(?:\s*,\s*#{FLOAT_MASK})?!?/ 23 | TRIPLE_MASK = /#{POINT_MASK}\s+#{POINT_MASK}\s+#{POINT_MASK}/ 24 | SPLINE_MASK = /(?:#{ENDP_MASK}\s+)?(?:#{STARTP_MASK}\s+)?#{POINT_MASK}(?:\s*#{TRIPLE_MASK})+/ 25 | 26 | FINAL_SPLINE_MASK = /^#{SPLINE_MASK}(?:\s*;\s*#{SPLINE_MASK})*$/ 27 | FINAL_POINT_MASK = /^#{POINT_MASK}$/ 28 | 29 | def check(data) 30 | unless SPLINE_MASK.match(data).nil? 31 | @is_spline = true 32 | return data 33 | end 34 | unless FINAL_POINT_MASK.match(data).nil? 35 | @is_spline = false 36 | return data 37 | end 38 | return nil if data.empty? 39 | 40 | raise SplineTypeException, "Invalid spline type value" 41 | end 42 | 43 | def output 44 | return @data.to_s.inspect.gsub( "\\\\", "\\" ) 45 | end 46 | 47 | alias :to_gv :output 48 | alias :to_s :output 49 | 50 | def point 51 | if point? 52 | "[#{@data}]".to_ruby 53 | else 54 | # TODO! 55 | end 56 | end 57 | 58 | def endp 59 | end 60 | 61 | def startp 62 | end 63 | 64 | def triples 65 | end 66 | 67 | private 68 | def point? 69 | not @is_spline 70 | end 71 | 72 | def splite_type? 73 | @is_spline 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /examples/graphml/nested.graphml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | black 17 | filled 18 | SUB n5 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | red 29 | filled 30 | SUB n6 31 | 32 | 33 | SUB n6::n0 34 | blue 35 | filled 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples/theory/tests.rb: -------------------------------------------------------------------------------- 1 | $:.unshift( "../../lib" ) 2 | require 'graphviz' 3 | require 'graphviz/theory' 4 | 5 | g = GraphViz.digraph( "G", :path => "/usr/local/bin" ) do |g| 6 | g.a[:label => "1"] 7 | g.b[:label => "2"] 8 | g.c[:label => "3"] 9 | g.d[:label => "4"] 10 | g.e[:label => "5"] 11 | g.f[:label => "6"] 12 | 13 | # g.a << g.a 14 | g.a << g.b 15 | g.a << g.d 16 | (g.a << g.f)[:weight => 6, :label => "6"] 17 | g.b << g.c 18 | g.b << g.d 19 | g.b << g.e 20 | g.c << g.d 21 | (g.c << g.f)[:weight => 2, :label => "2"] 22 | g.d << g.e 23 | # g.e << g.c 24 | end 25 | g.output( :png => "matrix.png" ) 26 | 27 | t = GraphViz::Theory.new( g ) 28 | 29 | puts "Adjancy matrix : " 30 | puts t.adjancy_matrix 31 | # => [ 0 1 0 1 0 1] 32 | # [ 0 0 1 1 1 0] 33 | # [ 0 0 0 1 0 1] 34 | # [ 0 0 0 0 1 0] 35 | # [ 0 0 0 0 0 0] 36 | # [ 0 0 0 0 0 0] 37 | 38 | puts "Symmetric ? #{t.symmetric?}" 39 | 40 | puts "Incidence matrix :" 41 | puts t.incidence_matrix 42 | # => [ 1 1 1 0 0 0 0 0 0] 43 | # [ -1 0 0 1 1 1 0 0 0] 44 | # [ 0 0 0 -1 0 0 1 1 0] 45 | # [ 0 -1 0 0 -1 0 -1 0 1] 46 | # [ 0 0 0 0 0 -1 0 0 -1] 47 | # [ 0 0 -1 0 0 0 0 -1 0] 48 | 49 | g.each_node do |name, node| 50 | puts "Degree of node `#{name}' = #{t.degree(node)}" 51 | print "neighbors : "; p t.neighbors(name).map{ |e| e.id } # = node.neighbors.map { |e| e.id } 52 | print "incidents : "; p t.incidents(name).map{ |e| e.id } # = node.incidents.map { |e| e.id } 53 | end 54 | 55 | puts "Laplacian matrix :" 56 | puts t.laplacian_matrix 57 | # => [ 3 -1 0 -1 0 -1] 58 | # [ 0 4 -1 -1 -1 0] 59 | # [ 0 0 3 -1 0 -1] 60 | # [ 0 0 0 4 -1 0] 61 | # [ 0 0 0 0 2 0] 62 | # [ 0 0 0 0 0 2] 63 | 64 | puts "Dijkstra between a and f" 65 | r = t.moore_dijkstra(g.a, g.f) 66 | if r.nil? 67 | puts "No way !" 68 | else 69 | print "\tPath : "; p r[:path] 70 | puts "\tDistance : #{r[:distance]}" 71 | end 72 | # => Path : ["a", "b", "c", "f"] 73 | # Distance : 4.0 74 | 75 | print "Ranges : " 76 | rr = t.range 77 | p rr 78 | puts "Your graph contains circuits" if rr.include?(nil) 79 | 80 | puts "Critical path : " 81 | rrr = t.critical_path 82 | print "\tPath "; p rrr[:path] 83 | puts "\tDistance : #{rrr[:distance]}" 84 | 85 | t.pagerank.each { |node, rank| 86 | puts "Pagerank for node #{node.id} = #{rank}" 87 | } 88 | -------------------------------------------------------------------------------- /lib/graphviz/attrs.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2004 - 2012 Gregoire Lejeune 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, write to the Free Software 15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | class AttributeException < RuntimeError 18 | end 19 | 20 | class GraphViz 21 | class Attrs 22 | attr_accessor :data 23 | 24 | def initialize( gviz, name, attributes ) 25 | @name = name 26 | @attributes = attributes 27 | @data = Hash::new( ) 28 | @graphviz = gviz 29 | end 30 | 31 | def each 32 | @data.each do |k, v| 33 | yield(k, v) 34 | end 35 | end 36 | 37 | def to_h 38 | @data.clone 39 | end 40 | 41 | def []( key ) 42 | if key.class == Hash 43 | key.each do |k, v| 44 | self[k] = v 45 | end 46 | else 47 | @data[key.to_s] 48 | end 49 | end 50 | 51 | def []=( key, value ) 52 | unless @attributes.keys.include?( key.to_s ) 53 | raise ArgumentError, "#{@name} attribute '#{key.to_s}' invalid" 54 | end 55 | 56 | if value.nil? 57 | warn "Value for attribute `#{key}` can't be null" 58 | return 59 | end 60 | 61 | begin 62 | value = GraphViz::Types.const_get(@attributes[key.to_s]).new(value) 63 | rescue => e 64 | raise AttributeException, "Invalid value `#{value}` for attribute `#{key}` : #{e}" 65 | end 66 | 67 | if value 68 | @data[key.to_s] = value 69 | @graphviz.set_position( @name, key.to_s, @data[key.to_s] ) if @graphviz 70 | end 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /examples/graphml/cluster.graphml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | lightgrey 14 | filled 15 | process #1 16 | 17 | filled 18 | white 19 | 20 | 21 | filled 22 | white 23 | 24 | 25 | filled 26 | white 27 | 28 | 29 | filled 30 | white 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | blue 41 | process #2 42 | 43 | filled 44 | 45 | 46 | filled 47 | 48 | 49 | filled 50 | 51 | 52 | filled 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Mdiamond 62 | 63 | 64 | Mdiamond 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /lib/graphviz/dot_script.rb: -------------------------------------------------------------------------------- 1 | require "forwardable" 2 | class GraphViz 3 | 4 | class DOTScriptData 5 | attr_accessor :type 6 | def initialize(type = nil) 7 | @data = [] 8 | @separator = "" 9 | @type = type 10 | end 11 | 12 | def append(data) 13 | @data << data 14 | end 15 | alias :<< :append 16 | 17 | def add_attribute(name, value) 18 | @data << @separator << name << " = " << value 19 | @separator = determine_separator 20 | end 21 | 22 | def to_str 23 | case @type 24 | when "graph_attr" then "#{@data.join}#{@separator}" 25 | when "node_attr" then "node[#{@data.join(' ')}];" 26 | when "edge_attr" then "edge[#{@data.join(' ')}];" 27 | else raise ArgumentError, "Wrong type: #{@type}." 28 | end 29 | end 30 | alias :to_s :to_str 31 | 32 | def empty? 33 | @data.empty? 34 | end 35 | 36 | private 37 | 38 | def determine_separator 39 | case @type 40 | when "graph_attr" then ";\n" 41 | when "node_attr", "edge_attr" then "," 42 | else raise ArgumentError, "Wrong type: #{@type}." 43 | end 44 | end 45 | 46 | end 47 | 48 | class DOTScript 49 | extend Forwardable 50 | 51 | def_delegators :@script, :end_with? 52 | 53 | def initialize 54 | @script = String.new 55 | end 56 | 57 | def append(line) 58 | @script << assure_ends_with(line.to_s,"\n") 59 | 60 | self 61 | end 62 | alias :<< :append 63 | 64 | def prepend(line) 65 | @script = assure_ends_with(line.to_s,"\n") + @script 66 | 67 | self 68 | end 69 | 70 | def make_subgraph(name) 71 | prepend(assure_ends_with("subgraph #{name}"," {")) 72 | end 73 | 74 | def add_type(type, data) 75 | return self if data.empty? 76 | 77 | case type 78 | when "graph_attr" 79 | append_statement(" " + data) 80 | when "node_attr" 81 | append_statement(" node [" + data + "]") 82 | when "edge_attr" 83 | append_statement(" edge [" + data + "]") 84 | else 85 | raise ArgumentError, 86 | "Unknown type: #{type}." << 87 | "Possible: 'graph_attr','node_attr','edge_attr'" 88 | end 89 | 90 | self 91 | end 92 | 93 | def to_str 94 | @script 95 | end 96 | alias :to_s :to_str 97 | 98 | private 99 | 100 | def assure_ends_with(str,ending="\n") 101 | str.to_s.end_with?("\n") ? str : str + ending 102 | end 103 | 104 | def append_statement(statement) 105 | append(assure_ends_with(statement, ";\n")) 106 | end 107 | 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /lib/graphviz/utils.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | 3 | class GraphViz 4 | module Utils 5 | # Since this code is an adaptation of Launchy::Application#find_executable 6 | # (http://copiousfreetime.rubyforge.org/launchy/Launchy/Application.html) 7 | # it follow is licence : 8 | # 9 | # Permission to use, copy, modify, and/or distribute this software for any 10 | # purpose with or without fee is hereby granted, provided that the above 11 | # copyright notice and this permission notice appear in all copies. 12 | # 13 | # THE SOFTWARE IS PROVIDED AS IS AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 16 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 18 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 19 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 | def find_executable(bin, custom_paths) #:nodoc: 21 | system_path = ENV['PATH'] 22 | user_given_path = Array(custom_paths).join(File::PATH_SEPARATOR) 23 | search_path = system_path + File::PATH_SEPARATOR + user_given_path 24 | 25 | search_path.split(File::PATH_SEPARATOR).each do |path| 26 | file_path = File.join(path,bin) 27 | return file_path if File.executable?(file_path) and File.file?(file_path) 28 | 29 | if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ # WAS: elsif RUBY_PLATFORM =~ /mswin|mingw/ 30 | found_ext = (ENV['PATHEXT'] || '.exe;.bat;.com').split(";").find {|ext| File.executable?(file_path + ext) } 31 | return file_path + found_ext if found_ext 32 | end 33 | end 34 | return nil 35 | end 36 | 37 | def output_and_errors_from_command(cmd) #:nodoc: 38 | unless defined? Open3 39 | begin 40 | require 'open3' 41 | require 'win32/open3' 42 | rescue LoadError 43 | end 44 | end 45 | begin 46 | out, err, status = Open3.capture3(*cmd, :binmode => true) 47 | [out, err, status.exitstatus] 48 | rescue NotImplementedError, NoMethodError 49 | IO.popen( *cmd ) do |stdout| 50 | stdout.binmode 51 | [stdout.read, nil, nil] 52 | end 53 | end 54 | end 55 | 56 | def output_from_command(cmd) #:nodoc: 57 | output, errors, status = output_and_errors_from_command(cmd) 58 | if (status.nil? && (errors.nil? || errors.strip.empty?)) || status.zero? 59 | output 60 | else 61 | raise "Error from #{cmd}:\n#{errors}" 62 | end 63 | end 64 | 65 | end 66 | end 67 | 68 | -------------------------------------------------------------------------------- /examples/dot/genetic.dot: -------------------------------------------------------------------------------- 1 | graph "" 2 | { 3 | label="((+ (* (X) (- (- (X) (X)) (X))) (% (+ (X) (X)) (COS (- (X) (X))))) (EXP (* (X) (X))) (+ (% (EXP (SIN (+ (X) (X)))) (SIN (* (X) (EXP (* (X) (X)))))) (* (X) (X))) (% (EXP (% (X) (% (X) (X)))) (EXP (SIN (X)))))"; 4 | 5 | subgraph cluster01 6 | { 7 | label="(+ (* (X) (- (- (X) (X)) (X))) (% (+ (X) (X)) (COS (- (X) (X)))))"; 8 | n002 ; 9 | n002 [label="+"] ; 10 | n002 -- n003 ; 11 | n003 [label="*"] ; 12 | n003 -- n004 ; 13 | n004 [label="X"] ; 14 | n003 -- n005 ; 15 | n005 [label="-"] ; 16 | n005 -- n006 ; 17 | n006 [label="-"] ; 18 | n006 -- n007 ; 19 | n007 [label="X"] ; 20 | n006 -- n008 ; 21 | n008 [label="X"] ; 22 | n005 -- n009 ; 23 | n009 [label="X"] ; 24 | n002 -- n010 ; 25 | n010 [label="%"] ; 26 | n010 -- n011 ; 27 | n011 [label="+"] ; 28 | n011 -- n012 ; 29 | n012 [label="X"] ; 30 | n011 -- n013 ; 31 | n013 [label="X"] ; 32 | n010 -- n014 ; 33 | n014 [label="COS"] ; 34 | n014 -- n015 ; 35 | n015 [label="-"] ; 36 | n015 -- n016 ; 37 | n016 [label="X"] ; 38 | n015 -- n017 ; 39 | n017 [label="X"] ; 40 | } 41 | 42 | subgraph cluster17 43 | { 44 | label="(EXP (* (X) (X)))"; 45 | n018 ; 46 | n018 [label="EXP"] ; 47 | n018 -- n019 ; 48 | n019 [label="*"] ; 49 | n019 -- n020 ; 50 | n020 [label="X"] ; 51 | n019 -- n021 ; 52 | n021 [label="X"] ; 53 | } 54 | 55 | subgraph cluster21 56 | { 57 | label="(+ (% (EXP (SIN (+ (X) (X)))) (SIN (* (X) (EXP (* (X) (X)))))) (* (X) (X)))"; 58 | n022 ; 59 | n022 [label="+"] ; 60 | n022 -- n023 ; 61 | n023 [label="%"] ; 62 | n023 -- n024 ; 63 | n024 [label="EXP"] ; 64 | n024 -- n025 ; 65 | n025 [label="SIN"] ; 66 | n025 -- n026 ; 67 | n026 [label="+"] ; 68 | n026 -- n027 ; 69 | n027 [label="X"] ; 70 | n026 -- n028 ; 71 | n028 [label="X"] ; 72 | n023 -- n029 ; 73 | n029 [label="SIN"] ; 74 | n029 -- n030 ; 75 | n030 [label="*"] ; 76 | n030 -- n031 ; 77 | n031 [label="X"] ; 78 | n030 -- n032 ; 79 | n032 [label="EXP"] ; 80 | n032 -- n033 ; 81 | n033 [label="*"] ; 82 | n033 -- n034 ; 83 | n034 [label="X"] ; 84 | n033 -- n035 ; 85 | n035 [label="X"] ; 86 | n022 -- n036 ; 87 | n036 [label="*"] ; 88 | n036 -- n037 ; 89 | n037 [label="X"] ; 90 | n036 -- n038 ; 91 | n038 [label="X"] ; 92 | } 93 | 94 | subgraph cluster38 95 | { 96 | label="(% (EXP (% (X) (% (X) (X)))) (EXP (SIN (X))))"; 97 | n039 ; 98 | n039 [label="%"] ; 99 | n039 -- n040 ; 100 | n040 [label="EXP"] ; 101 | n040 -- n041 ; 102 | n041 [label="%"] ; 103 | n041 -- n042 ; 104 | n042 [label="X"] ; 105 | n041 -- n043 ; 106 | n043 [label="%"] ; 107 | n043 -- n044 ; 108 | n044 [label="X"] ; 109 | n043 -- n045 ; 110 | n045 [label="X"] ; 111 | n039 -- n046 ; 112 | n046 [label="EXP"] ; 113 | n046 -- n047 ; 114 | n047 [label="SIN"] ; 115 | n047 -- n048 ; 116 | n048 [label="X"] ; 117 | } 118 | } -------------------------------------------------------------------------------- /examples/sample17.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | $:.unshift( "../lib" ); 4 | require "graphviz" 5 | 6 | GraphViz::new( "G", :type => "graph", :rankdir => "LR", :bgcolor => "#808080" ) { |graph| 7 | graph.edge[:dir] = "none" 8 | 9 | graph.node[:width] = "0.3" 10 | graph.node[:height] = "0.3" 11 | graph.node[:label] = "" 12 | 13 | _ = {} 14 | 15 | ("1".."8").each do |v| 16 | _[v] = graph.add_nodes( v, :shape => "circle", :style => "invis") 17 | end 18 | ["10","20","30","40","50","60","70","80"].each do |v| 19 | _[v] = graph.add_nodes( v, :shape => "circle", :style => "invis") 20 | end 21 | 22 | ("a".."x").each do |v| 23 | _[v] = graph.add_nodes( v, :shape => "circle") 24 | end 25 | 26 | ("A".."X").each do |v| 27 | _[v] = graph.add_nodes( v, :shape => "diamond") 28 | end 29 | 30 | (_["1"] << _["a"])[:color]="#0000ff" 31 | (_["a"] << _["A"])[:color]="#0000ff" 32 | (_["a"] << _["B"])[:color]="#0000ff" 33 | (_["2"] << _["b"])[:color]="#ff0000" 34 | (_["b"] << _["B"])[:color]="#ff0000" 35 | (_["b"] << _["A"])[:color]="#ff0000" 36 | (_["3"] << _["c"])[:color]="#ffff00" 37 | (_["c"] << _["C"])[:color]="#ffff00" 38 | (_["c"] << _["D"])[:color]="#ffff00" 39 | (_["4"] << _["d"])[:color]="#00ff00" 40 | (_["d"] << _["D"])[:color]="#00ff00" 41 | (_["d"] << _["C"])[:color]="#00ff00" 42 | (_["5"] << _["e"])[:color]="#000000" 43 | (_["e"] << _["E"])[:color]="#000000" 44 | (_["e"] << _["F"])[:color]="#000000" 45 | (_["6"] << _["f"])[:color]="#00ffff" 46 | (_["f"] << _["F"])[:color]="#00ffff" 47 | (_["f"] << _["E"])[:color]="#00ffff" 48 | (_["7"] << _["g"])[:color]="#ffffff" 49 | (_["g"] << _["G"])[:color]="#ffffff" 50 | (_["g"] << _["H"])[:color]="#ffffff" 51 | (_["8"] << _["h"])[:color]="#ff00ff" 52 | (_["h"] << _["H"])[:color]="#ff00ff" 53 | (_["h"] << _["G"])[:color]="#ff00ff" 54 | 55 | graph.edge[:color]="#ff0000:#0000ff" 56 | _["A"] << _["i"]; _["i"] << [_["I"], _["K"]] 57 | _["B"] << _["j"]; _["j"] << [_["J"], _["L"]] 58 | 59 | graph.edge[:color]="#00ff00:#ffff00" 60 | _["C"] << _["k"]; _["k"] << [_["K"], _["I"]] 61 | _["D"] << _["l"]; _["l"] << [_["L"], _["J"]] 62 | 63 | graph.edge[:color]="#00ffff:#000000" 64 | _["E"] << _["m"]; _["m"] << [_["M"], _["O"]] 65 | _["F"] << _["n"]; _["n"] << [_["N"], _["P"]] 66 | 67 | graph.edge[:color]="#ff00ff:#ffffff" 68 | _["G"] << _["o"]; _["o"] << [_["O"], _["M"]] 69 | _["H"] << _["p"]; _["p"] << [_["P"], _["N"]] 70 | 71 | graph.edge[:color]="#00ff00:#ffff00:#ff0000:#0000ff" 72 | _["I"] << _["q"]; _["q"] << [_["Q"], _["U"]] 73 | _["J"] << _["r"]; _["r"] << [_["R"], _["V"]] 74 | _["K"] << _["s"]; _["s"] << [_["S"], _["W"]] 75 | _["L"] << _["t"]; _["t"] << [_["T"], _["X"]] 76 | 77 | graph.edge[:color]="#ff00ff:#ffffff:#00ffff:#000000" 78 | _["M"] << _["u"]; _["u"] << [_["U"], _["Q"]] 79 | _["N"] << _["v"]; _["v"] << [_["V"], _["R"]] 80 | _["O"] << _["w"]; _["w"] << [_["W"], _["S"]] 81 | _["P"] << _["x"]; _["x"] << [_["X"], _["T"]] 82 | 83 | graph.edge[:color]="#ff00ff:#ffffff:#00ffff:#000000:#00ff00:#ffff00:#ff0000:#0000ff" 84 | _["Q"] << _["10"] 85 | _["R"] << _["20"] 86 | _["S"] << _["30"] 87 | _["T"] << _["40"] 88 | _["U"] << _["50"] 89 | _["V"] << _["60"] 90 | _["W"] << _["70"] 91 | _["X"] << _["80"] 92 | }.output( :path => '/usr/local/bin/', :png => "#{$0}.png" ) 93 | -------------------------------------------------------------------------------- /bin/dot2ruby: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (C) 2010 Gregoire Lejeune 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | require 'rubygems' 19 | require 'graphviz/constants' 20 | require 'graphviz/dot2ruby' 21 | require 'getoptlong' 22 | 23 | def usage 24 | puts "usage: dot2ruby [-ofile] [-Tformat] [-h] [-V] script" 25 | puts "-o, --output-file file Output file" 26 | puts "-T, --output-format format Output format (default: nil)" 27 | puts "-p, --path Graphviz path" 28 | puts "-V, --version Show version" 29 | puts "-h, --help Show this usage message" 30 | end 31 | 32 | def version 33 | puts "Dot2Ruby v#{GraphViz::Constants::RGV_VERSION}, (c) 2010 Gregoire Lejeune " 34 | puts "" 35 | puts "This program is free software; you can redistribute it and/or modify" 36 | puts "it under the terms of the GNU General Public License as published by" 37 | puts "the Free Software Foundation; either version 2 of the License, or" 38 | puts "(at your option) any later version." 39 | puts "" 40 | puts "This program is distributed in the hope that it will be useful," 41 | puts "but WITHOUT ANY WARRANTY; without even the implied warranty of" 42 | puts "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" 43 | puts "GNU General Public License for more details." 44 | puts "" 45 | puts "You should have received a copy of the GNU General Public License" 46 | puts "along with this program; if not, write to the Free Software" 47 | puts "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" 48 | end 49 | 50 | xOutFile = nil 51 | xGVPath = nil 52 | xOutFormat = nil 53 | 54 | oOpt = GetoptLong.new( 55 | ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT], 56 | ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT], 57 | ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], 58 | ['--help', '-h', GetoptLong::NO_ARGUMENT], 59 | ['--version', '-V', GetoptLong::NO_ARGUMENT] 60 | ) 61 | 62 | begin 63 | oOpt.each_option do |xOpt, xValue| 64 | case xOpt 65 | when '--output-file' 66 | xOutFile = xValue 67 | when '--output-format' 68 | xOutFormat = xValue 69 | when '--path' 70 | xGVPath = xValue 71 | when '--help' 72 | usage( ) 73 | exit 74 | when '--version' 75 | version( ) 76 | exit 77 | end 78 | end 79 | rescue GetoptLong::InvalidOption 80 | usage( ) 81 | exit 82 | end 83 | 84 | xFile = ARGV[0] 85 | 86 | if xFile.nil? 87 | usage( ) 88 | exit 89 | end 90 | 91 | Dot2Ruby::new( xGVPath, xOutFile, xOutFormat ).run( xFile ) 92 | -------------------------------------------------------------------------------- /test/test_theory.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class GraphVizTheoryTest < Test::Unit::TestCase 4 | def setup 5 | @g = GraphViz.digraph( "G", :path => "/usr/local/bin" ) do |g| 6 | g.a[:label => "1"] 7 | g.b[:label => "2"] 8 | g.c[:label => "3"] 9 | g.d[:label => "4"] 10 | g.e[:label => "5"] 11 | g.f[:label => "6"] 12 | 13 | g.a << g.b 14 | g.a << g.d 15 | (g.a << g.f)[:weight => 6, :label => "6"] 16 | g.b << g.c 17 | g.b << g.d 18 | g.b << g.e 19 | g.c << g.d 20 | (g.c << g.f)[:weight => 2, :label => "2"] 21 | g.d << g.e 22 | end 23 | 24 | @t = GraphViz::Theory.new( @g ) 25 | end 26 | 27 | def test_theory 28 | assert @g, "Create graph failed!" 29 | assert @t, "Theory failed!" 30 | end 31 | 32 | def test_adgency_matrix 33 | adgency = GraphViz::Math::Matrix.new([ 34 | [0,1,0,1,0,1], 35 | [0,0,1,1,1,0], 36 | [0,0,0,1,0,1], 37 | [0,0,0,0,1,0], 38 | [0,0,0,0,0,0], 39 | [0,0,0,0,0,0] 40 | ]) 41 | assert_equal @t.adjancy_matrix, adgency, "Wrong adgency matrix" 42 | end 43 | 44 | def test_symetric 45 | assert_equal false, @t.symmetric? 46 | end 47 | 48 | def test_incidence_matrix 49 | incidence = GraphViz::Math::Matrix.new([ 50 | [ 1, 1, 1, 0, 0, 0, 0, 0, 0], 51 | [-1, 0, 0, 1, 1, 1, 0, 0, 0], 52 | [ 0, 0, 0,-1, 0, 0, 1, 1, 0], 53 | [ 0,-1, 0, 0,-1, 0,-1, 0, 1], 54 | [ 0, 0, 0, 0, 0,-1, 0, 0,-1], 55 | [ 0, 0,-1, 0, 0, 0, 0,-1, 0] 56 | ]) 57 | assert_equal @t.incidence_matrix, incidence 58 | end 59 | 60 | def test_degree 61 | assert_equal 3, @t.degree(@g.get_node("a")) 62 | assert_equal 4, @t.degree(@g.get_node("b")) 63 | assert_equal 3, @t.degree(@g.get_node("c")) 64 | assert_equal 4, @t.degree(@g.get_node("d")) 65 | assert_equal 2, @t.degree(@g.get_node("e")) 66 | assert_equal 2, @t.degree(@g.get_node("f")) 67 | end 68 | 69 | def test_laplacian_matrix 70 | laplacian = GraphViz::Math::Matrix.new([ 71 | [3,-1, 0,-1, 0,-1], 72 | [0, 4,-1,-1,-1, 0], 73 | [0, 0, 3,-1, 0,-1], 74 | [0, 0, 0, 4,-1, 0], 75 | [0, 0, 0, 0, 2, 0], 76 | [0, 0, 0, 0, 0, 2] 77 | ]) 78 | assert_equal @t.laplacian_matrix, laplacian 79 | end 80 | 81 | def test_dijkstra_a_f 82 | r = @t.moore_dijkstra(@g.a, @g.f) 83 | assert r 84 | assert_equal ["a", "b", "c", "f"], r[:path].map{|n| n.id} 85 | assert_equal 4.0, r[:distance] 86 | end 87 | 88 | def test_range 89 | assert_equal [0, 1, 2, 3, 4, 3], @t.range 90 | end 91 | 92 | def test_critical_path 93 | r = @t.critical_path 94 | assert r 95 | assert_equal [1, 6], r[:path] 96 | assert_equal 6.0, r[:distance] 97 | end 98 | 99 | def test_escaped_node_ids__adjancy_matrix 100 | @g = GraphViz.graph "G" do |g| 101 | g.add_nodes 'a@com' 102 | g.add_nodes 'b@com' 103 | g.add_edges 'a@com', 'b@com' 104 | end 105 | 106 | @t = GraphViz::Theory.new( @g ) 107 | 108 | assert_nothing_raised NoMethodError do 109 | @t.adjancy_matrix 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /lib/graphviz/family_tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | require 'rubygems' 4 | require 'graphviz' 5 | require 'graphviz/family_tree/generation' 6 | require 'graphviz/family_tree/person' 7 | require 'graphviz/family_tree/couple' 8 | require 'graphviz/family_tree/sibling' 9 | 10 | class GraphViz 11 | class FamilyTree 12 | # Create a new family tree 13 | # 14 | # require 'graphviz/family_tree' 15 | # t = GraphViz::FamilyTree.new do 16 | # ... 17 | # end 18 | def initialize( &block ) 19 | @persons = {} 20 | @graph = GraphViz.new( "FamilyTree", :use => :neato ) 21 | @generation_number = 0 22 | @generations = [] 23 | @couples = {} 24 | 25 | instance_eval(&block) if block 26 | end 27 | 28 | # Add a new generation in the tree 29 | # 30 | # require 'graphviz/family_tree' 31 | # t = GraphViz::FamilyTree.new do 32 | # generation do 33 | # ... 34 | # end 35 | # generation do 36 | # ... 37 | # end 38 | # end 39 | def generation( &b ) 40 | gen = GraphViz::FamilyTree::Generation.new( @graph, @persons, self, @generation_number ) 41 | gen.make( &b ) 42 | @generations << gen 43 | @generation_number += 1 44 | end 45 | 46 | def persons #:nodoc: 47 | @persons ||= {} 48 | end 49 | 50 | def add_couple( x, y, node ) #:nodoc: 51 | @couples[x] = {} if @couples[x].nil? 52 | @couples[x][y] = GraphViz::FamilyTree::Couple.new( @graph, node, [x, y] ) 53 | @couples[y] = {} if @couples[y].nil? 54 | @couples[y][x] = @couples[x][y] 55 | end 56 | 57 | # Get a couple (GraphViz::FamilyTree::Couple) 58 | def couple( x, y ) 59 | @couples[x][y] 60 | end 61 | 62 | def method_missing(sym, *args, &block) #:nodoc: 63 | persons[sym.to_s] 64 | end 65 | 66 | # Family size 67 | def size 68 | @persons.size 69 | end 70 | 71 | # Get the graph 72 | def graph 73 | maxY = @generations.size 74 | biggestGen, maxX = biggestGenerationNumberAndSize 75 | 76 | puts "#{maxY} generations" 77 | puts "Plus grosse generation : ##{biggestGen} avec #{maxX} personnes" 78 | 79 | puts "traitement des générations..." 80 | 81 | puts " #{biggestGen}:" 82 | @generations[biggestGen].persons.each do |id, person| 83 | puts " - #{id} : #{person.class}" 84 | end 85 | 86 | puts " Up..." 87 | (0...biggestGen).reverse_each do |genNumber| 88 | puts " #{genNumber}:" 89 | @generations[genNumber].persons.each do |id, person| 90 | puts " - #{id} : #{person.class}" 91 | end 92 | end 93 | 94 | puts " Down..." 95 | ((biggestGen+1)...maxY).each do |genNumber| 96 | puts " #{genNumber}:" 97 | @generations[genNumber].persons.each do |id, person| 98 | puts " - #{id} : #{person.class}" 99 | end 100 | end 101 | 102 | @graph 103 | end 104 | 105 | private 106 | def biggestGenerationNumberAndSize 107 | size = 0 108 | number = 0 109 | @generations.each do |gen| 110 | if gen.size > size 111 | size = gen.size 112 | number = gen.number 113 | end 114 | end 115 | return number, size 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /examples/rgv/rgv.ps: -------------------------------------------------------------------------------- 1 | %! Greg shapes for GraphViz/DOT 2 | 3 | % input format : 4 | % [ 54 36 0 36 0 0 54 0 54 36 ] 4 false yourshape 5 | % or 6 | % [ 54 36 0 36 0 0 54 0 54 36 ] 4 true yourshape 7 | % [ 150 150 100 150 100 100 150 100 150 150 ] 4 true yourshape 8 | % 9 | % [upper right (y, x), lower right (y, x), lower left (y, x), upper left (y, x), upper right (y, x)] 10 | 11 | /xdef {exch def} bind def 12 | 13 | /rgv_box { 14 | 10 dict begin 15 | /fflag xdef 16 | /sides xdef 17 | 18 | 4 sides ne { stop } if 19 | 20 | aload pop 21 | 22 | newpath 23 | moveto 24 | lineto 25 | lineto 26 | lineto 27 | closepath 28 | 29 | pop pop 30 | 31 | fflag { fill } { stroke } ifelse 32 | end 33 | } bind def 34 | 35 | /rgv_cloud { 36 | 10 dict begin 37 | /fflag xdef 38 | /sides xdef 39 | 40 | % Check if we have 4 sides. Else stop 41 | 4 sides ne { stop } if 42 | 43 | % (aload) takes an array as its argument and places the individual elements 44 | % of that array, and then the array itself, on the stack. Then (pop) remove 45 | % the top element from the stack (the array) 46 | aload pop 47 | 48 | /ury xdef /urx xdef 49 | /lry xdef /lrx xdef 50 | /lly xdef /llx xdef 51 | /uly xdef /ulx xdef 52 | pop pop 53 | 54 | /mx lrx llx neg add 2 div def 55 | /my uly lly neg add 2 div def 56 | 57 | % empty the current path and declares we are starting a new path 58 | newpath 59 | 60 | urx ury my neg add my 270 90 arc 61 | ulx mx add uly mx 0 180 arc 62 | llx lly my add my 90 270 arc 63 | lrx lry lineto 64 | 65 | closepath 66 | 67 | % The stroke operator on line four causes the path we have constructed to be 68 | % painted onto the current page. 69 | % The fill operator fills the current path with ink. 70 | fflag { fill } { stroke } ifelse 71 | end 72 | } bind def 73 | 74 | /rgv_flower { 75 | 10 dict begin 76 | /fflag xdef 77 | /sides xdef 78 | 79 | % Check if we have 4 sides. Else stop 80 | 4 sides ne { stop } if 81 | 82 | % (aload) takes an array as its argument and places the individual elements 83 | % of that array, and then the array itself, on the stack. Then (pop) remove 84 | % the top element from the stack (the array) 85 | aload pop 86 | 87 | /ury xdef /urx xdef 88 | /lry xdef /lrx xdef 89 | /lly xdef /llx xdef 90 | /uly xdef /ulx xdef 91 | pop pop 92 | 93 | /mx lrx llx neg add 2 div def 94 | /my uly lly neg add 2 div def 95 | 96 | % empty the current path and declares we are starting a new path 97 | newpath 98 | 99 | % Arcs 100 | urx ury my neg add my 270 90 arc 101 | ulx mx add uly mx 0 180 arc 102 | llx lly my add my 90 270 arc 103 | lrx mx neg add lry mx 180 0 arc 104 | 105 | closepath 106 | 107 | % The stroke operator on line four causes the path we have constructed to be 108 | % painted onto the current page. 109 | % The fill operator fills the current path with ink. 110 | fflag { fill } { stroke } ifelse 111 | end 112 | } bind def 113 | 114 | %[ 150 150 50 150 50 100 150 100 150 150 ] 4 false rgv_box 115 | %[ 250 250 150 250 150 200 250 200 250 250 ] 4 false rgv_flower 116 | %[ 350 350 250 350 250 300 350 300 350 350 ] 4 false rgv_cloud 117 | % 118 | %.5 setgray 119 | %[ 150 450 50 450 50 400 150 400 150 450 ] 4 true rgv_box 120 | %.5 setgray 121 | %[ 250 550 150 550 150 500 250 500 250 550 ] 4 true rgv_flower 122 | %.5 setgray 123 | %[ 350 650 250 650 250 600 350 600 350 650 ] 4 true rgv_cloud 124 | % 125 | %showpage 126 | -------------------------------------------------------------------------------- /lib/graphviz/family_tree/person.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'graphviz' 3 | 4 | class GraphViz 5 | class FamilyTree 6 | class Person 7 | def initialize( graph, tree, generation, id ) #:nodoc: 8 | @graph = graph 9 | @node = @graph.add_nodes( id ) 10 | @node["shape"] = "box" 11 | @tree = tree 12 | @generation = generation 13 | @x, @y = 0, 0 14 | @sibling = nil 15 | end 16 | 17 | def id 18 | @node.id 19 | end 20 | 21 | def name 22 | @node.label || @node.id 23 | end 24 | 25 | def sibling 26 | @sibling 27 | end 28 | 29 | def sibling=(x) 30 | @sibling=x 31 | end 32 | 33 | def couples #:nodoc: 34 | @couples 35 | end 36 | 37 | def node #:nodoc: 38 | @node 39 | end 40 | 41 | # Define the current person as a man 42 | # 43 | # greg.is_a_man( "Greg" ) 44 | def is_a_man( name ) 45 | @node["label"] = name 46 | @node["color"] = "blue" 47 | end 48 | 49 | # Define the current person as a boy 50 | # 51 | # greg.is_a_boy( "Greg" ) 52 | def is_a_boy( name ) 53 | is_a_man( name ) 54 | end 55 | 56 | # Define the current perdon as a woman 57 | # 58 | # mu.is_a_woman( "Muriel" ) 59 | def is_a_woman( name ) 60 | @node["label"] = name 61 | @node["color"] = "pink" 62 | end 63 | # Define the current perdon as a girl 64 | # 65 | # maia.is_a_girl( "Maia" ) 66 | def is_a_girl( name ) 67 | is_a_woman( name ) 68 | end 69 | 70 | # Define that's two persons are maried 71 | # 72 | # mu.is_maried_with greg 73 | def is_maried_with( x ) 74 | node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" ) 75 | node["shape"] = "point" 76 | @graph.add_edges( @node, node, "dir" => "none" ) 77 | @graph.add_edges( node, x.node, "dir" => "none" ) 78 | @tree.add_couple( self, x, node ) 79 | end 80 | 81 | # Define that's two persons are divorced 82 | # 83 | # sophie.is_divorced_with john 84 | def is_divorced_with( x ) 85 | node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" ) 86 | node["shape"] = "point" 87 | node["color"] = "red" 88 | @graph.add_edges( @node, node, "dir" => "none", "color" => "red" ) 89 | @graph.add_edges( node, x.node, "dir" => "none", "color" => "red" ) 90 | @tree.add_couple( self, x, node ) 91 | end 92 | 93 | # Define that's a person is widower of another 94 | # 95 | # simon.is_widower_of elisa 96 | def is_widower_of( x ) #veuf 97 | node = @graph.add_nodes( "#{@node.id}And#{x.node.id}" ) 98 | node["shape"] = "point" 99 | node["color"] = "green" 100 | @graph.add_edges( @node, node, "dir" => "none", "color" => "green" ) 101 | @graph.add_edges( node, x.node, "dir" => "none", "color" => "green" ) 102 | @tree.add_couple( self, x, node ) 103 | end 104 | 105 | # Define the current person as dead 106 | # 107 | # jack.is_dead 108 | def is_dead 109 | @node["style"] = "filled" 110 | end 111 | 112 | # Define the kids of a single person 113 | # 114 | # alice.kids( john, jack, julie ) 115 | def kids( *z ) 116 | GraphViz::FamilyTree::Couple.new( @graph, @node, [self] ).kids( *z ) 117 | end 118 | end 119 | end 120 | end 121 | -------------------------------------------------------------------------------- /bin/xml2gv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (C) 2005 - 2012 Gregoire Lejeune 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | require 'rubygems' 19 | require 'getoptlong' 20 | require 'graphviz/xml' 21 | 22 | def usage 23 | puts "usage: xml2gv [-Tformat] [-ofile] [-h] [-V] script" 24 | puts "-T, --output-format format Output format (default: PNG)" 25 | puts "-o, --output-file file Output file (default: STDOUT)" 26 | puts "-p, --path Graphviz path" 27 | puts "-u, --use PROGRAM Program to use (default: dot)" 28 | puts "-V, --version Show version" 29 | puts "-h, --help Show this usage message" 30 | end 31 | 32 | def version 33 | puts "XML2GraphViz v#{GraphViz::Constants::RGV_VERSION}, (c)2010 Gregoire Lejeune " 34 | puts "" 35 | puts "This program is free software; you can redistribute it and/or modify" 36 | puts "it under the terms of the GNU General Public License as published by" 37 | puts "the Free Software Foundation; either version 2 of the License, or" 38 | puts "(at your option) any later version." 39 | puts "" 40 | puts "This program is distributed in the hope that it will be useful," 41 | puts "but WITHOUT ANY WARRANTY; without even the implied warranty of" 42 | puts "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" 43 | puts "GNU General Public License for more details." 44 | puts "" 45 | puts "You should have received a copy of the GNU General Public License" 46 | puts "along with this program; if not, write to the Free Software" 47 | puts "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" 48 | end 49 | 50 | xOutFormat = "png" 51 | xOutFile = nil 52 | xGVPath = "" 53 | xUse = "dot" 54 | 55 | oOpt = GetoptLong.new( 56 | ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT], 57 | ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT], 58 | ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], 59 | ['--use', '-u', GetoptLong::REQUIRED_ARGUMENT], 60 | ['--help', '-h', GetoptLong::NO_ARGUMENT], 61 | ['--version', '-V', GetoptLong::NO_ARGUMENT] 62 | ) 63 | 64 | begin 65 | oOpt.each_option do |xOpt, xValue| 66 | case xOpt 67 | when '--output-format' 68 | xOutFormat = xValue 69 | when '--output-file' 70 | xOutFile = xValue 71 | when '--path' 72 | xGVPath = xValue 73 | when '--use' 74 | xUse = xValue 75 | when '--help' 76 | usage( ) 77 | exit 78 | when '--version' 79 | version( ) 80 | exit 81 | end 82 | end 83 | rescue GetoptLong::InvalidOption 84 | usage( ) 85 | exit 86 | end 87 | 88 | xFile = ARGV[0] 89 | 90 | if xFile.nil? 91 | usage( ) 92 | exit 93 | end 94 | 95 | gvxml = GraphViz::XML::new( xFile, :text => true, :attrs => true ) 96 | gvxml.graph.output( xOutFormat => xOutFile, :path => xGVPath ) 97 | -------------------------------------------------------------------------------- /lib/graphviz/xml.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2004 - 2012 Gregoire Lejeune 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | # GNU General Public License for more details. 12 | # 13 | # You should have received a copy of the GNU General Public License 14 | # along with this program; if not, write to the Free Software 15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | 17 | require 'graphviz' 18 | require 'rexml/document' 19 | 20 | class GraphViz 21 | class XML 22 | 23 | # The GraphViz object 24 | attr_accessor :graph 25 | 26 | # 27 | # Generate the graph 28 | # 29 | # THIS METHOD IS DEPRECATED, PLEASE USE GraphViz::XML.graph.output 30 | # 31 | def output( *options ) 32 | warn "GraphViz::XML.output is deprecated, use GraphViz::XML.graph.output" 33 | @graph.output( *options ) 34 | end 35 | 36 | private 37 | 38 | # 39 | # Create a graph from a XML file 40 | # 41 | # In: 42 | # * xml_file : XML File 43 | # * *options : Graph options: 44 | # * :text : show text nodes (default true) 45 | # * :attrs : show XML attributes (default true) 46 | # 47 | def initialize( xml_file, *options ) 48 | @node_name = String.new("00000") 49 | @show_text = true 50 | @show_attributes = true 51 | 52 | if options and options[0] 53 | options[0].each do |xKey, xValue| 54 | case xKey.to_s 55 | when "text" 56 | @show_text = xValue 57 | options[0].delete( xKey ) 58 | when "attrs" 59 | @show_attributes = xValue 60 | options[0].delete( xKey ) 61 | end 62 | end 63 | end 64 | 65 | @rexml_document = REXML::Document::new( File::new( xml_file ) ) 66 | @graph = GraphViz::new( "XML", *options ) 67 | parse_xml_node( @rexml_document.root() ) 68 | end 69 | 70 | def parse_xml_node( xml_node ) #:nodoc: 71 | local_node_name = @node_name.clone 72 | @node_name.succ! 73 | 74 | label = xml_node.name 75 | if xml_node.has_attributes? and @show_attributes 76 | label = "{ " + xml_node.name 77 | 78 | xml_node.attributes.each do |xName, xValue| 79 | label << "| { #{xName} | #{xValue} } " 80 | end 81 | 82 | label << "}" 83 | end 84 | @graph.add_nodes( local_node_name, "label" => label, "color" => "blue", "shape" => "record" ) 85 | 86 | ## Act: Search and add Text nodes 87 | if xml_node.has_text? and @show_text 88 | text_node_name = local_node_name.clone 89 | text_node_name << "111" 90 | 91 | xText = String.new 92 | xSep = "" 93 | xml_node.texts().each do |l| 94 | x = l.value.chomp.strip 95 | if x.length > 0 96 | xText << xSep << x 97 | xSep = "\n" 98 | end 99 | end 100 | 101 | if xText.length > 0 102 | @graph.add_nodes( text_node_name, "label" => xText, "color" => "black", "shape" => "ellipse" ) 103 | @graph.add_edges( local_node_name, text_node_name ) 104 | end 105 | end 106 | 107 | ## Act: Search and add attributes 108 | ## TODO 109 | 110 | xml_node.each_element( ) do |xml_child_node| 111 | child_node_name = parse_xml_node( xml_child_node ) 112 | @graph.add_edges( local_node_name, child_node_name ) 113 | end 114 | 115 | return( local_node_name ) 116 | end 117 | 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /test/test_graph.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | 3 | class GraphVizTest < Test::Unit::TestCase 4 | def setup 5 | @graph = GraphViz::new( :G ) 6 | end 7 | 8 | def test_graph 9 | assert(@graph, 'Create graph faild.') 10 | 11 | assert_block 'Set attribut for graph faild.' do 12 | @graph['size'] = "10,10" 13 | end 14 | 15 | assert_equal( "\"10,10\"", @graph['size'].to_s, 'Get attribut for graph faild.' ) 16 | 17 | assert_equal( "G", @graph.name, "Wrong graph name." ) 18 | end 19 | 20 | def test_node 21 | n, m = nil, nil 22 | 23 | assert_block 'Create node failed.' do 24 | n = @graph.add_nodes( "n1" ) 25 | end 26 | 27 | assert_block 'Get node failed.' do 28 | m = @graph.get_node( "n1" ) 29 | end 30 | 31 | assert_equal( m, n, "Node corrupted when get." ) 32 | 33 | assert_equal( @graph.node_count, 1, "Wrong number of nodes" ) 34 | 35 | assert_block 'Set attribut for node faild.' do 36 | n['label'] = "Hello\n\"world\"\\l" 37 | end 38 | 39 | assert_equal( "\"Hello\\n\\\"world\\\"\\l\"", n['label'].to_s, 'Get attribut for node faild.' ) 40 | end 41 | 42 | def test_search 43 | g = GraphViz::new( "G" ) 44 | g.node["shape"] = "ellipse" 45 | g.node["color"] = "black" 46 | 47 | g["color"] = "black" 48 | 49 | c0 = g.add_graph( "cluster0" ) 50 | c0["label"] = "process #1" 51 | c0["style"] = "filled" 52 | c0["color"] = "lightgrey" 53 | a0 = c0.add_nodes( "a0", "style" => "filled", "color" => "white" ) 54 | a1 = c0.add_nodes( "a1", "style" => "filled", "color" => "white" ) 55 | a2 = c0.add_nodes( "a2", "style" => "filled", "color" => "white" ) 56 | a3 = c0.add_nodes( "a3", "style" => "filled", "color" => "white" ) 57 | c0.add_edges( a0, a1 ) 58 | c0.add_edges( a1, a2 ) 59 | c0.add_edges( a2, a3 ) 60 | 61 | c1 = g.add_graph( "cluster1", "label" => "process #2" ) 62 | b0 = c1.add_nodes( "b0", "style" => "filled", "color" => "blue" ) 63 | b1 = c1.add_nodes( "b1", "style" => "filled", "color" => "blue" ) 64 | b2 = c1.add_nodes( "b2", "style" => "filled", "color" => "blue" ) 65 | b3 = c1.add_nodes( "b3", "style" => "filled", "color" => "blue" ) 66 | c1.add_edges( b0, b1 ) 67 | c1.add_edges( b1, b2 ) 68 | c1.add_edges( b2, b3 ) 69 | 70 | start = g.add_nodes( "start", "shape" => "Mdiamond" ) 71 | endn = g.add_nodes( "end", "shape" => "Msquare" ) 72 | 73 | g.add_edges( start, a0 ) 74 | g.add_edges( start, b0 ) 75 | g.add_edges( a1, b3 ) 76 | g.add_edges( b2, a3 ) 77 | g.add_edges( a3, a0 ) 78 | g.add_edges( a3, endn ) 79 | 80 | assert g 81 | 82 | assert_equal g.get_node("start"), start 83 | assert_equal g.find_node("start"), start 84 | assert_equal g.search_node("start"), start 85 | 86 | assert_nil g.get_node("a0") 87 | assert_equal g.find_node("a0"), a0 88 | assert_equal g.search_node("a0"), a0 89 | 90 | assert_nil c0.get_node("start") 91 | assert_equal c0.find_node("start"), start 92 | assert_nil c0.search_node("start") 93 | 94 | assert_equal c0.get_node("a0"), a0 95 | assert_equal c0.find_node("a0"), a0 96 | assert_equal c0.search_node("a0"), a0 97 | 98 | assert_nil c1.get_node("start") 99 | assert_equal c1.find_node("start"), start 100 | assert_nil c1.search_node("start") 101 | 102 | assert_nil c1.get_node("a0") 103 | assert_equal c1.find_node("a0"), a0 104 | assert_nil c1.search_node("a0") 105 | end 106 | 107 | def test_getting_escaped_node_from_edge 108 | @g = GraphViz.graph "G" do |g| 109 | g.add_nodes 'a@com' 110 | g.add_nodes 'b@com' 111 | g.add_edges 'a@com', 'b@com' 112 | end 113 | 114 | @g.each_edge do |e| 115 | assert_not_nil @g.get_node e.node_one(true, false) 116 | assert_not_nil @g.get_node e.node_two(true, false) 117 | end 118 | end 119 | 120 | def test_to_s 121 | assert_nothing_raised 'to_s with edge with numeric label failed.' do 122 | a = @graph.add_nodes('a') 123 | b = @graph.add_nodes('b') 124 | @graph.add_edges(a, b, :label => 5) 125 | @graph.to_s 126 | end 127 | end 128 | end 129 | -------------------------------------------------------------------------------- /test/test_examples.rb: -------------------------------------------------------------------------------- 1 | require 'open3' 2 | 3 | class GraphVizTest < Test::Unit::TestCase 4 | # you can run a subset of all the samples like this: 5 | # ruby test/test_examples.rb --name='/sample3[6-9]/' 6 | # 7 | # The above will run samples 36, 37, 38, and 39 8 | # 9 | RootDir = File.expand_path('../..', __FILE__) 10 | ExampleDir = File.join(RootDir,'examples') 11 | OutputDir = File.join(File.dirname(__FILE__),'output') 12 | 13 | # the below tests write to stdout. the other tests write to filesystem 14 | Skips = { 15 | #'35' => 'hanging for me', 16 | '33' => 'FamilyTree is broken', 17 | '36' => 'hangs for me', 18 | '53' => 'FamilyTree is broken', 19 | '57' => 'will not be able to find the graphml script', 20 | '98' => 'This test is just for debug', 21 | '99' => 'FamilyTree is broken' 22 | } 23 | 24 | def test_sample07 25 | assert_output_pattern(/\Adigraph structs \{.+\}\n\Z/m, '07') 26 | end 27 | 28 | def test_sample22 29 | assert_output_pattern(/\Adigraph mainmap \{.+\}\n\Z/m, '22') 30 | end 31 | 32 | def test_sample23 33 | assert_output_pattern(%r{\A\n\Z}m, '23') 34 | end 35 | 36 | def test_sample27 37 | assert_output_pattern(/\Adigraph G \{.*\}\n\Z/m, '27') 38 | end 39 | 40 | def test_sample38 41 | assert_output_pattern(/\Adigraph G \{.*\}\n\Z/m, '38') 42 | end 43 | 44 | def test_sample40 45 | assert_output_pattern(/\Adigraph G \{.*\}\n\Z/m, '40') 46 | end 47 | 48 | def test_sample41 49 | assert_output_pattern(/\A.*\Z/m, '40') 50 | end 51 | 52 | def test_sample55 53 | assert_output_pattern(/\Agraph G \{.*\}\n\Z/m, '55') 54 | end 55 | 56 | def test_sample62 57 | assert_output_pattern(/\ANode.*\n\Z/m, '62') 58 | end 59 | 60 | def test_sample70 61 | assert_output_pattern(/\Agraph G \{.*\}\n\Z/m, '70') 62 | end 63 | 64 | # 65 | # for every sample file in the examples directory that matches the 66 | # pattern ("sample01.rb, sample02.rb, etc) make a corresponding 67 | # test method: test_sample01(), test_sample02(), etc. To actually define 68 | # this methods in this way instead of just iterating over the list of files 69 | # will make it easier to use command-line options to isolate certain 70 | # tests, 71 | # (for example: ruby test/test_examples.rb --name '/sample0[1-5]/' ) 72 | # and to integrate better with certain kinds of test output and 73 | # reporting tools. 74 | # 75 | # we will skip over any methods already defined 76 | # 77 | 78 | @last_image_path = nil 79 | @number_to_path = {} 80 | class << self 81 | def make_sample_test_method path 82 | fail("failed match: #{path}") unless 83 | matches = %r{/(sample(\d\d))\.rb\Z}.match(path) 84 | basename, number = matches.captures 85 | number_to_path[number] = path 86 | meth = "test_#{basename}" 87 | return if method_defined?(meth) # if we hand-write one 88 | if Skips[number] 89 | puts "skipping #{basename} - #{Skips[number]}" 90 | return 91 | end 92 | define_method(meth){ assert_sample_file_has_no_output(path) } 93 | end 94 | attr_accessor :last_image_path, :number_to_path 95 | end 96 | 97 | if File.directory? OutputDir 98 | FileUtils.rm_rf OutputDir 99 | end 100 | FileUtils.cp_r ExampleDir, OutputDir 101 | 102 | samples = Dir[File.join(OutputDir,'sample*.rb')].sort 103 | samples.each {|path| make_sample_test_method(path) } 104 | 105 | private 106 | 107 | def assert_output_pattern tgt_regexp, number 108 | path = self.class.number_to_path[number] 109 | out, err, _ = Open3.capture3("ruby #{path}") 110 | assert_equal "", err, "no errors" 111 | assert_match tgt_regexp, out.gsub(/\r\n/, "\n"), "output for sample#{number} should match regexp" 112 | end 113 | 114 | def assert_sample_file_has_no_output path 115 | begin 116 | out, err, _ = Open3.capture3("ruby #{path}") 117 | assert_equal(0, out.length, "expecting empty output got [#{out}]") 118 | assert_equal(0, err.length, "expecting empty errorput got [#{err}]") 119 | rescue Exception => e 120 | assert(false, "got exception on #{File.basename(path)}: #{e.message}") 121 | end 122 | end 123 | 124 | def setup_sample path 125 | unless File.directory? OutputDir 126 | FileUtils.mkdir_p(OutputDir, :verbose => true) 127 | end 128 | ARGV[0] = nil if ARGV.any? # hack trigger searching for 'dot' executable 129 | end 130 | 131 | def run_sample(path) 132 | run_path = File.join(OutputDir, File.basename(path)) 133 | FileUtils.cp path, run_path 134 | out, err, _ = Open3.capture3("ruby #{run_path}") 135 | return out, err 136 | end 137 | end 138 | -------------------------------------------------------------------------------- /lib/ext/gvpr/dot2ruby.g: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010 Gregoire Lejeune 2 | // 3 | // This program is free software; you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation; either version 2 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // This program is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with this program; if not, write to the Free Software 15 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 | // 17 | // Usage : 18 | // gvpr -f dot2ruby.g [-a ] 19 | 20 | BEGIN { 21 | int g_strict; int g_direct; 22 | graph_t cluster; 23 | node_t cnode; 24 | edge_t cedge; 25 | string attr; string attrv; 26 | graph_t subgraph; graph_t pgraph; 27 | graph_t ofgraph; 28 | graph_t sub_graph; 29 | graph_t tmp_g; 30 | 31 | string xOut; 32 | if( ARGC == 0 ) { 33 | xOut = "_"; 34 | } else { 35 | xOut = tolower(ARGV[0]); 36 | } 37 | 38 | printf( "# This code was generated by dot2ruby.g\n\n" ); 39 | 40 | string rubyfy( string s ) { 41 | string out; 42 | out = tolower( s ); 43 | out = gsub( out, "[!a-zA-Z0-9_]", "_" ); 44 | return( out ); 45 | } 46 | 47 | string stringify( string s ) { 48 | string sout; 49 | sout = gsub(s, "\"", "\\\""); 50 | sout = gsub(sout, "@", "\\@"); 51 | sout = gsub(sout, "$", "\\$"); 52 | return( sout ); 53 | } 54 | 55 | void load_sub_graph( graph_t p ) { 56 | if(p == NULL) { 57 | return; 58 | } 59 | sub_graph = fstsubg(p); 60 | while( sub_graph != NULL ) { 61 | pgraph = sub_graph.parent; 62 | printf ( " graph_%s = graph_%s.add_graph( \"%s\" )\n", rubyfy(sub_graph.name), rubyfy(pgraph.name), rubyfy(sub_graph.name) ); 63 | 64 | // ATTRS 65 | attr = fstAttr(sub_graph, "G"); 66 | while( attr != "" ) { 67 | attrv = aget( sub_graph, attr ); 68 | if( attrv != "" ) { 69 | printf( " graph_%s[:%s] = '%s'\n", rubyfy(sub_graph.name), attr, attrv ); 70 | } 71 | attr = nxtAttr( sub_graph, "G", attr ); 72 | } 73 | tmp_g = sub_graph; 74 | load_sub_graph(sub_graph); 75 | sub_graph = nxtsubg( tmp_g ); 76 | 77 | } 78 | } 79 | 80 | graph_t get_node_graph(node_t n, graph_t p) { 81 | sub_graph = fstsubg(p); 82 | while( sub_graph != NULL ) { 83 | if( isSubnode( sub_graph, n) != 0 ) { 84 | return get_node_graph(n, sub_graph); 85 | } 86 | sub_graph = nxtsubg( sub_graph ); 87 | } 88 | return p; 89 | } 90 | 91 | graph_t get_edge_graph(edge_t e, graph_t p) { 92 | sub_graph = fstsubg(p); 93 | while( sub_graph != NULL ) { 94 | if( isSubedge( sub_graph, e) != 0 ) { 95 | return get_edge_graph(e, sub_graph); 96 | } 97 | sub_graph = nxtsubg( sub_graph ); 98 | } 99 | return p; 100 | } 101 | 102 | 103 | } 104 | 105 | BEG_G { 106 | printf( "require 'rubygems'\nrequire 'graphviz'\n"); 107 | // Directed 108 | g_direct = isDirect($); 109 | if( g_direct == 0 ) { 110 | printf( "graph_%s = GraphViz.graph( \"%s\"", rubyfy($.name), stringify($.name) ); 111 | } else { 112 | printf( "graph_%s = GraphViz.digraph( \"%s\"", rubyfy($.name), stringify($.name) ); 113 | } 114 | // Strict 115 | g_strict = isStrict($); 116 | if( g_strict != 0 ) { 117 | printf( ", :strict => true" ); 118 | } 119 | printf( " ) { |graph_%s|\n", rubyfy($.name) ); 120 | 121 | // Attributs of G 122 | attr = fstAttr($, "G"); 123 | while( attr != "" ) { 124 | attrv = aget( $, attr ); 125 | if( attrv != "" ) { 126 | printf( " graph_%s[:%s] = '%s'\n", rubyfy($.name), attr, attrv ); 127 | } 128 | attr = nxtAttr( $, "G", attr ); 129 | } 130 | 131 | load_sub_graph($); 132 | } 133 | 134 | N { 135 | pgraph = $.root; 136 | ofgraph = get_node_graph($, pgraph); 137 | 138 | printf( " node_%s = graph_%s.add_nodes( \"%s\"", rubyfy($.name), rubyfy(ofgraph.name), stringify($.name) ); 139 | 140 | // Attributs of N 141 | attr = fstAttr($G, "N"); 142 | while( attr != "" ) { 143 | attrv = aget( $, attr ); 144 | if( attrv != "" ) { 145 | printf( ", :%s => '%s'", attr, gsub( attrv, "'", "\\'" ) ); 146 | } else { 147 | printf( ", :%s => ''", attr ); 148 | } 149 | attr = nxtAttr( $G, "N", attr ); 150 | } 151 | 152 | printf( " )\n"); 153 | } 154 | 155 | E { 156 | pgraph = $.root; 157 | ofgraph = get_edge_graph($, $.root); 158 | 159 | printf( " graph_%s.add_edges( \"%s\", \"%s\"", rubyfy(ofgraph.name), stringify($.tail.name), stringify($.head.name) ); 160 | 161 | // Attributs of E 162 | attr = fstAttr($G, "E"); 163 | while( attr != "" ) { 164 | attrv = aget( $, attr ); 165 | if( attrv != "" ) { 166 | printf( ", :%s => '%s'", attr, gsub( attrv, "'", "\\'" ) ); 167 | } else { 168 | printf( ", :%s => ''", attr ); 169 | } 170 | attr = nxtAttr( $G, "E", attr ); 171 | } 172 | 173 | printf( " )\n" ); 174 | } 175 | 176 | END_G { 177 | printf( "}\n" ); 178 | if( xOut != "_" ) { 179 | if( xOut == "-" ) { 180 | printf( "@_graph_eval = graph_%s\n", rubyfy($.name) ); 181 | } else { 182 | printf( "graph_%s.output( :%s => \"%s.%s\" )\n", rubyfy($.name), xOut, gsub($F, ".*/", ""), xOut ); 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /bin/git2gv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (C) 2010 Gregoire Lejeune 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | require 'rubygems' 19 | require 'getoptlong' 20 | require 'graphviz' 21 | 22 | class Git2Gv 23 | def initialize( xGVPath, xOutFile, xOutFormat, bNothugly ) 24 | @xGVPath, @xOutFile, @xOutFormat, @bNothugly = xGVPath, xOutFile, xOutFormat.to_sym, bNothugly 25 | end 26 | 27 | def run 28 | git = GraphViz.new( :G, :path => @xGVPath ) 29 | 30 | git.node[:shape => "record"] 31 | 32 | branches.each do |branch| 33 | git.add_nodes( branch, :style => "filled", :fillcolor => :lightgrey ) 34 | end 35 | 36 | commits.each do |commit| 37 | git.add_nodes( 38 | commit[:short], 39 | :style => "filled", 40 | :fillcolor => :lightblue, 41 | :label => "{ #{commit[:long]} |{ #{commit[:comment].gsub(/\{/, "\\{").gsub(/\}/, "\\}").gsub(/\|/, "\\|").gsub(//, "\\>")}}| { #{commit[:commiter]} | #{commit[:date]} } }" 42 | ) 43 | end 44 | 45 | refs.each do |from, to| 46 | git.add_edges( from, to ) 47 | end 48 | 49 | relations.each do |from, to| 50 | git.add_edges( to, from, :dir => "back" ) 51 | end 52 | 53 | git.output( @xOutFormat => @xOutFile, :nothugly => @bNothugly ) 54 | end 55 | 56 | # private 57 | def cmd(c, &blk) 58 | `#{c}`.split($/).map(&blk || proc {|a| a }) 59 | end 60 | 61 | def commits 62 | @commits ||= begin 63 | data = [] 64 | cmd('git log --pretty=format:"%h - %H - %s - %cn - %cd" --date=short').each do |commit| 65 | x = commit.split( " - " ) 66 | data << { 67 | :short => x[0], 68 | :long => x[1], 69 | :comment => x[2], 70 | :commiter => x[3], 71 | :date => x[4] 72 | } 73 | end 74 | data 75 | end 76 | end 77 | 78 | def relations 79 | @rels ||= cmd("git log --pretty=format:\"%h %p\"") { |l| 80 | c, *parents = l.split 81 | parents.map {|p| [p, c] } 82 | }.flatten(1) 83 | end 84 | 85 | def branches 86 | @branches ||= cmd("git branch") {|b| b[2..-1] } 87 | end 88 | 89 | def refs 90 | branches.inject({}) {|h,b| 91 | h.tap { h[b] = `git log -1 #{b} --pretty=format:"%h"` } 92 | } 93 | end 94 | 95 | def current_branch 96 | cmd("git branch").select {|l| l =~ /^\*/ }.first.strip[2..-1] 97 | end 98 | end 99 | 100 | def usage 101 | puts "usage: git2gv [-Tformat] [-ofile] [-h] [-V]" 102 | puts "-T, --output-format format Output format (default: png)" 103 | puts " --nothugly Use nothugly if SVG output" 104 | puts "-o, --output-file file Output file (default: STDOUT)" 105 | puts "-p, --path Graphviz path" 106 | puts "-V, --version Show version" 107 | puts "-h, --help Show this usage message" 108 | end 109 | 110 | def version 111 | puts "Git2GraphViz v#{GraphViz::Constants::RGV_VERSION}, (c)2010 Gregoire Lejeune " 112 | puts "" 113 | puts "This program is free software; you can redistribute it and/or modify" 114 | puts "it under the terms of the GNU General Public License as published by" 115 | puts "the Free Software Foundation; either version 2 of the License, or" 116 | puts "(at your option) any later version." 117 | puts "" 118 | puts "This program is distributed in the hope that it will be useful," 119 | puts "but WITHOUT ANY WARRANTY; without even the implied warranty of" 120 | puts "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" 121 | puts "GNU General Public License for more details." 122 | puts "" 123 | puts "You should have received a copy of the GNU General Public License" 124 | puts "along with this program; if not, write to the Free Software" 125 | puts "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" 126 | end 127 | 128 | oOpt = GetoptLong.new( 129 | ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT], 130 | ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT], 131 | ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], 132 | ['--nothugly', GetoptLong::NO_ARGUMENT], 133 | ['--help', '-h', GetoptLong::NO_ARGUMENT], 134 | ['--version', '-V', GetoptLong::NO_ARGUMENT] 135 | ) 136 | 137 | xOutFormat = "png" 138 | xOutFile = nil 139 | xGVPath = "" 140 | bNothugly = false 141 | 142 | begin 143 | oOpt.each_option do |xOpt, xValue| 144 | case xOpt 145 | when '--output-format' 146 | xOutFormat = xValue 147 | when '--output-file' 148 | xOutFile = xValue 149 | when '--path' 150 | xGVPath = xValue 151 | when '--nothugly' 152 | bNothugly = true 153 | when '--help' 154 | usage( ) 155 | exit 156 | when '--version' 157 | version( ) 158 | exit 159 | end 160 | end 161 | rescue GetoptLong::InvalidOption 162 | usage( ) 163 | exit 164 | end 165 | 166 | Git2Gv.new( xGVPath, xOutFile, xOutFormat, bNothugly ).run 167 | 168 | -------------------------------------------------------------------------------- /bin/gem2gv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (C) 2010 Gregoire Lejeune 3 | # 4 | # This program is free software; you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation; either version 2 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program; if not, write to the Free Software 16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | require 'rubygems' 19 | require 'graphviz' 20 | require 'getoptlong' 21 | 22 | class Gem2Gv 23 | def initialize( xGVPath, xUse ) 24 | @oGraph = GraphViz::new( :G, :path => xGVPath, :use => xUse ) 25 | 26 | @nodes = [] 27 | @name = 'gem2gv' 28 | end 29 | 30 | def out( xFormat = "dot", xFile = nil ) 31 | if xFile.nil? 32 | @oGraph.output( xFormat => String ) 33 | else 34 | @oGraph.output( xFormat => xFile ) 35 | end 36 | end 37 | 38 | def go( gemName, version = ">0" ) 39 | nodes = getDependency(gemName, version) 40 | 41 | createEdges( gemName, version, nodes ) 42 | 43 | nodes.each do |node| 44 | unless @nodes.include?(node) 45 | @nodes << node 46 | go( node[:name], node[:version] ) 47 | end 48 | end 49 | end 50 | 51 | def getDependency( gemName, version = ">0" ) 52 | nodes = [] 53 | 54 | dependency = Gem::Dependency.new( gemName, version ) 55 | fetcher = Gem::SpecFetcher.fetcher 56 | 57 | fetcher.find_matching(dependency).each do |spec_tuple, source_uri| 58 | spec = fetcher.fetch_spec spec_tuple, URI.parse(source_uri) 59 | 60 | spec.dependencies.each do |dep| 61 | #nodes << { :name => dep.name, :version => dep.version_requirements.to_s} unless nodes.include?({ :name => dep.name, :version => dep.version_requirements.to_s}) 62 | nodes << { :name => dep.name, :version => ">0" } unless nodes.include?({ :name => dep.name, :version => ">0" }) 63 | end 64 | end 65 | 66 | return nodes 67 | end 68 | 69 | def getNode( name, version ) 70 | #nodeName = "#{name}#{version}" 71 | #nodeLabel = "#{name}\n#{version}" 72 | nodeName = "#{name}" 73 | nodeLabel = "#{name}" 74 | return @oGraph.get_node(nodeName) || @oGraph.add_nodes( nodeName, "label" => nodeLabel ) 75 | end 76 | 77 | def createEdges( gemName, version, nodes ) 78 | nodeA = getNode( gemName, version ) 79 | 80 | nodes.each do |node| 81 | nodeB = getNode( node[:name], node[:version] ) 82 | @oGraph.add_edges( nodeA, nodeB ) 83 | end 84 | end 85 | end 86 | 87 | def usage 88 | puts "usage: gem2gv [-Tformat] [-ofile] [-h] [-V] gemname" 89 | puts "-T, --output-format format Output format (default: PNG)" 90 | puts "-o, --output-file file Output file (default: STDOUT)" 91 | puts "-p, --path Graphviz path" 92 | puts "-u, --use PROGRAM Program to use (default: dot)" 93 | puts "-s, --stop LIB[,LIB, ...] Stop on libs" 94 | puts "-V, --version Show version" 95 | puts "-h, --help Show this usage message" 96 | end 97 | 98 | def version 99 | puts "Gem2GraphViz v#{GraphViz::Constants::RGV_VERSION}, (c)2010 Gregoire Lejeune " 100 | puts "" 101 | puts "This program is free software; you can redistribute it and/or modify" 102 | puts "it under the terms of the GNU General Public License as published by" 103 | puts "the Free Software Foundation; either version 2 of the License, or" 104 | puts "(at your option) any later version." 105 | puts "" 106 | puts "This program is distributed in the hope that it will be useful," 107 | puts "but WITHOUT ANY WARRANTY; without even the implied warranty of" 108 | puts "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the" 109 | puts "GNU General Public License for more details." 110 | puts "" 111 | puts "You should have received a copy of the GNU General Public License" 112 | puts "along with this program; if not, write to the Free Software" 113 | puts "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA" 114 | end 115 | 116 | xOutFormat = "png" 117 | xOutFile = nil 118 | xGVPath = "" 119 | xUse = "dot" 120 | 121 | oOpt = GetoptLong.new( 122 | ['--output-format', '-T', GetoptLong::REQUIRED_ARGUMENT], 123 | ['--output-file', '-o', GetoptLong::REQUIRED_ARGUMENT], 124 | ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], 125 | ['--use', '-u', GetoptLong::REQUIRED_ARGUMENT], 126 | ['--help', '-h', GetoptLong::NO_ARGUMENT], 127 | ['--version', '-V', GetoptLong::NO_ARGUMENT] 128 | ) 129 | 130 | begin 131 | oOpt.each_option do |xOpt, xValue| 132 | case xOpt 133 | when '--output-format' 134 | xOutFormat = xValue 135 | when '--output-file' 136 | xOutFile = xValue 137 | when '--path' 138 | xGVPath = xValue 139 | when '--use' 140 | xUse = xValue 141 | when '--help' 142 | usage( ) 143 | exit 144 | when '--version' 145 | version( ) 146 | exit 147 | end 148 | end 149 | rescue GetoptLong::InvalidOption 150 | usage( ) 151 | exit 152 | end 153 | 154 | xGem = ARGV[0] 155 | 156 | if xGem.nil? 157 | usage( ) 158 | exit 159 | end 160 | 161 | 162 | g = Gem2Gv.new( xGVPath, xUse ) 163 | g.go( xGem ) 164 | result = g.out( xOutFormat, xOutFile ) 165 | puts result unless result.nil? 166 | -------------------------------------------------------------------------------- /examples/dot/lion_share.dot: -------------------------------------------------------------------------------- 1 | digraph Ped_Lion_Share { 2 | ratio = "auto" ; 3 | label = "Pedigree Lion_Share" ; 4 | 5 | "001" [shape=box , regular=1,style=filled,fillcolor=white ] ; 6 | "002" [shape=box , regular=1,style=filled,fillcolor=white ] ; 7 | "003" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 8 | "004" [shape=box , regular=1,style=filled,fillcolor=white ] ; 9 | "005" [shape=box , regular=1,style=filled,fillcolor=white ] ; 10 | "006" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 11 | "007" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 12 | "009" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 13 | "014" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 14 | "015" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 15 | "016" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 16 | "ZZ01" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 17 | "ZZ02" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 18 | "017" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 19 | "012" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 20 | "008" [shape=box , regular=1,style=filled,fillcolor=white ] ; 21 | "011" [shape=box , regular=1,style=filled,fillcolor=white ] ; 22 | "013" [shape=box , regular=1,style=filled,fillcolor=white ] ; 23 | "010" [shape=box , regular=1,style=filled,fillcolor=white ] ; 24 | "023" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 25 | "020" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 26 | "021" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 27 | "018" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 28 | "025" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 29 | "019" [shape=box , regular=1,style=filled,fillcolor=white ] ; 30 | "022" [shape=box , regular=1,style=filled,fillcolor=white ] ; 31 | "024" [shape=box , regular=1,style=filled,fillcolor=white ] ; 32 | "027" [shape=circle , regular=1,style=filled,fillcolor=white ] ; 33 | "026" [shape=box , regular=1,style=filled,fillcolor=white ] ; 34 | "028" [shape=box , regular=1,style=filled,fillcolor=grey ] ; 35 | "marr0001" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 36 | "001" -> "marr0001" [dir=none,weight=1] ; 37 | "007" -> "marr0001" [dir=none,weight=1] ; 38 | "marr0001" -> "017" [dir=none, weight=2] ; 39 | "marr0002" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 40 | "001" -> "marr0002" [dir=none,weight=1] ; 41 | "ZZ02" -> "marr0002" [dir=none,weight=1] ; 42 | "marr0002" -> "012" [dir=none, weight=2] ; 43 | "marr0003" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 44 | "002" -> "marr0003" [dir=none,weight=1] ; 45 | "003" -> "marr0003" [dir=none,weight=1] ; 46 | "marr0003" -> "008" [dir=none, weight=2] ; 47 | "marr0004" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 48 | "002" -> "marr0004" [dir=none,weight=1] ; 49 | "006" -> "marr0004" [dir=none,weight=1] ; 50 | "marr0004" -> "011" [dir=none, weight=2] ; 51 | "marr0005" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 52 | "002" -> "marr0005" [dir=none,weight=1] ; 53 | "ZZ01" -> "marr0005" [dir=none,weight=1] ; 54 | "marr0005" -> "013" [dir=none, weight=2] ; 55 | "marr0006" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 56 | "004" -> "marr0006" [dir=none,weight=1] ; 57 | "009" -> "marr0006" [dir=none,weight=1] ; 58 | "marr0006" -> "010" [dir=none, weight=2] ; 59 | "marr0007" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 60 | "005" -> "marr0007" [dir=none,weight=1] ; 61 | "015" -> "marr0007" [dir=none,weight=1] ; 62 | "marr0007" -> "023" [dir=none, weight=2] ; 63 | "marr0008" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 64 | "005" -> "marr0008" [dir=none,weight=1] ; 65 | "016" -> "marr0008" [dir=none,weight=1] ; 66 | "marr0008" -> "020" [dir=none, weight=2] ; 67 | "marr0009" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 68 | "005" -> "marr0009" [dir=none,weight=1] ; 69 | "012" -> "marr0009" [dir=none,weight=1] ; 70 | "marr0009" -> "021" [dir=none, weight=2] ; 71 | "marr0010" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 72 | "008" -> "marr0010" [dir=none,weight=1] ; 73 | "017" -> "marr0010" [dir=none,weight=1] ; 74 | "marr0010" -> "018" [dir=none, weight=2] ; 75 | "marr0011" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 76 | "011" -> "marr0011" [dir=none,weight=1] ; 77 | "023" -> "marr0011" [dir=none,weight=1] ; 78 | "marr0011" -> "025" [dir=none, weight=2] ; 79 | "marr0012" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 80 | "013" -> "marr0012" [dir=none,weight=1] ; 81 | "014" -> "marr0012" [dir=none,weight=1] ; 82 | "marr0012" -> "019" [dir=none, weight=2] ; 83 | "marr0013" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 84 | "010" -> "marr0013" [dir=none,weight=1] ; 85 | "021" -> "marr0013" [dir=none,weight=1] ; 86 | "marr0013" -> "022" [dir=none, weight=2] ; 87 | "marr0014" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 88 | "019" -> "marr0014" [dir=none,weight=1] ; 89 | "020" -> "marr0014" [dir=none,weight=1] ; 90 | "marr0014" -> "024" [dir=none, weight=2] ; 91 | "marr0015" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 92 | "022" -> "marr0015" [dir=none,weight=1] ; 93 | "025" -> "marr0015" [dir=none,weight=1] ; 94 | "marr0015" -> "027" [dir=none, weight=2] ; 95 | "marr0016" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 96 | "024" -> "marr0016" [dir=none,weight=1] ; 97 | "018" -> "marr0016" [dir=none,weight=1] ; 98 | "marr0016" -> "026" [dir=none, weight=2] ; 99 | "marr0017" [shape=diamond,style=filled,label="",height=.1,width=.1] ; 100 | "026" -> "marr0017" [dir=none,weight=1] ; 101 | "027" -> "marr0017" [dir=none,weight=1] ; 102 | "marr0017" -> "028" [dir=none, weight=2] ; 103 | } -------------------------------------------------------------------------------- /examples/dot/psg.dot: -------------------------------------------------------------------------------- 1 | digraph g { 2 | graph [fontsize=30 labelloc="t" label="" splines=true overlap=false rankdir = "LR"]; 3 | ratio = auto; 4 | "state0" [ style = "filled, bold" penwidth = 5 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #0
(0) s -> •e $
(1) e -> •l '=' r
(2) e -> •r
(3) l -> •'*' r
(4) l -> •'n'
(5) r -> •l
> ]; 5 | "state1" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #1
(3) l -> •'*' r
(3) l -> '*' •r
(4) l -> •'n'
(5) r -> •l
> ]; 6 | "state2" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #2
(4) l -> 'n' •=$
> ]; 7 | "state3" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #3
(5) r -> l •=$
> ]; 8 | "state4" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #4
(3) l -> '*' r •=$
> ]; 9 | "state5" [ style = "filled" penwidth = 1 fillcolor = "black" fontname = "Courier New" shape = "Mrecord" label =<
State #5
(0) s -> e •$
> ]; 10 | "state6" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #6
(1) e -> l •'=' r
(5) r -> l •$
> ]; 11 | "state7" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #7
(1) e -> l '=' •r
(3) l -> •'*' r
(4) l -> •'n'
(5) r -> •l
> ]; 12 | "state8" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #8
(1) e -> l '=' r •$
> ]; 13 | "state9" [ style = "filled" penwidth = 1 fillcolor = "white" fontname = "Courier New" shape = "Mrecord" label =<
State #9
(2) e -> r •$
> ]; 14 | state0 -> state5 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "e" ]; 15 | state0 -> state6 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ]; 16 | state0 -> state9 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ]; 17 | state0 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ]; 18 | state0 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ]; 19 | state1 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ]; 20 | state1 -> state4 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ]; 21 | state1 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ]; 22 | state1 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ]; 23 | state6 -> state7 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'='" ]; 24 | state7 -> state8 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "r" ]; 25 | state7 -> state1 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'*'" ]; 26 | state7 -> state2 [ penwidth = 1 fontsize = 14 fontcolor = "grey28" label = "'n'" ]; 27 | state7 -> state3 [ penwidth = 5 fontsize = 28 fontcolor = "black" label = "l" ]; 28 | } --------------------------------------------------------------------------------