spacetree 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Changelog +2 -0
- data/LICENSE +20 -0
- data/README.md +39 -0
- data/Rakefile +13 -0
- data/lib/spacetree.rb +22 -0
- data/lib/spacetree/node.rb +59 -0
- data/lib/spacetree/parser.rb +44 -0
- data/test/helper.rb +13 -0
- data/test/test_node.rb +58 -0
- data/test/test_parser.rb +78 -0
- metadata +68 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e1ec12ace1a11f7639558f401ffb4c2169978ae0
|
4
|
+
data.tar.gz: 0281ff038ee6bed1dd0f1e6349aa196905d8b71d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 34f9c9a26e16ca0113c6069968af7ef1373bc1c6d2e7154fe1374a4b652a30551c5f519428f1dd081602ed1f59fb96e631f4a646cc262341d07b2f4cddeb163c
|
7
|
+
data.tar.gz: a795c3716be4b02facd945fcee59c7802cf4aa09ebf1a6f6379649554429eac4c3b56a3b3bf71108c4472fbab63d97515896ced02a389066a46b5a36fd082e78
|
data/Changelog
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2016 Jan Friedrich
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
spacetree
|
2
|
+
=========
|
3
|
+
|
4
|
+
A Ruby library to generate a tree structure from a text file indented by spaces.
|
5
|
+
|
6
|
+
Example
|
7
|
+
-------
|
8
|
+
|
9
|
+
Given a text file tree.txt
|
10
|
+
|
11
|
+
foo
|
12
|
+
bar
|
13
|
+
baz
|
14
|
+
|
15
|
+
Parsing it:
|
16
|
+
|
17
|
+
require 'spacetree'
|
18
|
+
parser = Spacetree::Parser.new
|
19
|
+
tree = parser.parse File.read('tree.txt')
|
20
|
+
p tree.value # => "foo"
|
21
|
+
p tree.map(&:value) # => ["bar", "baz"]
|
22
|
+
|
23
|
+
Emitting a tree as indented text:
|
24
|
+
|
25
|
+
puts tree.emit
|
26
|
+
|
27
|
+
or simple
|
28
|
+
|
29
|
+
puts tree
|
30
|
+
|
31
|
+
Author
|
32
|
+
------
|
33
|
+
|
34
|
+
Jan Friedrich <janfri26@gmail.com>
|
35
|
+
|
36
|
+
License
|
37
|
+
-------
|
38
|
+
|
39
|
+
MIT license see file LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rim/tire'
|
2
|
+
require 'rim/version'
|
3
|
+
require_relative 'lib/spacetree'
|
4
|
+
|
5
|
+
Rim.setup do
|
6
|
+
name 'spacetree'
|
7
|
+
authors 'Jan Friedrich'
|
8
|
+
email 'janfri26@gmail.com'
|
9
|
+
license 'MIT'
|
10
|
+
summary 'Generate a tree structure from a text file indented by spaces.'
|
11
|
+
version Spacetree::VERSION
|
12
|
+
end
|
13
|
+
|
data/lib/spacetree.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -- encoding: utf-8 --
|
2
|
+
# Generate a tree structure from a text file indented by spaces.
|
3
|
+
module Spacetree
|
4
|
+
|
5
|
+
VERSION = '1.0.0'
|
6
|
+
|
7
|
+
autoload :Node, 'spacetree/node'
|
8
|
+
autoload :Parser, 'spacetree/parser'
|
9
|
+
|
10
|
+
# Do parsing @see Parser#parse
|
11
|
+
def self.parse s, &blk
|
12
|
+
Parser.new.parse s, &blk
|
13
|
+
end
|
14
|
+
|
15
|
+
# Generate a formatted string representation of a node and its children
|
16
|
+
# recursively
|
17
|
+
# @see Node#emit
|
18
|
+
def self.emit node
|
19
|
+
node.emit
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# -- encoding: utf-8 --
|
2
|
+
module Spacetree
|
3
|
+
|
4
|
+
# Represent a node respectively a tree
|
5
|
+
class Node
|
6
|
+
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attr_accessor :value, :children
|
10
|
+
|
11
|
+
# @param value value of the node
|
12
|
+
# @children array of nodes wich represent the children of this node
|
13
|
+
def initialize value=nil, *children
|
14
|
+
@value = value
|
15
|
+
@children = children
|
16
|
+
end
|
17
|
+
|
18
|
+
def == o
|
19
|
+
return false unless o.kind_of? Node
|
20
|
+
[self.value, self.children] == [o.value, o.children]
|
21
|
+
end
|
22
|
+
|
23
|
+
def each *args, &blk
|
24
|
+
enum = Enumerator.new do |y|
|
25
|
+
y << self
|
26
|
+
children.each do |c|
|
27
|
+
c.each *args, &blk
|
28
|
+
end
|
29
|
+
end
|
30
|
+
if block_given?
|
31
|
+
enum.each *args, &blk
|
32
|
+
else
|
33
|
+
enum
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Generate a formatted string representation of a node and its children
|
38
|
+
# recursively
|
39
|
+
# @param indent Count of spaces to indent a level deeper
|
40
|
+
# @param level level of indentation
|
41
|
+
def emit indent: 2, level: 0
|
42
|
+
res = []
|
43
|
+
if value.nil?
|
44
|
+
children.each {|c| res << c.emit(indent: indent, level: level)}
|
45
|
+
else
|
46
|
+
spaces = ' ' * indent * level
|
47
|
+
res << (spaces << value.to_s)
|
48
|
+
children.each {|c| res << c.emit(indent: indent, level: level+1)}
|
49
|
+
end
|
50
|
+
res.join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
emit
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -- encoding: utf-8 --
|
2
|
+
module Spacetree
|
3
|
+
|
4
|
+
# Parser to parse a text file indented by spaces to a tree structure
|
5
|
+
class Parser
|
6
|
+
|
7
|
+
# Do parsing
|
8
|
+
# @s String to parse
|
9
|
+
# @blk if block given each line without the starting spaces is yielded
|
10
|
+
def parse s, &blk
|
11
|
+
root = Node.new
|
12
|
+
@indent_map = {-1 => root}
|
13
|
+
s.chomp.split(/\n/).each do |line|
|
14
|
+
generate_node line, &blk
|
15
|
+
end
|
16
|
+
root
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def generate_node line
|
22
|
+
if line =~ /(^ *)([^ ].*)$/
|
23
|
+
indent = $1.size
|
24
|
+
line = $2
|
25
|
+
line = yield line if block_given?
|
26
|
+
parent = search_parent_node indent
|
27
|
+
new_node = Node.new line
|
28
|
+
@indent_map[indent] = new_node
|
29
|
+
parent.children << new_node
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def search_parent_node indent
|
34
|
+
fail ArgumentError if indent < 0
|
35
|
+
(indent - 1).downto(-1).each do |i|
|
36
|
+
res = @indent_map[i]
|
37
|
+
return res if res
|
38
|
+
end
|
39
|
+
fail ArgumentError
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
data/test/helper.rb
ADDED
data/test/test_node.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# -- encoding: utf-8 --
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
class TestNode < Minitest::Test
|
5
|
+
|
6
|
+
include Helper
|
7
|
+
|
8
|
+
FOO_BAR_BAZ_TREE_STRING = <<~END.chomp
|
9
|
+
foo1
|
10
|
+
foo2
|
11
|
+
foo3
|
12
|
+
bar1
|
13
|
+
bar2
|
14
|
+
bar3
|
15
|
+
baz1
|
16
|
+
baz2
|
17
|
+
baz3
|
18
|
+
END
|
19
|
+
|
20
|
+
def test_enumerable
|
21
|
+
arr = [nil, 'foo1', 'foo2', 'foo3', 'bar1', 'bar2', 'bar3', 'baz1', 'baz2', 'baz3']
|
22
|
+
res = foo_bar_baz_tree.map &:value
|
23
|
+
assert_equal arr, res
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_emit_one_node
|
27
|
+
assert_equal '', n(nil).emit
|
28
|
+
assert_equal 'foo', n('foo').emit
|
29
|
+
assert_equal ' foo', n('foo').emit(level: 1)
|
30
|
+
assert_equal ' foo', n('foo').emit(level: 2)
|
31
|
+
assert_equal ' foo', n('foo').emit(indent: 3, level: 1)
|
32
|
+
assert_equal ' foo', n('foo').emit(indent: 3, level: 2)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_complex_emit
|
36
|
+
assert_equal FOO_BAR_BAZ_TREE_STRING, foo_bar_baz_tree.emit
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_emit_argumenterror_for_negative_arguments
|
40
|
+
assert_raises ArgumentError do
|
41
|
+
n('foo').emit(indent: -1)
|
42
|
+
end
|
43
|
+
assert_raises ArgumentError do
|
44
|
+
n('foo').emit(level: -1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_to_s
|
49
|
+
assert_equal FOO_BAR_BAZ_TREE_STRING, foo_bar_baz_tree.emit
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
def foo_bar_baz_tree
|
55
|
+
n(nil, n('foo1', n('foo2', n('foo3'))), n('bar1', n('bar2', n('bar3'))), n('baz1', n('baz2', n('baz3'))))
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/test/test_parser.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# -- encoding: utf-8 --
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
class TestParser < Minitest::Test
|
5
|
+
|
6
|
+
include Helper
|
7
|
+
include Spacetree
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@parser = Parser.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_empty_string
|
14
|
+
assert_equal n, @parser.parse('')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_one_node
|
18
|
+
assert_equal n(nil, n('foo')), @parser.parse('foo')
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_more_nodes
|
22
|
+
tree = n(nil, n('foo'), n('bar'), n('baz'))
|
23
|
+
s = <<~END
|
24
|
+
foo
|
25
|
+
bar
|
26
|
+
baz
|
27
|
+
END
|
28
|
+
assert_equal tree, @parser.parse(s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_simple_indentation
|
32
|
+
tree = n(nil, n('foo', n('bar')))
|
33
|
+
s = <<~END
|
34
|
+
foo
|
35
|
+
bar
|
36
|
+
END
|
37
|
+
assert_equal tree, @parser.parse(s)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_usual_indentation
|
41
|
+
tree = n(nil, n('foo1', n('foo2', n('foo3'))), n('bar1', n('bar2', n('bar3'))), n('baz1', n('baz2', n('baz3'))))
|
42
|
+
s = <<~END
|
43
|
+
foo1
|
44
|
+
foo2
|
45
|
+
foo3
|
46
|
+
bar1
|
47
|
+
bar2
|
48
|
+
bar3
|
49
|
+
baz1
|
50
|
+
baz2
|
51
|
+
baz3
|
52
|
+
END
|
53
|
+
assert_equal tree, @parser.parse(s)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_spaces_in_line
|
57
|
+
tree = n(nil, n('foo and bar', n('bar and baz', n('baz and foo'))))
|
58
|
+
s = <<~END
|
59
|
+
foo and bar
|
60
|
+
bar and baz
|
61
|
+
baz and foo
|
62
|
+
END
|
63
|
+
assert_equal tree, @parser.parse(s)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_converting_line
|
67
|
+
tree = n(nil, n(%i(foo bar)), n(%i(bar baz)))
|
68
|
+
s = <<~END
|
69
|
+
foo bar
|
70
|
+
bar baz
|
71
|
+
END
|
72
|
+
res = @parser.parse(s) do |line|
|
73
|
+
line.split.map &:to_sym
|
74
|
+
end
|
75
|
+
assert_equal tree, res
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spacetree
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Friedrich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rim
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.6'
|
27
|
+
description: ''
|
28
|
+
email: janfri26@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- Changelog
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- Rakefile
|
37
|
+
- lib/spacetree.rb
|
38
|
+
- lib/spacetree/node.rb
|
39
|
+
- lib/spacetree/parser.rb
|
40
|
+
- test/helper.rb
|
41
|
+
- test/test_node.rb
|
42
|
+
- test/test_parser.rb
|
43
|
+
homepage:
|
44
|
+
licenses:
|
45
|
+
- MIT
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.6.4
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Generate a tree structure from a text file indented by spaces.
|
67
|
+
test_files: []
|
68
|
+
has_rdoc:
|