term_utils 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/COPYING +3 -3
- data/README.md +7 -1
- data/doc/TermUtils/AP/Article.html +991 -0
- data/doc/TermUtils/AP/Element.html +1025 -0
- data/doc/TermUtils/AP/Flag.html +539 -0
- data/doc/TermUtils/AP/Level.html +638 -0
- data/doc/TermUtils/AP/NoSuchValueError.html +217 -0
- data/doc/TermUtils/AP/Parameter.html +804 -0
- data/doc/TermUtils/AP/ParseError.html +217 -0
- data/doc/TermUtils/AP/Parser.html +572 -0
- data/doc/TermUtils/AP/Result.html +1029 -0
- data/doc/TermUtils/AP/ResultView.html +597 -0
- data/doc/TermUtils/AP/Syntax.html +1051 -0
- data/doc/TermUtils/AP/SyntaxError.html +217 -0
- data/doc/TermUtils/AP.html +505 -0
- data/doc/TermUtils/FF/Config.html +1 -1
- data/doc/TermUtils/FF/Cursor/Context.html +1 -1
- data/doc/TermUtils/FF/Cursor.html +1 -1
- data/doc/TermUtils/FF/Query.html +1 -1
- data/doc/TermUtils/FF.html +1 -1
- data/doc/TermUtils/PropertyTreeNode.html +1999 -0
- data/doc/TermUtils/Tab/Column.html +1 -1
- data/doc/TermUtils/Tab/Holder.html +1 -1
- data/doc/TermUtils/Tab/Printer.html +1 -1
- data/doc/TermUtils/Tab/Table.html +1 -1
- data/doc/TermUtils/Tab.html +1 -1
- data/doc/TermUtils.html +5 -3
- data/doc/_index.html +143 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +8 -2
- data/doc/index.html +8 -2
- data/doc/method_list.html +638 -22
- data/doc/top-level-namespace.html +1 -1
- data/lib/term_utils/ap/article.rb +68 -0
- data/lib/term_utils/ap/element.rb +78 -0
- data/lib/term_utils/ap/flag.rb +48 -0
- data/lib/term_utils/ap/level.rb +57 -0
- data/lib/term_utils/ap/no_such_value_error.rb +27 -0
- data/lib/term_utils/ap/parameter.rb +75 -0
- data/lib/term_utils/ap/parse_error.rb +27 -0
- data/lib/term_utils/ap/parser.rb +185 -0
- data/lib/term_utils/ap/result.rb +175 -0
- data/lib/term_utils/ap/syntax.rb +112 -0
- data/lib/term_utils/ap/syntax_error.rb +27 -0
- data/lib/term_utils/ap.rb +59 -0
- data/lib/term_utils/property_tree_node.rb +200 -0
- data/lib/term_utils.rb +1 -0
- data/term_utils.gemspec +2 -2
- metadata +29 -2
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents an argument parsing Result.
|
21
|
+
class Result
|
22
|
+
# @return [TermUtils::PropertyTreeNode]
|
23
|
+
attr_accessor :value
|
24
|
+
# Constructs a new Result.
|
25
|
+
# @param syntax [Darn::AP::Syntax] Syntax.
|
26
|
+
# @param element [Darn::AP::Element] Optional Element.
|
27
|
+
# @param value [Darn::PropertyTreeNode] Optional value.
|
28
|
+
def initialize(syntax, element = nil, value = nil)
|
29
|
+
@syntax = syntax.dup
|
30
|
+
@element = element ? element.dup : nil
|
31
|
+
if value
|
32
|
+
@value = value.dup
|
33
|
+
@value.key = nil
|
34
|
+
else
|
35
|
+
@value = TermUtils::PropertyTreeNode.new
|
36
|
+
end
|
37
|
+
end
|
38
|
+
# Tests whether a given level/parameter/article is present in the result value.
|
39
|
+
# @param id [Symbol, Array<Symbol>]
|
40
|
+
# @return [Boolean]
|
41
|
+
def present?(id)
|
42
|
+
if id.is_a? Symbol
|
43
|
+
!!@value.child_node(id)
|
44
|
+
elsif id.is_a? Array
|
45
|
+
@value.node_exists?(id)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
# Evaluates the number of occurrences of a given level, parameter or article.
|
49
|
+
# @param id [Symbol, Array<Symbol>]
|
50
|
+
# @return [Integer]
|
51
|
+
def eval_occurs(id)
|
52
|
+
id = [id] if id.is_a? Symbol
|
53
|
+
obj = fetch_syntax_object(id)
|
54
|
+
raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
|
55
|
+
node = @value.find_node(id)
|
56
|
+
return 0 unless node
|
57
|
+
return 1 if obj.occur_bounded? && (obj.max_occurs == 1)
|
58
|
+
# Parameter is multiple.
|
59
|
+
node.child_nodes ? node.child_nodes.length : 0
|
60
|
+
end
|
61
|
+
# Fetches a value.
|
62
|
+
# @param id [Symbol, Array<Symbol>, nil]
|
63
|
+
# @param opts [Hash] `:index`, `:multi`.
|
64
|
+
# @option opts [Integer] :index The index of a multiple-occurrence level/parameter/article.
|
65
|
+
# @option opts [Boolean] :multi Whether an array of values shall be returned instead of a single value.
|
66
|
+
# @return [Object]
|
67
|
+
# @raise [TermUtils::AP::NoSuchValueError]
|
68
|
+
def fetch_value(id, opts = {})
|
69
|
+
index = opts.fetch(:index, nil)
|
70
|
+
multi = opts.fetch(:multi, false)
|
71
|
+
unless id
|
72
|
+
node = @value
|
73
|
+
if node && node.child_nodes && index
|
74
|
+
node = node.child_node(index)
|
75
|
+
end
|
76
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" unless node
|
77
|
+
vals = node.collect_values
|
78
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
|
79
|
+
return multi ? vals : vals.first
|
80
|
+
end
|
81
|
+
id = [id] if id.is_a? Symbol
|
82
|
+
obj = fetch_syntax_object(id)
|
83
|
+
raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
|
84
|
+
node = @value.find_node(id)
|
85
|
+
if node && node.child_nodes && index
|
86
|
+
node = node.child_node(index)
|
87
|
+
end
|
88
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" unless node
|
89
|
+
catch :value do
|
90
|
+
if obj.is_a? TermUtils::AP::Parameter
|
91
|
+
raise TermUtils::AP::NoSuchValueError, "parameter has no article" if obj.articles.empty?
|
92
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" if node.leaf?
|
93
|
+
vals = node.collect_values
|
94
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
|
95
|
+
if multi
|
96
|
+
throw :value, vals
|
97
|
+
else
|
98
|
+
throw :value, vals.first
|
99
|
+
end
|
100
|
+
elsif obj.is_a? TermUtils::AP::Article
|
101
|
+
# raise TermUtils::AP::NoSuchValueError, "no such value" if node.leaf?
|
102
|
+
vals = node.collect_values
|
103
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
|
104
|
+
if multi
|
105
|
+
throw :value, vals
|
106
|
+
else
|
107
|
+
throw :value, vals.first
|
108
|
+
end
|
109
|
+
end
|
110
|
+
raise TermUtils::AP::NoSuchValueError, "wrong id"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
# Shifts this one.
|
114
|
+
# @param id [Symbol, Array<Symbol>]
|
115
|
+
# @param opts [Hash] `:index`, `:multi`.
|
116
|
+
# @option opts [Integer] :index The index of a multiple-occurrence level/parameter/article.
|
117
|
+
# @return [TermUtils::AP::Result]
|
118
|
+
# @raise [TermUtils::AP::NoSuchValueError]
|
119
|
+
def shift(id, opts = {})
|
120
|
+
index = opts.fetch(:index, nil)
|
121
|
+
id = [id] if id.is_a? Symbol
|
122
|
+
obj = fetch_syntax_object(id)
|
123
|
+
raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
|
124
|
+
node = @value.find_node(id)
|
125
|
+
if node && node.child_nodes && index
|
126
|
+
node = node.child_node(index)
|
127
|
+
end
|
128
|
+
raise TermUtils::AP::NoSuchValueError, "no such value" unless node
|
129
|
+
catch :value do
|
130
|
+
if obj.is_a? TermUtils::AP::Level
|
131
|
+
throw :value, TermUtils::AP::Result.new(obj.syntax, nil, node)
|
132
|
+
elsif obj.is_a? TermUtils::AP::Parameter
|
133
|
+
throw :value, TermUtils::AP::Result.new(@syntax, obj, node)
|
134
|
+
elsif obj.is_a? TermUtils::AP::Article
|
135
|
+
throw :value, TermUtils::AP::Result.new(@syntax, obj, node)
|
136
|
+
end
|
137
|
+
raise TermUtils::AP::NoSuchValueError, "wrong id"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
private
|
141
|
+
# Fetches a given syntax object.
|
142
|
+
# @param id_path [Array<Symbol>]
|
143
|
+
# @return [TermUtils::AP::Level, TermUtils::AP::Parameter, TermUtils::AP::Article, nil]
|
144
|
+
def fetch_syntax_object(id_path)
|
145
|
+
id = id_path.dup
|
146
|
+
id = [@element.id].concat(id) if @element
|
147
|
+
catch :done do
|
148
|
+
fetch_syntax_object0(@syntax, id)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
# Fetches a given syntax object.
|
152
|
+
# @param syntax [TermUtils::AP::Syntax]
|
153
|
+
# @param id_path [Array<Symbol>]
|
154
|
+
# @return [TermUtils::AP::Level, TermUtils::AP::Parameter, TermUtils::AP::Article, nil]
|
155
|
+
def fetch_syntax_object0(syntax, id_path)
|
156
|
+
id = id_path.shift
|
157
|
+
syntax.elements.each do |e|
|
158
|
+
next unless e.id == id
|
159
|
+
throw :done, e if id_path.empty?
|
160
|
+
if e.is_a? TermUtils::AP::Level
|
161
|
+
fetch_syntax_object0(e.syntax, id_path)
|
162
|
+
elsif e.is_a? TermUtils::AP::Parameter
|
163
|
+
throw :done if id_path.empty?
|
164
|
+
id = id_path.shift
|
165
|
+
throw :done unless id_path.empty?
|
166
|
+
e.articles.each do |a|
|
167
|
+
throw :done, a if a.id = id
|
168
|
+
end
|
169
|
+
throw :done
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents the argument list syntax. It holds a list of parameters and
|
21
|
+
# levels.
|
22
|
+
class Syntax
|
23
|
+
# @return [Array<TermUtils::AP::Element>]
|
24
|
+
attr_accessor :elements
|
25
|
+
# Constructs a new Syntax.
|
26
|
+
def initialize
|
27
|
+
@elements = []
|
28
|
+
end
|
29
|
+
# For dup method.
|
30
|
+
def initialize_dup(other)
|
31
|
+
if other.elements
|
32
|
+
@elements = []
|
33
|
+
other.elements.each do |e|
|
34
|
+
@elements << e.dup
|
35
|
+
end
|
36
|
+
end
|
37
|
+
super
|
38
|
+
end
|
39
|
+
# Finalizes this one. Internal use.
|
40
|
+
# @return [nil]
|
41
|
+
def finalize!(opts = {})
|
42
|
+
opts[:anonymous] = 0 unless opts.has_key? :anonymous
|
43
|
+
@elements.each { |e| e.finalize!(opts) }
|
44
|
+
end
|
45
|
+
# Creates and adds a new Parameter.
|
46
|
+
# @param opts [Hash]
|
47
|
+
# @option opts [Symbol] :id
|
48
|
+
# @option opts [Integer] :min_occurs Default value is `0`.
|
49
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
50
|
+
# @return [TermUtils::AP::Parameter]
|
51
|
+
def define_parameter(opts = {}, &block)
|
52
|
+
new_parameter = TermUtils::AP::Parameter.new(opts)
|
53
|
+
@elements << new_parameter
|
54
|
+
block.call(new_parameter) if block
|
55
|
+
new_parameter
|
56
|
+
end
|
57
|
+
# Creates and adds a new Level.
|
58
|
+
# @param opts [Hash]
|
59
|
+
# @option opts [Symbol] :id
|
60
|
+
# @option opts [Integer] :min_occurs Default value is `0`.
|
61
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
62
|
+
# @return [TermUtils::AP::Level]
|
63
|
+
def define_level(opts = {}, &block)
|
64
|
+
new_level = TermUtils::AP::Level.new(opts)
|
65
|
+
@elements << new_level
|
66
|
+
block.call(new_level) if block
|
67
|
+
new_level
|
68
|
+
end
|
69
|
+
# Fetches all direct flagged parameters and levels.
|
70
|
+
# @return [Array]
|
71
|
+
# @see TermUtils::AP::Syntax#fetch_flagged_elements
|
72
|
+
# @see TermUtils::AP::Syntax#fetch_unflagged_parameters
|
73
|
+
def fetch_elements
|
74
|
+
flagged_elems = {}
|
75
|
+
unflagged_params = []
|
76
|
+
@elements.each do |e|
|
77
|
+
if e.flags.empty?
|
78
|
+
# Parameter
|
79
|
+
unflagged_params << e
|
80
|
+
else
|
81
|
+
# Parameter or Level
|
82
|
+
e.flags.each do |f|
|
83
|
+
flagged_elems[f.to_s] = e
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
[flagged_elems, unflagged_params]
|
88
|
+
end
|
89
|
+
# Fetches all direct flagged parameters and levels.
|
90
|
+
# @return [Hash<String, TermUtils::AP::Element>]
|
91
|
+
def fetch_flagged_elements
|
92
|
+
elems = {}
|
93
|
+
@elements.each do |e|
|
94
|
+
e.flags.each do |f|
|
95
|
+
elems[f.to_s] = e
|
96
|
+
end
|
97
|
+
end
|
98
|
+
elems
|
99
|
+
end
|
100
|
+
# Fetches all direct unflagged.
|
101
|
+
# @return [Array<TermUtils::AP::Parameter>]
|
102
|
+
def fetch_unflagged_parameters
|
103
|
+
params = []
|
104
|
+
@elements.each do |e|
|
105
|
+
next unless e.is_a? TermUtils::AP::Parameter
|
106
|
+
params << e if e.flags.empty?
|
107
|
+
end
|
108
|
+
params
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Syntax error.
|
21
|
+
class SyntaxError < StandardError
|
22
|
+
def initialize(msg)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright (C) 2019 Thomas Baron
|
2
|
+
#
|
3
|
+
# This file is part of term_utils.
|
4
|
+
#
|
5
|
+
# term_utils is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, version 3 of the License.
|
8
|
+
#
|
9
|
+
# term_utils 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 term_utils. If not, see <https://www.gnu.org/licenses/>.
|
16
|
+
require 'term_utils/property_tree_node'
|
17
|
+
require 'term_utils/ap/no_such_value_error'
|
18
|
+
require 'term_utils/ap/parse_error'
|
19
|
+
require 'term_utils/ap/syntax_error'
|
20
|
+
require 'term_utils/ap/article'
|
21
|
+
require 'term_utils/ap/flag'
|
22
|
+
require 'term_utils/ap/element'
|
23
|
+
require 'term_utils/ap/level'
|
24
|
+
require 'term_utils/ap/parameter'
|
25
|
+
require 'term_utils/ap/syntax'
|
26
|
+
require 'term_utils/ap/result'
|
27
|
+
require 'term_utils/ap/parser'
|
28
|
+
module TermUtils
|
29
|
+
# The Argument Parser module provides a way to parse command arguments.
|
30
|
+
module AP
|
31
|
+
# Creates a new Syntax.
|
32
|
+
# @return [TermUtils::AP::Syntax]
|
33
|
+
def self.create_syntax(&block)
|
34
|
+
new_syntax = TermUtils::AP::Syntax.new
|
35
|
+
block.call(new_syntax) if block
|
36
|
+
new_syntax
|
37
|
+
end
|
38
|
+
# Parses a given command.
|
39
|
+
# @param syntax [TermUtils::AP::Syntax]
|
40
|
+
# @param command [String]
|
41
|
+
# @param opts [Hash]
|
42
|
+
# @return [TermUtils::AP::Result]
|
43
|
+
# @raise [TermUtils::AP::ParseError]
|
44
|
+
# @raise [TermUtils::AP::SyntaxError]
|
45
|
+
def self.parse_command(syntax, command, opts = {})
|
46
|
+
TermUtils::AP::Parser.new.parse_command(syntax, command, opts)
|
47
|
+
end
|
48
|
+
# Parses a given list of arguments.
|
49
|
+
# @param syntax [TermUtils::AP::Syntax]
|
50
|
+
# @param arguments [Array<String>]
|
51
|
+
# @param opts [Hash]
|
52
|
+
# @return [TermUtils::AP::Result]
|
53
|
+
# @raise [TermUtils::AP::ParseError]
|
54
|
+
# @raise [TermUtils::AP::SyntaxError]
|
55
|
+
def self.parse_arguments(syntax, arguments, opts = {})
|
56
|
+
TermUtils::AP::Parser.new.parse_arguments(syntax, arguments, opts)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# Copyright (C) 2019 Thomas Baron
|
2
|
+
#
|
3
|
+
# This file is part of term_utils.
|
4
|
+
#
|
5
|
+
# term_utils is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, version 3 of the License.
|
8
|
+
#
|
9
|
+
# term_utils 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 term_utils. If not, see <https://www.gnu.org/licenses/>.
|
16
|
+
module TermUtils
|
17
|
+
# Represents a general-purpose tree node that holds a key-value pair.
|
18
|
+
class PropertyTreeNode
|
19
|
+
# @return [TermUtils::PropertyTreeNode]
|
20
|
+
attr_accessor :parent_node
|
21
|
+
# @return [Array<TermUtils::PropertyTreeNode>]
|
22
|
+
attr_accessor :child_nodes
|
23
|
+
# @return [Object]
|
24
|
+
attr_accessor :key
|
25
|
+
# @return [Object]
|
26
|
+
attr_accessor :value
|
27
|
+
# Creates a new node.
|
28
|
+
# @param opts [Hash<Symbol, Object>]
|
29
|
+
# option opts [Object] :key
|
30
|
+
# option opts [Object] :value
|
31
|
+
def initialize(opts = {}, &block)
|
32
|
+
@parent_node = nil
|
33
|
+
@child_nodes = nil
|
34
|
+
@key = opts.fetch(:key, nil)
|
35
|
+
@value = opts.fetch(:value, nil)
|
36
|
+
block.call(self) if block
|
37
|
+
end
|
38
|
+
# For dup method.
|
39
|
+
def initialize_dup(other)
|
40
|
+
@parent_node = nil
|
41
|
+
if other.child_nodes
|
42
|
+
@child_nodes = []
|
43
|
+
other.child_nodes.each do |n|
|
44
|
+
new_node = n.dup
|
45
|
+
new_node.parent_node = self
|
46
|
+
@child_nodes << new_node
|
47
|
+
end
|
48
|
+
end
|
49
|
+
super
|
50
|
+
end
|
51
|
+
# Tests whether this one is the head of the tree (i.e. has no parent).
|
52
|
+
# @return [Boolean]
|
53
|
+
def head?
|
54
|
+
@parent_node == nil
|
55
|
+
end
|
56
|
+
# Tests whether this one is a leaf of the tree (i.e. has no child).
|
57
|
+
# @return [Boolean]
|
58
|
+
def leaf?
|
59
|
+
@child_nodes == nil
|
60
|
+
end
|
61
|
+
# Returns the child node identified by a given key.
|
62
|
+
# @param key [Object]
|
63
|
+
# @return [TermUtils::PropertyTreeNode, nil]
|
64
|
+
def child_node(key)
|
65
|
+
if @child_nodes
|
66
|
+
@child_nodes.find { |n| n.key == key }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
# Creates a new node and adds it as a child.
|
70
|
+
# @param opts [Hash<Symbol,Object>] key value
|
71
|
+
# @return [TermUtils::PropertyTreeNode]
|
72
|
+
def define_node(opts = {}, &block)
|
73
|
+
new_node = TermUtils::PropertyTreeNode.new(opts)
|
74
|
+
new_node.parent_node = self
|
75
|
+
@child_nodes = [] unless @child_nodes
|
76
|
+
@child_nodes << new_node
|
77
|
+
block.call(new_node) if block
|
78
|
+
new_node
|
79
|
+
end
|
80
|
+
# Builds the path of keys.
|
81
|
+
# @return [Array<Object>]
|
82
|
+
def path
|
83
|
+
p = @parent_node ? @parent_node.path : []
|
84
|
+
p << @key if @key
|
85
|
+
p
|
86
|
+
end
|
87
|
+
# Iterates over every node.
|
88
|
+
# @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
|
89
|
+
# @return [nil]
|
90
|
+
def each_node(opts = {}, &block)
|
91
|
+
rpath = nil
|
92
|
+
if opts.has_key? :path
|
93
|
+
rpath = opts[:path].dup
|
94
|
+
end
|
95
|
+
dive = true
|
96
|
+
if @key
|
97
|
+
hide = false
|
98
|
+
if rpath
|
99
|
+
if rpath.shift == @key
|
100
|
+
unless rpath.empty?
|
101
|
+
hide = true
|
102
|
+
end
|
103
|
+
else
|
104
|
+
dive = false
|
105
|
+
hide = true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
unless hide or (opts[:leaf_only] and @child_nodes)
|
109
|
+
if opts.has_key? :block
|
110
|
+
opts[:block].call(self)
|
111
|
+
elsif block
|
112
|
+
block.call(self)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end # if @key
|
116
|
+
if dive and @child_nodes
|
117
|
+
ropts = opts.dup
|
118
|
+
if rpath
|
119
|
+
if rpath.empty?
|
120
|
+
ropts.delete :path
|
121
|
+
else
|
122
|
+
ropts[:path] = rpath
|
123
|
+
end
|
124
|
+
end
|
125
|
+
if block
|
126
|
+
ropts[:block] = block
|
127
|
+
end
|
128
|
+
@child_nodes.each do |n|
|
129
|
+
n.each_node(ropts)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
# Collects nodes.
|
135
|
+
# @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
|
136
|
+
# @return [Array<TermUtils::PropertyTreeNode>]
|
137
|
+
def collect_nodes(opts = {})
|
138
|
+
nodes = []
|
139
|
+
each_node(opts) do |n|
|
140
|
+
nodes << n
|
141
|
+
end
|
142
|
+
nodes
|
143
|
+
end
|
144
|
+
# Collects node paths.
|
145
|
+
# @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
|
146
|
+
# @return [Array<Array<Object>>]
|
147
|
+
def collect_paths(opts = {})
|
148
|
+
paths = []
|
149
|
+
each_node(opts) do |n|
|
150
|
+
paths << n.path
|
151
|
+
end
|
152
|
+
paths
|
153
|
+
end
|
154
|
+
# Collect node values.
|
155
|
+
# @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
|
156
|
+
# @return [Array<Object>]
|
157
|
+
def collect_values(opts = {})
|
158
|
+
vals = []
|
159
|
+
each_node(opts) do |n|
|
160
|
+
vals << n.value if n.value
|
161
|
+
end
|
162
|
+
vals
|
163
|
+
end
|
164
|
+
# Finds the node identified by a given path of keys.
|
165
|
+
# @param path [Array<Object>]
|
166
|
+
# @return [TermUtils::PropertyTreeNode]
|
167
|
+
def find_node(path)
|
168
|
+
catch :found do
|
169
|
+
each_node(:path => path) do |n|
|
170
|
+
throw :found, n
|
171
|
+
end
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
# Tests whether the node identified by a given path of keys exists.
|
176
|
+
# @param path [Array<Object>]
|
177
|
+
# @return [Boolean]
|
178
|
+
def node_exists?(path)
|
179
|
+
find_node(path) != nil
|
180
|
+
end
|
181
|
+
# Evaluates the total number of nodes in the tree represented by this one.
|
182
|
+
# @param path [Array<Object>]
|
183
|
+
# @return [Integer]
|
184
|
+
def eval_child_count(path)
|
185
|
+
node = find_node(path)
|
186
|
+
if node
|
187
|
+
node.child_nodes ? node.child_nodes.length : 0
|
188
|
+
end
|
189
|
+
end
|
190
|
+
# Finds the node identified by a given path of keys and returns its value.
|
191
|
+
# @param path [Array<Object>]
|
192
|
+
# @return [Object]
|
193
|
+
def find_node_value(path)
|
194
|
+
node = find_node(path)
|
195
|
+
if node
|
196
|
+
node.value
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/lib/term_utils.rb
CHANGED
data/term_utils.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: term_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Baron
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10
|
11
|
+
date: 2019-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: 'Provides terminal utilities like table formatting.
|
14
14
|
|
@@ -24,11 +24,25 @@ files:
|
|
24
24
|
- README.md
|
25
25
|
- Rakefile
|
26
26
|
- doc/TermUtils.html
|
27
|
+
- doc/TermUtils/AP.html
|
28
|
+
- doc/TermUtils/AP/Article.html
|
29
|
+
- doc/TermUtils/AP/Element.html
|
30
|
+
- doc/TermUtils/AP/Flag.html
|
31
|
+
- doc/TermUtils/AP/Level.html
|
32
|
+
- doc/TermUtils/AP/NoSuchValueError.html
|
33
|
+
- doc/TermUtils/AP/Parameter.html
|
34
|
+
- doc/TermUtils/AP/ParseError.html
|
35
|
+
- doc/TermUtils/AP/Parser.html
|
36
|
+
- doc/TermUtils/AP/Result.html
|
37
|
+
- doc/TermUtils/AP/ResultView.html
|
38
|
+
- doc/TermUtils/AP/Syntax.html
|
39
|
+
- doc/TermUtils/AP/SyntaxError.html
|
27
40
|
- doc/TermUtils/FF.html
|
28
41
|
- doc/TermUtils/FF/Config.html
|
29
42
|
- doc/TermUtils/FF/Cursor.html
|
30
43
|
- doc/TermUtils/FF/Cursor/Context.html
|
31
44
|
- doc/TermUtils/FF/Query.html
|
45
|
+
- doc/TermUtils/PropertyTreeNode.html
|
32
46
|
- doc/TermUtils/Tab.html
|
33
47
|
- doc/TermUtils/Tab/Column.html
|
34
48
|
- doc/TermUtils/Tab/Holder.html
|
@@ -49,10 +63,23 @@ files:
|
|
49
63
|
- doc/method_list.html
|
50
64
|
- doc/top-level-namespace.html
|
51
65
|
- lib/term_utils.rb
|
66
|
+
- lib/term_utils/ap.rb
|
67
|
+
- lib/term_utils/ap/article.rb
|
68
|
+
- lib/term_utils/ap/element.rb
|
69
|
+
- lib/term_utils/ap/flag.rb
|
70
|
+
- lib/term_utils/ap/level.rb
|
71
|
+
- lib/term_utils/ap/no_such_value_error.rb
|
72
|
+
- lib/term_utils/ap/parameter.rb
|
73
|
+
- lib/term_utils/ap/parse_error.rb
|
74
|
+
- lib/term_utils/ap/parser.rb
|
75
|
+
- lib/term_utils/ap/result.rb
|
76
|
+
- lib/term_utils/ap/syntax.rb
|
77
|
+
- lib/term_utils/ap/syntax_error.rb
|
52
78
|
- lib/term_utils/ff.rb
|
53
79
|
- lib/term_utils/ff/config.rb
|
54
80
|
- lib/term_utils/ff/cursor.rb
|
55
81
|
- lib/term_utils/ff/query.rb
|
82
|
+
- lib/term_utils/property_tree_node.rb
|
56
83
|
- lib/term_utils/tab.rb
|
57
84
|
- term_utils.gemspec
|
58
85
|
homepage: https://git.yellowcube.net/tvb/term_utils
|