gv 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +7 -0
- data/gv.gemspec +25 -0
- data/lib/gv.rb +226 -0
- data/lib/gv/version.rb +3 -0
- data/spec/graph_spec.rb +143 -0
- data/spec/render.png +0 -0
- data/spec/simple_graph.dot +6 -0
- data/spec/spec_helper.rb +2 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fdabad8208f3857d6f16f16b5db3d7e005def7a2
|
4
|
+
data.tar.gz: 5e9d9f1993de38f9e43b80ac61e3f8d75e37c9c4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8f74f1b224cf335ad1f9328379b1de48d176c169d82499faabe0fe9a2661791b62576dc7540d40719d1e79f4f474c2afbbf99a89263f6e8264b78609cecefaa8
|
7
|
+
data.tar.gz: 680ecfbd1bd2dd1269aaa43706eaa1f7513c1c9249c234e85bbabdeae61b426d05d2c428aba36043aaeb810c3f4f7049c3bc446e304cf810f8465b162f545ca1
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 furunkel
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# GV
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'gv'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install gv
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/[my-github-username]/gv/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/gv.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gv/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gv"
|
8
|
+
spec.version = GV::VERSION
|
9
|
+
spec.authors = ["furunkel"]
|
10
|
+
spec.email = ["julian@linux4you.it"]
|
11
|
+
spec.summary = %q{Graphviz for Ruby, using libgvc directly via FFI}
|
12
|
+
spec.homepage = "https://github.com/furunkel/gv"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
spec.add_development_dependency "minitest"
|
23
|
+
|
24
|
+
spec.add_dependency "ffi"
|
25
|
+
end
|
data/lib/gv.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'gv/version'
|
2
|
+
require 'ffi'
|
3
|
+
|
4
|
+
module GV
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
extend ::FFI::Library
|
8
|
+
|
9
|
+
ffi_lib 'gvc', 'cgraph', 'cgraph'
|
10
|
+
|
11
|
+
class AGraph < ::FFI::ManagedStruct
|
12
|
+
# dummy layout, only ever used by reference
|
13
|
+
layout :_1, :int,
|
14
|
+
:_2, :int
|
15
|
+
|
16
|
+
def self.release(ptr)
|
17
|
+
FFI.agclose(ptr) unless ptr.null?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
typedef :pointer, :gvc
|
22
|
+
typedef :pointer, :ag_node
|
23
|
+
typedef :pointer, :ag_edge
|
24
|
+
|
25
|
+
attach_function :gvContext, [], :pointer
|
26
|
+
attach_function :gvFreeLayout, [:gvc, AGraph.by_ref], :int
|
27
|
+
attach_function :gvLayout, [:gvc, AGraph.by_ref, :string], :int
|
28
|
+
|
29
|
+
attach_function :gvRenderFilename, [:gvc, AGraph.by_ref, :string, :string], :int
|
30
|
+
attach_function :gvRenderData, [:gvc, AGraph.by_ref, :string, :pointer, :pointer], :int
|
31
|
+
attach_function :gvFreeRenderData, [:pointer], :void
|
32
|
+
|
33
|
+
attach_function :agmemread, [:string], AGraph.by_ref
|
34
|
+
attach_function :agopen, [:string, :long, :pointer], AGraph.by_ref
|
35
|
+
attach_function :agclose, [AGraph.by_ref], :int
|
36
|
+
|
37
|
+
attach_variable :Agundirected, :long
|
38
|
+
attach_variable :Agstrictundirected, :long
|
39
|
+
attach_variable :Agdirected, :long
|
40
|
+
attach_variable :Agstrictdirected, :long
|
41
|
+
|
42
|
+
attach_function :agnode, [AGraph.by_ref, :string, :int], :ag_node
|
43
|
+
attach_function :agedge, [AGraph.by_ref, :ag_node, :ag_node, :string, :int], :ag_edge
|
44
|
+
attach_function :agsubg, [AGraph.by_ref, :string, :int], :pointer
|
45
|
+
|
46
|
+
attach_function :agnameof, [:pointer], :string
|
47
|
+
attach_function :agraphof, [:pointer], :pointer
|
48
|
+
|
49
|
+
attach_function :agtail, [:ag_edge], :ag_node
|
50
|
+
attach_function :aghead, [:ag_edge], :ag_node
|
51
|
+
attach_function :agget, [:pointer, :string], :string
|
52
|
+
|
53
|
+
attach_function :agsafeset, [:pointer, :string, :string, :string], :pointer
|
54
|
+
attach_function :agstrdup_html, [:pointer, :string], :string
|
55
|
+
attach_function :agstrfree, [:pointer, :string], :int
|
56
|
+
|
57
|
+
attach_function :agisdirected, [AGraph.by_ref], :int
|
58
|
+
attach_function :agisstrict, [AGraph.by_ref], :int
|
59
|
+
end
|
60
|
+
|
61
|
+
class Component
|
62
|
+
@@gvc = FFI.gvContext()
|
63
|
+
|
64
|
+
attr_reader :graph
|
65
|
+
|
66
|
+
def hash
|
67
|
+
ptr.hash
|
68
|
+
end
|
69
|
+
|
70
|
+
def ==(other)
|
71
|
+
other.is_a?(Component) && ptr == other.ptr
|
72
|
+
end
|
73
|
+
|
74
|
+
alias :eql? :==
|
75
|
+
|
76
|
+
def name
|
77
|
+
FFI.agnameof ptr
|
78
|
+
end
|
79
|
+
|
80
|
+
def []=(attr, value)
|
81
|
+
FFI.agsafeset(ptr, attr.to_s, value.to_s, "")
|
82
|
+
end
|
83
|
+
|
84
|
+
def [](attr)
|
85
|
+
FFI.agget(ptr, attr.to_s)
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
attr_reader :ptr
|
90
|
+
end
|
91
|
+
|
92
|
+
class Node < Component
|
93
|
+
def initialize(graph, name_or_ptr)
|
94
|
+
@graph = graph
|
95
|
+
case name_or_ptr
|
96
|
+
when String
|
97
|
+
@ptr = FFI.agnode(graph.ptr, name_or_ptr, 1)
|
98
|
+
else
|
99
|
+
@ptr = name_or_ptr
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Edge < Component
|
105
|
+
def initialize(graph, name, tail, head)
|
106
|
+
@graph = graph
|
107
|
+
|
108
|
+
@ptr = FFI.agedge(graph.ptr, tail.ptr, head.ptr, name, 1)
|
109
|
+
end
|
110
|
+
|
111
|
+
def head
|
112
|
+
Node.new @graph, FFI.aghead(ptr)
|
113
|
+
end
|
114
|
+
|
115
|
+
def tail
|
116
|
+
Node.new @graph, FFI.agtail(ptr)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class BaseGraph < Component
|
121
|
+
|
122
|
+
def node(name, attrs = {})
|
123
|
+
component Node, [name], attrs
|
124
|
+
end
|
125
|
+
|
126
|
+
def edge(name, tail, head, attrs = {})
|
127
|
+
component Edge, [name, tail, head], attrs
|
128
|
+
end
|
129
|
+
|
130
|
+
def graph(name, attrs = {})
|
131
|
+
graph = component SubGraph, [name], attrs
|
132
|
+
yield graph if block_given?
|
133
|
+
|
134
|
+
graph
|
135
|
+
end
|
136
|
+
|
137
|
+
def directed?
|
138
|
+
FFI.agisdirected(ptr) == 1
|
139
|
+
end
|
140
|
+
|
141
|
+
def strict?
|
142
|
+
FFI.agisstrict(ptr) == 1
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
def component(klass, args, attrs = {})
|
147
|
+
comp = klass.new self, *args
|
148
|
+
|
149
|
+
attrs.each do |attr, value|
|
150
|
+
comp[attr] = value
|
151
|
+
end
|
152
|
+
|
153
|
+
comp
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
class SubGraph < BaseGraph
|
159
|
+
def initialize(graph, name)
|
160
|
+
@graph = graph
|
161
|
+
@ptr = FFI.agsubg(graph.ptr, name, 1)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
class Graph < BaseGraph
|
166
|
+
|
167
|
+
class << self
|
168
|
+
private :new
|
169
|
+
def open(name, type = :directed, strict = :normal)
|
170
|
+
ag_type = case [type, strict]
|
171
|
+
when [:directed, :normal] then FFI.Agdirected
|
172
|
+
when [:undirected, :normal] then FFI.Agundirected
|
173
|
+
when [:directed, :strict] then FFI.Agstrictdirected
|
174
|
+
when [:undirected, :strict] then FFI.Agstrictundirected
|
175
|
+
else
|
176
|
+
raise ArgumentError, "invalid graph type #{[type, strict]}"
|
177
|
+
end
|
178
|
+
|
179
|
+
graph = new(FFI.agopen(name, ag_type, ::FFI::Pointer::NULL))
|
180
|
+
|
181
|
+
if block_given?
|
182
|
+
yield graph
|
183
|
+
end
|
184
|
+
|
185
|
+
graph
|
186
|
+
end
|
187
|
+
|
188
|
+
def load(io)
|
189
|
+
data = if io.is_a? String
|
190
|
+
io
|
191
|
+
else
|
192
|
+
io.read
|
193
|
+
end
|
194
|
+
new FFI.agmemread(data)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def initialize(ptr)
|
199
|
+
@ptr = ptr
|
200
|
+
end
|
201
|
+
|
202
|
+
def write(filename, format = 'png', layout = 'dot')
|
203
|
+
FFI.gvLayout(@@gvc, ptr, layout.to_s)
|
204
|
+
FFI.gvRenderFilename(@@gvc, ptr, format.to_s, filename);
|
205
|
+
FFI.gvFreeLayout(@@gvc, ptr)
|
206
|
+
end
|
207
|
+
|
208
|
+
def render(format = 'png', layout = 'dot')
|
209
|
+
FFI.gvLayout(@@gvc, ptr, layout.to_s)
|
210
|
+
|
211
|
+
data_ptr = ::FFI::MemoryPointer.new(:pointer, 1)
|
212
|
+
len_ptr = ::FFI::MemoryPointer.new(:int, 1)
|
213
|
+
|
214
|
+
FFI.gvRenderData(@@gvc, ptr, format.to_s, data_ptr, len_ptr);
|
215
|
+
len = len_ptr.read_uint
|
216
|
+
data_ptr = data_ptr.read_pointer
|
217
|
+
|
218
|
+
data = data_ptr.read_string_length len
|
219
|
+
|
220
|
+
FFI.gvFreeRenderData(data_ptr)
|
221
|
+
FFI.gvFreeLayout(@@gvc, ptr)
|
222
|
+
|
223
|
+
data
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
data/lib/gv/version.rb
ADDED
data/spec/graph_spec.rb
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
include GV
|
4
|
+
|
5
|
+
describe Graph do
|
6
|
+
describe :open do
|
7
|
+
it "creates a new graph" do
|
8
|
+
graph = Graph.open 'test'
|
9
|
+
graph.directed?.must_equal true
|
10
|
+
graph.strict?.must_equal false
|
11
|
+
|
12
|
+
graph = Graph.open 'test', :directed, :strict
|
13
|
+
graph.strict?.must_equal true
|
14
|
+
graph.directed?.must_equal true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "takes a block" do
|
18
|
+
graph = Graph.open 'test' do |g|
|
19
|
+
g.directed?.must_equal true
|
20
|
+
g.strict?.must_equal false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe :load do
|
26
|
+
it "loads graph from file" do
|
27
|
+
f = lambda do |f|
|
28
|
+
graph = Graph.load f
|
29
|
+
graph.directed?.must_equal true
|
30
|
+
graph.strict?.must_equal false
|
31
|
+
graph.name.must_equal 'g'
|
32
|
+
end
|
33
|
+
|
34
|
+
filename = File.join(__dir__, 'simple_graph.dot')
|
35
|
+
file = File.open filename
|
36
|
+
f.call file
|
37
|
+
file.close
|
38
|
+
|
39
|
+
f.call File.read(filename)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe :node do
|
44
|
+
before do
|
45
|
+
@graph = Graph.open 'test'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "creates a new node" do
|
49
|
+
@graph.node('test').must_be_kind_of Node
|
50
|
+
end
|
51
|
+
|
52
|
+
it "sets given attributes" do
|
53
|
+
@graph.node('test', color: 'green')[:color].must_equal 'green'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe :graph do
|
58
|
+
before do
|
59
|
+
@graph = Graph.open 'test'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "creates a new subgraph" do
|
63
|
+
@graph.graph('test').must_be_kind_of SubGraph
|
64
|
+
end
|
65
|
+
|
66
|
+
it "sets given attributes" do
|
67
|
+
@graph.graph('test', color: 'green')[:color].must_equal 'green'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "takes a block" do
|
71
|
+
graph = @graph.graph('test') do |g|
|
72
|
+
g[:color] = 'green'
|
73
|
+
end
|
74
|
+
graph[:color].must_equal 'green'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
describe :edge do
|
80
|
+
before do
|
81
|
+
@graph = Graph.open 'test'
|
82
|
+
@head = @graph.node 'head'
|
83
|
+
@tail = @graph.node 'tail'
|
84
|
+
end
|
85
|
+
|
86
|
+
it "creates a new edge" do
|
87
|
+
@graph.edge('test', @tail, @head).must_be_kind_of Edge
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets given attributes" do
|
91
|
+
@graph.edge('test', @tail, @head, color: 'green')[:color].must_equal 'green'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe :write do
|
96
|
+
it "renders the graph to the given filename" do
|
97
|
+
graph = Graph.open 'test'
|
98
|
+
graph.edge 'e', graph.node('A'), graph.node('B')
|
99
|
+
filename = File.join Dir.tmpdir, Dir::Tmpname.make_tmpname(['gv_test', '.png'], nil)
|
100
|
+
graph.write filename
|
101
|
+
File.file?(filename).must_equal true
|
102
|
+
File.unlink filename
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe :render do
|
107
|
+
it "renders the graph to a string" do
|
108
|
+
graph = Graph.open 'test'
|
109
|
+
graph.edge 'e', graph.node('A'), graph.node('B', shape: 'polygon')
|
110
|
+
data = graph.render
|
111
|
+
|
112
|
+
graph = nil
|
113
|
+
GC.start
|
114
|
+
data.must_be_kind_of String
|
115
|
+
|
116
|
+
File.write 'spec/render.png', data
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe Edge do
|
122
|
+
before do
|
123
|
+
@graph = Graph.open 'test'
|
124
|
+
@head = @graph.node 'head'
|
125
|
+
@tail = @graph.node 'tail'
|
126
|
+
@edge = Edge.new @graph, 'test', @tail, @head
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'gives access to head and tail' do
|
130
|
+
@edge.head.must_equal @head
|
131
|
+
@edge.tail.must_equal @tail
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'gives access to name' do
|
135
|
+
@edge.name.must_equal 'test'
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'gives access to attributes' do
|
139
|
+
@edge[:color].must_equal nil
|
140
|
+
@edge[:color] = 'green'
|
141
|
+
@edge[:color].must_equal 'green'
|
142
|
+
end
|
143
|
+
end
|
data/spec/render.png
ADDED
Binary file
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- furunkel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: ffi
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- julian@linux4you.it
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE.txt
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- gv.gemspec
|
82
|
+
- lib/gv.rb
|
83
|
+
- lib/gv/version.rb
|
84
|
+
- spec/graph_spec.rb
|
85
|
+
- spec/render.png
|
86
|
+
- spec/simple_graph.dot
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
homepage: https://github.com/furunkel/gv
|
89
|
+
licenses:
|
90
|
+
- MIT
|
91
|
+
metadata: {}
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 2.4.5
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: Graphviz for Ruby, using libgvc directly via FFI
|
112
|
+
test_files:
|
113
|
+
- spec/graph_spec.rb
|
114
|
+
- spec/render.png
|
115
|
+
- spec/simple_graph.dot
|
116
|
+
- spec/spec_helper.rb
|