ucd 0.1.0 → 0.1.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 +4 -4
- data/README.md +102 -0
- data/VERSION +1 -1
- data/examples/composite.dot +66 -0
- data/lib/ucd/formatter/base.rb +0 -6
- data/lib/ucd/formatter/graphviz.rb +5 -11
- data/lib/ucd/interface/command_line.rb +27 -16
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdaec7d175f5ab56710dc4b64d3e79ab6ad9a076
|
4
|
+
data.tar.gz: dada32605eab973771134ddf2bc3c62549cdd4d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1128275fe76fb04862fd555650f37c78452e8bc5449101bfbd97810568bddcd923aa19f2515612e893b8dbc4d7045327c0a79209c8212d8304c144d0da699b9c
|
7
|
+
data.tar.gz: d3a1c0a61fe3fece3f69fd0a8090a50ed1c499673ab7f2315b6a5a166f78383697fe52bd866017a4379f2658e271d697127f80b7ed35f5a4a1a2c5e425723f39
|
data/README.md
CHANGED
@@ -14,6 +14,9 @@ different formats.
|
|
14
14
|
```sh
|
15
15
|
# Convert composite.ucd to composite.png
|
16
16
|
$ ucd --type png --output . composite.ucd
|
17
|
+
|
18
|
+
# Display detailed help message
|
19
|
+
$ ucd --help
|
17
20
|
```
|
18
21
|
|
19
22
|
## Language
|
@@ -22,6 +25,105 @@ $ ucd --type png --output . composite.ucd
|
|
22
25
|
|
23
26
|
See the examples directory for UCD files and their generated DOT and PNG files.
|
24
27
|
|
28
|
+
#### Component Pattern
|
29
|
+
|
30
|
+
`component.ucd`
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
abstract class Component {
|
34
|
+
method operation
|
35
|
+
}
|
36
|
+
|
37
|
+
class Leaf {
|
38
|
+
generalizes Component
|
39
|
+
}
|
40
|
+
|
41
|
+
class Composite {
|
42
|
+
protected field children : Component
|
43
|
+
method addChild(child : Component) : Component
|
44
|
+
method removeChild(child : Component) : Component
|
45
|
+
method getChild(index : Integer) : Component
|
46
|
+
|
47
|
+
generalizes Component
|
48
|
+
aggregation Component *
|
49
|
+
}
|
50
|
+
```
|
51
|
+
|
52
|
+
`component.png`
|
53
|
+
|
54
|
+

|
55
|
+
|
56
|
+
`component.dot`
|
57
|
+
|
58
|
+
```dot
|
59
|
+
digraph G {
|
60
|
+
graph [splines="ortho" rankdir="BT"]
|
61
|
+
edge [color="gray50"]
|
62
|
+
node [shape="plain"]
|
63
|
+
|
64
|
+
ClassComponent [label=<
|
65
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
66
|
+
<TR>
|
67
|
+
<TD>«abstract»<BR/><I><B>Component</B></I></TD>
|
68
|
+
</TR>
|
69
|
+
<TR>
|
70
|
+
<TD></TD>
|
71
|
+
</TR>
|
72
|
+
<TR>
|
73
|
+
<TD>
|
74
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
75
|
+
<TR><TD ALIGN="LEFT">+ operation()</TD></TR>
|
76
|
+
</TABLE>
|
77
|
+
</TD>
|
78
|
+
</TR>
|
79
|
+
</TABLE>
|
80
|
+
>]
|
81
|
+
|
82
|
+
ClassLeaf [label=<
|
83
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
84
|
+
<TR>
|
85
|
+
<TD><B>Leaf</B></TD>
|
86
|
+
</TR>
|
87
|
+
<TR>
|
88
|
+
<TD></TD>
|
89
|
+
</TR>
|
90
|
+
<TR>
|
91
|
+
<TD></TD>
|
92
|
+
</TR>
|
93
|
+
</TABLE>
|
94
|
+
>]
|
95
|
+
|
96
|
+
ClassComposite [label=<
|
97
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
98
|
+
<TR>
|
99
|
+
<TD><B>Composite</B></TD>
|
100
|
+
</TR>
|
101
|
+
<TR>
|
102
|
+
<TD>
|
103
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
104
|
+
<TR><TD ALIGN="LEFT"># children : Component</TD></TR>
|
105
|
+
</TABLE>
|
106
|
+
</TD>
|
107
|
+
</TR>
|
108
|
+
<TR>
|
109
|
+
<TD>
|
110
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
111
|
+
<TR><TD ALIGN="LEFT">+ addChild(child : Component) : Component</TD></TR>
|
112
|
+
<TR><TD ALIGN="LEFT">+ removeChild(child : Component) : Component</TD></TR>
|
113
|
+
<TR><TD ALIGN="LEFT">+ getChild(index : Integer) : Component</TD></TR>
|
114
|
+
</TABLE>
|
115
|
+
</TD>
|
116
|
+
</TR>
|
117
|
+
</TABLE>
|
118
|
+
>]
|
119
|
+
|
120
|
+
ClassLeaf -> ClassComponent [arrowhead="onormal"]
|
121
|
+
ClassComposite -> ClassComponent [arrowhead="onormal"]
|
122
|
+
|
123
|
+
ClassComposite -> ClassComponent [dir="back" arrowtail="odiamond" headlabel="*"]
|
124
|
+
}
|
125
|
+
```
|
126
|
+
|
25
127
|
### Syntax
|
26
128
|
|
27
129
|
> Note: Syntax is represented in [ABNF](https://tools.ietf.org/html/rfc5234) and are omitting spaces for clarity
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
@@ -0,0 +1,66 @@
|
|
1
|
+
digraph G {
|
2
|
+
graph [splines="ortho" rankdir="BT"]
|
3
|
+
edge [color="gray50"]
|
4
|
+
node [shape="plain"]
|
5
|
+
|
6
|
+
ClassComponent [label=<
|
7
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
8
|
+
<TR>
|
9
|
+
<TD>«abstract»<BR/><I><B>Component</B></I></TD>
|
10
|
+
</TR>
|
11
|
+
<TR>
|
12
|
+
<TD></TD>
|
13
|
+
</TR>
|
14
|
+
<TR>
|
15
|
+
<TD>
|
16
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
17
|
+
<TR><TD ALIGN="LEFT">+ operation()</TD></TR>
|
18
|
+
</TABLE>
|
19
|
+
</TD>
|
20
|
+
</TR>
|
21
|
+
</TABLE>
|
22
|
+
>]
|
23
|
+
|
24
|
+
ClassLeaf [label=<
|
25
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
26
|
+
<TR>
|
27
|
+
<TD><B>Leaf</B></TD>
|
28
|
+
</TR>
|
29
|
+
<TR>
|
30
|
+
<TD></TD>
|
31
|
+
</TR>
|
32
|
+
<TR>
|
33
|
+
<TD></TD>
|
34
|
+
</TR>
|
35
|
+
</TABLE>
|
36
|
+
>]
|
37
|
+
|
38
|
+
ClassComposite [label=<
|
39
|
+
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
|
40
|
+
<TR>
|
41
|
+
<TD><B>Composite</B></TD>
|
42
|
+
</TR>
|
43
|
+
<TR>
|
44
|
+
<TD>
|
45
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
46
|
+
<TR><TD ALIGN="LEFT"># children : Component</TD></TR>
|
47
|
+
</TABLE>
|
48
|
+
</TD>
|
49
|
+
</TR>
|
50
|
+
<TR>
|
51
|
+
<TD>
|
52
|
+
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0">
|
53
|
+
<TR><TD ALIGN="LEFT">+ addChild(child : Component) : Component</TD></TR>
|
54
|
+
<TR><TD ALIGN="LEFT">+ removeChild(child : Component) : Component</TD></TR>
|
55
|
+
<TR><TD ALIGN="LEFT">+ getChild(index : Integer) : Component</TD></TR>
|
56
|
+
</TABLE>
|
57
|
+
</TD>
|
58
|
+
</TR>
|
59
|
+
</TABLE>
|
60
|
+
>]
|
61
|
+
|
62
|
+
ClassLeaf -> ClassComponent [arrowhead="onormal"]
|
63
|
+
ClassComposite -> ClassComponent [arrowhead="onormal"]
|
64
|
+
|
65
|
+
ClassComposite -> ClassComponent [dir="back" arrowtail="odiamond" headlabel="*"]
|
66
|
+
}
|
data/lib/ucd/formatter/base.rb
CHANGED
@@ -31,6 +31,8 @@ module UCD
|
|
31
31
|
|
32
32
|
@node_attributes = Attributes.new
|
33
33
|
@node_attributes["shape"] = "plain"
|
34
|
+
|
35
|
+
@type = :dot
|
34
36
|
end
|
35
37
|
|
36
38
|
attr_reader :graph_attributes
|
@@ -40,21 +42,13 @@ module UCD
|
|
40
42
|
def type=(value)
|
41
43
|
super
|
42
44
|
|
43
|
-
@type = VALID_TYPES.include?(@type)
|
45
|
+
@type = :dot unless VALID_TYPES.include?(@type)
|
44
46
|
end
|
45
47
|
|
46
48
|
def format(node)
|
47
49
|
dot = super.lines.map(&:rstrip).join("\n")
|
48
|
-
data = generate_from_dot(dot)
|
49
|
-
|
50
|
-
if @output_path.nil?
|
51
|
-
puts data
|
52
|
-
else
|
53
|
-
self.type ||= @output_path.extname.gsub(/^\./, "")
|
54
|
-
output_path = @output_path.extname.empty? ? Pathname.new("#{@output_path}.#{@type}") : @output_path
|
55
50
|
|
56
|
-
|
57
|
-
end
|
51
|
+
generate_from_dot(dot)
|
58
52
|
end
|
59
53
|
|
60
54
|
def format_field(node)
|
@@ -181,7 +175,7 @@ HEREDOC
|
|
181
175
|
protected
|
182
176
|
|
183
177
|
def generate_from_dot(dot)
|
184
|
-
return dot if @type
|
178
|
+
return dot if @type == :dot
|
185
179
|
|
186
180
|
Open3.popen3("dot -T#{type}") do |stdin, stdout, stderr, wait|
|
187
181
|
stdin.puts(dot)
|
@@ -13,32 +13,51 @@ module UCD
|
|
13
13
|
|
14
14
|
def initialize(attributes={})
|
15
15
|
@formatter = Formatter::Graphviz.new
|
16
|
-
@verbose
|
16
|
+
@verbose = false
|
17
17
|
setup_parser
|
18
18
|
|
19
19
|
super
|
20
20
|
end
|
21
21
|
|
22
22
|
def output_path=(value)
|
23
|
-
@output_path = Pathname.new(value.to_s)
|
23
|
+
@output_path = value.is_a?(Pathname) ? value : Pathname.new(value.to_s) unless value.nil?
|
24
24
|
end
|
25
25
|
|
26
26
|
def paths=(values)
|
27
27
|
@paths = values.to_a.map { |path| Pathname.new(path) }
|
28
28
|
end
|
29
29
|
|
30
|
+
def formatter=(value)
|
31
|
+
value = value.to_s.strip.downcase.to_sym
|
32
|
+
value = Formatter.find_by_name(value)
|
33
|
+
raise Error, "Formatter not found: #{value}" if value.nil?
|
34
|
+
|
35
|
+
@formatter = value
|
36
|
+
end
|
37
|
+
|
30
38
|
def run
|
31
39
|
@option_parser.parse!
|
32
40
|
self.paths = ARGV
|
41
|
+
@formatter.type = @type
|
42
|
+
|
43
|
+
raise Error, "Output path must be a directory if multiple input files are given" if @output_path && @output_path.file? && @paths.length > 1
|
33
44
|
|
34
45
|
@paths.each do |input_path|
|
35
46
|
raise FileError, "File does not exist: #{input_path}" unless input_path.exist?
|
36
47
|
|
37
|
-
|
38
|
-
data = input_path.read
|
48
|
+
data = input_path.read
|
39
49
|
document = Parser.parse(data)
|
50
|
+
result = @formatter.format(document)
|
51
|
+
|
52
|
+
if @output_path
|
53
|
+
output_path = @output_path
|
54
|
+
output_path = output_path.join(input_path.basename(".*").to_s + ".#{@formatter.type}") if output_path.directory?
|
55
|
+
|
56
|
+
output_path.open("w+") { |file| file.write(result) }
|
57
|
+
else
|
58
|
+
puts result
|
59
|
+
end
|
40
60
|
|
41
|
-
result = @formatter.format(document)
|
42
61
|
end
|
43
62
|
end
|
44
63
|
|
@@ -82,14 +101,8 @@ module UCD
|
|
82
101
|
|
83
102
|
BANNER
|
84
103
|
|
85
|
-
parser.on("-f", "--formatter VALUE", "The output formatter (Default: '#{@formatter.name}')")
|
86
|
-
|
87
|
-
value = Formatter.find_by_name(value)
|
88
|
-
raise Error, "Formatter not found: #{value}" if value.nil?
|
89
|
-
|
90
|
-
@formatter = value
|
91
|
-
end
|
92
|
-
parser.on("-t", "--type VALUE", "The output format type") { |value| @formatter.type = value }
|
104
|
+
parser.on("-f", "--formatter VALUE", "The output formatter (Default: '#{@formatter.name}')") { |value| self.formatter = value }
|
105
|
+
parser.on("-t", "--type VALUE", "The output format type") { |value| @type = value }
|
93
106
|
parser.on("-o", "--output VALUE", "The output path") { |value| self.output_path = value }
|
94
107
|
parser.on("-h", "--help", "Prints this help") do
|
95
108
|
puts parser
|
@@ -103,9 +116,7 @@ module UCD
|
|
103
116
|
|
104
117
|
The output can be directed to a path with #{text_bold_italic("--output")}, which can be a file or a directory.
|
105
118
|
If the output path is a directory, then the filename will be the same as the input filename,
|
106
|
-
|
107
|
-
If the output path is a file when multiple input files are given, the current input file index is appended
|
108
|
-
to the output filename.
|
119
|
+
with it's file extension substituted with the #{text_bold_italic("--type")}.
|
109
120
|
|
110
121
|
#{text_underline("Examples")}
|
111
122
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ucd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Scott Lewis
|
@@ -102,6 +102,7 @@ files:
|
|
102
102
|
- bin/console
|
103
103
|
- bin/setup
|
104
104
|
- examples/composite - minimal.ucd
|
105
|
+
- examples/composite.dot
|
105
106
|
- examples/composite.png
|
106
107
|
- examples/composite.ucd
|
107
108
|
- exe/ucd
|