ascii_tree 1.0.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -3
- data/lib/ascii_tree/comment_stripper.rb +0 -2
- data/lib/ascii_tree/coordinate.rb +12 -11
- data/lib/ascii_tree/edge.rb +15 -15
- data/lib/ascii_tree/edge_parser.rb +0 -2
- data/lib/ascii_tree/node.rb +4 -6
- data/lib/ascii_tree/node_builder.rb +2 -8
- data/lib/ascii_tree/parenthesis_toggle.rb +2 -3
- data/lib/ascii_tree/relationship.rb +0 -2
- data/lib/ascii_tree/relationships_builder.rb +17 -19
- data/lib/ascii_tree/scanner.rb +0 -2
- data/lib/ascii_tree/word.rb +4 -6
- data/lib/ascii_tree/word_parser.rb +7 -11
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 727377cc812889ffd5a12fe02510d31fd8c60046
|
4
|
+
data.tar.gz: 51e1abce380f5c8a587be253e0494d973faecb76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b7032761679fa3c2c9f63647da68e1d284e5b576b99c88539509f715061c012157ff3ed677b02948bd6bbf7e2f3e00a451ebd4cb8cd855d708c97a1d581bd17
|
7
|
+
data.tar.gz: 9d19f645ed89eaa27ad43ad89c7ba550211c2de2cf4da9d561c547620f996af5bd9039bd5b84bbd35af971045b9ce2cdaacf00e8cb3316ea3541fcd390a15b22
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
## Ascii Tree
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/tuzz/ascii_tree.svg?branch=master)](https://travis-ci.org/tuzz/ascii_tree)
|
4
|
+
|
3
5
|
Parses a usable tree from ASCII art.
|
4
6
|
|
5
7
|
Ascii Tree turns something humans understand into something computers
|
@@ -24,14 +26,14 @@ root = AsciiTree.parse('
|
|
24
26
|
|
25
27
|
')
|
26
28
|
|
27
|
-
root.
|
29
|
+
root.identity
|
28
30
|
#=> "chestnuts"
|
29
31
|
|
30
32
|
root.parent
|
31
33
|
#=> nil
|
32
34
|
|
33
35
|
root.children
|
34
|
-
#=> [#<AsciiTree::Node @
|
36
|
+
#=> [#<AsciiTree::Node @identity="roasting">, ...]
|
35
37
|
```
|
36
38
|
|
37
39
|
## Multiple words
|
@@ -47,7 +49,7 @@ root = AsciiTree.parse('
|
|
47
49
|
|
48
50
|
')
|
49
51
|
|
50
|
-
root.
|
52
|
+
root.identity
|
51
53
|
#=> "single node"
|
52
54
|
```
|
53
55
|
|
@@ -1,13 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
module AsciiTree
|
2
|
+
class Coordinate
|
3
|
+
attr_reader :x, :y
|
4
|
+
|
5
|
+
def initialize(x:, y:)
|
6
|
+
@x = x
|
7
|
+
@y = y
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(other)
|
11
|
+
x == other.x && y == other.y
|
12
|
+
end
|
7
13
|
end
|
8
|
-
|
9
|
-
def ==(other)
|
10
|
-
x == other.x && y == other.y
|
11
|
-
end
|
12
|
-
|
13
14
|
end
|
data/lib/ascii_tree/edge.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
|
1
|
+
module AsciiTree
|
2
|
+
class Edge
|
3
|
+
attr_reader :character, :coordinate, :parent_coordinate, :child_coordinate
|
2
4
|
|
3
|
-
|
5
|
+
def initialize(character:, coordinate:, parent_coordinate:, child_coordinate:)
|
6
|
+
@character = character
|
7
|
+
@coordinate = coordinate
|
8
|
+
@parent_coordinate = parent_coordinate
|
9
|
+
@child_coordinate = child_coordinate
|
10
|
+
end
|
4
11
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
def ==(other)
|
13
|
+
character == other.character &&
|
14
|
+
coordinate == other.coordinate &&
|
15
|
+
parent_coordinate == other.parent_coordinate &&
|
16
|
+
child_coordinate == other.child_coordinate
|
17
|
+
end
|
10
18
|
end
|
11
|
-
|
12
|
-
def ==(other)
|
13
|
-
character == other.character &&
|
14
|
-
coordinate == other.coordinate &&
|
15
|
-
parent_coordinate == other.parent_coordinate &&
|
16
|
-
child_coordinate == other.child_coordinate
|
17
|
-
end
|
18
|
-
|
19
19
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
module EdgeParser
|
3
3
|
class << self
|
4
|
-
|
5
4
|
def parse(string)
|
6
5
|
edge_chars_with_coordinates(string).map do |char, coordinate|
|
7
6
|
offsets = edge_offsets[char]
|
@@ -36,7 +35,6 @@ module AsciiTree
|
|
36
35
|
edge_offsets.keys.include?(char)
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
data/lib/ascii_tree/node.rb
CHANGED
@@ -1,21 +1,19 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
class Node
|
3
|
+
attr_reader :identity, :value, :parent, :children
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(id:, value:, parent:, children:)
|
7
|
-
@id = id
|
5
|
+
def initialize(identity:, value:, parent:, children:)
|
6
|
+
@identity = identity
|
8
7
|
@value = value
|
9
8
|
@parent = parent
|
10
9
|
@children = children
|
11
10
|
end
|
12
11
|
|
13
12
|
def ==(other)
|
14
|
-
|
13
|
+
identity == other.identity &&
|
15
14
|
value == other.value &&
|
16
15
|
parent == other.parent &&
|
17
16
|
children == other.children
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
class NodeBuilder
|
3
|
-
|
4
3
|
def self.build(*args)
|
5
4
|
new(*args).build
|
6
5
|
end
|
@@ -10,11 +9,7 @@ module AsciiTree
|
|
10
9
|
end
|
11
10
|
|
12
11
|
def build
|
13
|
-
if relationships.any?
|
14
|
-
build_for(root_word, nil)
|
15
|
-
else
|
16
|
-
nil
|
17
|
-
end
|
12
|
+
build_for(root_word, nil) if relationships.any?
|
18
13
|
end
|
19
14
|
|
20
15
|
private
|
@@ -31,7 +26,7 @@ module AsciiTree
|
|
31
26
|
|
32
27
|
def build_for(word, parent)
|
33
28
|
node = Node.new(
|
34
|
-
|
29
|
+
identity: word.identity,
|
35
30
|
value: word.value,
|
36
31
|
parent: parent,
|
37
32
|
children: []
|
@@ -53,6 +48,5 @@ module AsciiTree
|
|
53
48
|
build_for(r.child_word, parent)
|
54
49
|
end
|
55
50
|
end
|
56
|
-
|
57
51
|
end
|
58
52
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
class Relationship
|
3
|
-
|
4
3
|
attr_reader :parent_word, :edge, :child_word
|
5
4
|
|
6
5
|
def initialize(parent_word:, edge:, child_word:)
|
@@ -14,6 +13,5 @@ module AsciiTree
|
|
14
13
|
edge == other.edge &&
|
15
14
|
child_word == other.child_word
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
17
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
module RelationshipsBuilder
|
3
3
|
class << self
|
4
|
-
|
5
4
|
def build(words, edges)
|
6
5
|
relationships = []
|
7
6
|
|
@@ -24,27 +23,26 @@ module AsciiTree
|
|
24
23
|
private
|
25
24
|
|
26
25
|
def root_relationship(words)
|
27
|
-
|
26
|
+
return unless words.any?
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
end
|
28
|
+
root_word = words.first
|
29
|
+
Relationship.new(parent_word: nil, edge: nil, child_word: root_word)
|
32
30
|
end
|
33
31
|
|
34
32
|
def validate_presence(parent, child, edge)
|
35
33
|
if parent.nil? && child.nil?
|
36
34
|
error = "No parent or child"
|
37
35
|
elsif parent.nil?
|
38
|
-
error = "No parent for child '#{child.
|
36
|
+
error = "No parent for child '#{child.identity}'"
|
39
37
|
elsif child.nil?
|
40
|
-
error = "No child for parent '#{parent.
|
38
|
+
error = "No child for parent '#{parent.identity}'"
|
41
39
|
end
|
42
40
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
41
|
+
return unless error
|
42
|
+
|
43
|
+
c = edge.coordinate
|
44
|
+
error += " for edge '#{edge.character}' at line #{c.y}, column #{c.x}"
|
45
|
+
fail ::AsciiTree::RelationshipError, error
|
48
46
|
end
|
49
47
|
|
50
48
|
def validate_one_parent(relationships)
|
@@ -56,11 +54,11 @@ module AsciiTree
|
|
56
54
|
count > 1
|
57
55
|
end
|
58
56
|
|
59
|
-
groups = multiple_parents.group_by
|
57
|
+
groups = multiple_parents.group_by(&:child_word)
|
60
58
|
|
61
|
-
maps = groups.map do |child_word,
|
62
|
-
parent_words =
|
63
|
-
[child_word.
|
59
|
+
maps = groups.map do |child_word, rels|
|
60
|
+
parent_words = rels.map(&:parent_word)
|
61
|
+
[child_word.identity, parent_words.map(&:identity)]
|
64
62
|
end
|
65
63
|
|
66
64
|
if maps.any?
|
@@ -72,10 +70,10 @@ module AsciiTree
|
|
72
70
|
end
|
73
71
|
end
|
74
72
|
|
75
|
-
|
73
|
+
fail ::AsciiTree::RelationshipError, error if error
|
76
74
|
end
|
77
|
-
|
78
|
-
class ::AsciiTree::RelationshipError < StandardError; end
|
79
75
|
end
|
80
76
|
end
|
77
|
+
|
78
|
+
class RelationshipError < StandardError; end
|
81
79
|
end
|
data/lib/ascii_tree/scanner.rb
CHANGED
data/lib/ascii_tree/word.rb
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
class Word
|
3
|
+
attr_reader :identity, :value, :start_coordinate, :end_coordinate
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(id:, value:, start_coordinate:, end_coordinate:)
|
7
|
-
@id = id
|
5
|
+
def initialize(identity:, value:, start_coordinate:, end_coordinate:)
|
6
|
+
@identity = identity
|
8
7
|
@value = value
|
9
8
|
@start_coordinate = start_coordinate
|
10
9
|
@end_coordinate = end_coordinate
|
11
10
|
end
|
12
11
|
|
13
12
|
def ==(other)
|
14
|
-
|
13
|
+
identity == other.identity &&
|
15
14
|
value == other.value &&
|
16
15
|
start_coordinate == other.start_coordinate &&
|
17
16
|
end_coordinate == other.end_coordinate
|
@@ -30,6 +29,5 @@ module AsciiTree
|
|
30
29
|
def inside?(x)
|
31
30
|
(start_coordinate.x..end_coordinate.x).include?(x)
|
32
31
|
end
|
33
|
-
|
34
32
|
end
|
35
33
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module AsciiTree
|
2
2
|
module WordParser
|
3
3
|
class << self
|
4
|
-
|
5
4
|
def parse(string)
|
6
5
|
chars = word_chars_with_coordinates(string)
|
7
6
|
group_contiguous(chars).map do |word_with_coords|
|
8
|
-
|
7
|
+
identity, value = identity_value(word_with_coords)
|
9
8
|
|
10
9
|
Word.new(
|
11
|
-
|
10
|
+
identity: identity.strip,
|
12
11
|
value: value,
|
13
12
|
start_coordinate: word_with_coords.first.last,
|
14
13
|
end_coordinate: word_with_coords.last.last
|
@@ -21,7 +20,7 @@ module AsciiTree
|
|
21
20
|
def word_chars_with_coordinates(string)
|
22
21
|
toggle = ParenthesisToggle.new
|
23
22
|
|
24
|
-
Scanner.scan(string).reject do |char,
|
23
|
+
Scanner.scan(string).reject do |char, _coordinate|
|
25
24
|
toggle.read(char)
|
26
25
|
toggle.off? && (edge?(char) || whitespace?(char))
|
27
26
|
end
|
@@ -35,7 +34,7 @@ module AsciiTree
|
|
35
34
|
char.match(/\s/)
|
36
35
|
end
|
37
36
|
|
38
|
-
def
|
37
|
+
def identity_value(word_with_coords)
|
39
38
|
chars = word_with_coords.map(&:first)
|
40
39
|
chars = remove_parentheses(chars)
|
41
40
|
|
@@ -43,10 +42,10 @@ module AsciiTree
|
|
43
42
|
word.strip!
|
44
43
|
|
45
44
|
if word.end_with?("}")
|
46
|
-
|
45
|
+
identity, tail = word.split("{", 2)
|
47
46
|
expression = tail[0..-2]
|
48
47
|
value = eval(expression)
|
49
|
-
[
|
48
|
+
[identity, value]
|
50
49
|
else
|
51
50
|
[word, nil]
|
52
51
|
end
|
@@ -61,7 +60,7 @@ module AsciiTree
|
|
61
60
|
end
|
62
61
|
|
63
62
|
def group_contiguous(chars)
|
64
|
-
chars.
|
63
|
+
chars.each_with_object([]) do |(char, coord), array|
|
65
64
|
prev = previous_coordinate(array)
|
66
65
|
|
67
66
|
if contigous?(prev, coord)
|
@@ -69,8 +68,6 @@ module AsciiTree
|
|
69
68
|
else
|
70
69
|
array << [[char, coord]]
|
71
70
|
end
|
72
|
-
|
73
|
-
array
|
74
71
|
end
|
75
72
|
end
|
76
73
|
|
@@ -85,7 +82,6 @@ module AsciiTree
|
|
85
82
|
previous_coordinate.y == coordinate.y &&
|
86
83
|
previous_coordinate.x == coordinate.x - 1
|
87
84
|
end
|
88
|
-
|
89
85
|
end
|
90
86
|
end
|
91
87
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ascii_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Patuzzo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,6 +24,34 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
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.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.31'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.31'
|
27
55
|
description: Parses a usable tree from ASCII art.
|
28
56
|
email: chris@patuzzo.co.uk
|
29
57
|
executables: []
|