term_utils 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -2
  3. data/COPYING +3 -3
  4. data/README.md +51 -16
  5. data/doc/TermUtils.html +9 -9
  6. data/doc/TermUtils/AP.html +48 -159
  7. data/doc/TermUtils/AP/Article.html +48 -46
  8. data/doc/TermUtils/AP/ArticleResult.html +584 -0
  9. data/doc/TermUtils/AP/Flag.html +294 -77
  10. data/doc/TermUtils/AP/NoSuchValueError.html +13 -13
  11. data/doc/TermUtils/AP/Parameter.html +885 -97
  12. data/doc/TermUtils/AP/ParameterResult.html +980 -0
  13. data/doc/TermUtils/{FF/Cursor/Context.html → AP/ParameterWalkerHooks.html} +59 -59
  14. data/doc/TermUtils/AP/ParseError.html +13 -13
  15. data/doc/TermUtils/AP/Parser.html +174 -142
  16. data/doc/TermUtils/AP/Result.html +200 -527
  17. data/doc/TermUtils/AP/Syntax.html +102 -392
  18. data/doc/TermUtils/AP/SyntaxError.html +13 -13
  19. data/doc/TermUtils/AP/Walker.html +686 -0
  20. data/doc/TermUtils/FF.html +10 -10
  21. data/doc/TermUtils/FF/Config.html +201 -33
  22. data/doc/TermUtils/FF/Context.html +585 -0
  23. data/doc/TermUtils/FF/Entry.html +626 -0
  24. data/doc/TermUtils/FF/Query.html +402 -66
  25. data/doc/TermUtils/PropertyTreeNode.html +302 -188
  26. data/doc/TermUtils/Tab.html +90 -83
  27. data/doc/TermUtils/Tab/Column.html +94 -92
  28. data/doc/TermUtils/Tab/Header.html +26 -26
  29. data/doc/TermUtils/Tab/Holder.html +74 -74
  30. data/doc/TermUtils/Tab/Printer.html +42 -42
  31. data/doc/TermUtils/Tab/Table.html +124 -128
  32. data/doc/TermUtils/Tab/TableError.html +11 -11
  33. data/doc/_index.html +48 -34
  34. data/doc/class_list.html +3 -3
  35. data/doc/css/style.css +2 -2
  36. data/doc/file.README.html +64 -31
  37. data/doc/file_list.html +2 -2
  38. data/doc/frames.html +2 -2
  39. data/doc/index.html +64 -31
  40. data/doc/js/app.js +14 -3
  41. data/doc/method_list.html +387 -211
  42. data/doc/top-level-namespace.html +6 -6
  43. data/lib/term_utils.rb +8 -1
  44. data/lib/term_utils/ap.rb +41 -30
  45. data/lib/term_utils/ap/article.rb +14 -8
  46. data/lib/term_utils/ap/flag.rb +36 -19
  47. data/lib/term_utils/ap/parameter.rb +87 -18
  48. data/lib/term_utils/ap/parser.rb +141 -115
  49. data/lib/term_utils/ap/result.rb +207 -160
  50. data/lib/term_utils/ap/syntax.rb +52 -68
  51. data/lib/term_utils/ff.rb +11 -2
  52. data/lib/term_utils/ff/config.rb +20 -8
  53. data/lib/term_utils/{ap/no_such_value_error.rb → ff/entry.rb} +25 -7
  54. data/lib/term_utils/ff/query.rb +93 -14
  55. data/lib/term_utils/property_tree_node.rb +47 -19
  56. data/lib/term_utils/tab.rb +102 -58
  57. data/term_utils.gemspec +4 -4
  58. metadata +12 -14
  59. data/doc/TermUtils/AP/Element.html +0 -1025
  60. data/doc/TermUtils/AP/Level.html +0 -638
  61. data/doc/TermUtils/FF/Cursor.html +0 -929
  62. data/lib/term_utils/ap/element.rb +0 -78
  63. data/lib/term_utils/ap/level.rb +0 -57
  64. data/lib/term_utils/ap/parse_error.rb +0 -27
  65. data/lib/term_utils/ap/syntax_error.rb +0 -27
  66. data/lib/term_utils/ff/cursor.rb +0 -153
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
- #
3
- # Copyright (C) 2019 Thomas Baron
2
+
3
+ # Copyright (C) 2020 Thomas Baron
4
4
  #
5
5
  # This file is part of term_utils.
6
6
  #
@@ -15,183 +15,230 @@
15
15
  #
16
16
  # You should have received a copy of the GNU General Public License
17
17
  # along with term_utils. If not, see <https://www.gnu.org/licenses/>.
18
+
18
19
  module TermUtils
19
20
  module AP
20
21
  # Represents an argument parsing Result.
21
22
  class Result
22
- # @return [TermUtils::PropertyTreeNode]
23
- attr_accessor :value
23
+ # @return [Syntax]
24
+ attr_reader :parameter
25
+ # @return [Array<ParameterResult>]
26
+ attr_reader :results
27
+ # @return [Array<String>]
28
+ attr_accessor :remaining_arguments
29
+
24
30
  # 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
31
+ # @param syntax [Syntax]
32
+ def initialize(syntax)
33
+ @syntax = syntax
34
+ @results = []
35
+ @remaining_arguments = nil
37
36
  end
38
- # Collects IDs.
39
- # @param id [Symbol, Array<Symbol>] ID path.
40
- # @return [Array<Symbol>]
41
- def collect(id, &block)
42
- node = @value
43
- if id
44
- id = [id] if id.is_a? Symbol
45
- node = @value.find_node(id)
46
- end
47
- res = []
48
- return res unless node && node.child_nodes
49
- if block
50
- node.child_nodes.each do |n|
51
- res << n.key if block.call(n.key)
52
- end
53
- else
54
- node.child_nodes.each do |n|
55
- res << n.key
37
+
38
+ # Adds a ParameterResult.
39
+ # @param result [ParameterResult]
40
+ def add_result(result)
41
+ @results << result
42
+ end
43
+
44
+ # Returns the first ParameterResult for a given parameter id.
45
+ # @param id [Symbol]
46
+ # @return [ParameterResult]
47
+ def find_parameter(id)
48
+ @results.find { |r| r.param_id == id }
49
+ end
50
+
51
+ # Returns all ParameterResult(s) for a given parameter id.
52
+ # @param id [Symbol]
53
+ # @return [Array<ParameterResult>]
54
+ def find_parameters(id)
55
+ @results.find_all { |r| r.param_id == id }
56
+ end
57
+
58
+ # Walks through this one.
59
+ def walk(&block)
60
+ walker = TermUtils::AP::Walker.new
61
+ block.call(walker)
62
+ @results.each do |p|
63
+ p.results.each do |a|
64
+ walker.notify_article(a)
56
65
  end
66
+ walker.notify_parameter(p)
57
67
  end
58
- res
59
- end
60
- # Tests whether a given level/parameter/article is present in the result value.
61
- # @param id [Symbol, Array<Symbol>] ID path.
62
- # @return [Boolean]
63
- def present?(id)
64
- if id.is_a? Symbol
65
- !!@value.child_node(id)
66
- elsif id.is_a? Array
67
- @value.node_exists?(id)
68
- end
68
+ walker.notify_finished(@remaining_arguments)
69
+ end
70
+ end
71
+
72
+ # Represents a result for a parameter.
73
+ class ParameterResult
74
+ # @return [Parameter]
75
+ attr_accessor :parameter
76
+ # @return [Array<ArticleResult>]
77
+ attr_accessor :results
78
+
79
+ # Constructs a new ParameterResult.
80
+ # @param parent [Result]
81
+ # @param parameter [Parameter]
82
+ def initialize(parent, parameter)
83
+ @parent = parent
84
+ @parent.add_result(self)
85
+ @parameter = parameter
86
+ @results = []
87
+ end
88
+
89
+ # Adds an ArticleResult.
90
+ # @param result [ArticleResult]
91
+ def add_result(result)
92
+ @results << result
69
93
  end
70
- # Evaluates the number of occurrences of a given level, parameter or article.
71
- # @param id [Symbol, Array<Symbol>]
72
- # @return [Integer]
73
- def eval_occurs(id)
74
- id = [id] if id.is_a? Symbol
75
- obj = fetch_syntax_object(id)
76
- raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
77
- node = @value.find_node(id)
78
- return 0 unless node
79
- return 1 if obj.occur_bounded? && (obj.max_occurs == 1)
80
- # Parameter is multiple.
81
- node.child_nodes ? node.child_nodes.length : 0
82
- end
83
- # Fetches a value.
84
- # @param id [Symbol, Array<Symbol>, nil]
85
- # @param opts [Hash] `:index`, `:multi`.
86
- # @option opts [Integer] :index The index of a multiple-occurrence level/parameter/article.
87
- # @option opts [Boolean] :multi Whether an array of values shall be returned instead of a single value.
94
+
95
+ # @return [Symbol]
96
+ def param_id
97
+ @parameter.id
98
+ end
99
+
100
+ # Returns the first ArticleResult for a given article id.
101
+ # @param id [Symbol]
102
+ # @return [ArticleResult]
103
+ def find_article(id)
104
+ @results.find { |r| r.art_id == id }
105
+ end
106
+
107
+ # Returns all ArticleResult(s) for a given article id.
108
+ # @param id [Symbol]
109
+ # @return [Array<Result>]
110
+ def find_articles(id)
111
+ @results.find_all { |r| r.art_id == id }
112
+ end
113
+
114
+ # Returns the value of the first ArticleResult.
115
+ # @param id [Symbol] Filter of article id.
88
116
  # @return [Object]
89
- # @raise [TermUtils::AP::NoSuchValueError]
90
- def fetch_value(id, opts = {})
91
- index = opts.fetch(:index, nil)
92
- multi = opts.fetch(:multi, false)
93
- unless id
94
- node = @value
95
- if node && node.child_nodes && index
96
- node = node.child_node(index)
97
- end
98
- raise TermUtils::AP::NoSuchValueError, "no such value" unless node
99
- vals = node.collect_values
100
- raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
101
- return multi ? vals : vals.first
102
- end
103
- id = [id] if id.is_a? Symbol
104
- obj = fetch_syntax_object(id)
105
- raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
106
- node = @value.find_node(id)
107
- if node && node.child_nodes && index
108
- node = node.child_node(index)
117
+ def value(id = nil)
118
+ return @results.first.value unless id
119
+
120
+ find_article(id).value
121
+ end
122
+
123
+ # Returns the value of all ArticleResult(s).
124
+ # @param id [Symbol] Filter of article id.
125
+ # @return [Array<Object>]
126
+ def values(id = nil)
127
+ return @results.map(&:value) unless id
128
+
129
+ vals = []
130
+ @results.each do |r|
131
+ next if r.art_id != id
132
+
133
+ vals << r.values
109
134
  end
110
- raise TermUtils::AP::NoSuchValueError, "no such value" unless node
111
- catch :value do
112
- if obj.is_a? TermUtils::AP::Parameter
113
- raise TermUtils::AP::NoSuchValueError, "parameter has no article" if obj.articles.empty?
114
- raise TermUtils::AP::NoSuchValueError, "no such value" if node.leaf?
115
- vals = node.collect_values
116
- raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
117
- if multi
118
- throw :value, vals
119
- else
120
- throw :value, vals.first
121
- end
122
- elsif obj.is_a? TermUtils::AP::Article
123
- # raise TermUtils::AP::NoSuchValueError, "no such value" if node.leaf?
124
- vals = node.collect_values
125
- raise TermUtils::AP::NoSuchValueError, "no such value" if vals.empty?
126
- if multi
127
- throw :value, vals
128
- else
129
- throw :value, vals.first
130
- end
131
- end
132
- raise TermUtils::AP::NoSuchValueError, "wrong id"
135
+ vals
136
+ end
137
+ end
138
+
139
+ # Represents a result for an article.
140
+ class ArticleResult
141
+ # @return [ParameterResult]
142
+ attr_accessor :parent
143
+ # @return [Article]
144
+ attr_accessor :article
145
+ # @return [Object]
146
+ attr_accessor :value
147
+
148
+ # Constructs a new ArticleResult.
149
+ # @param parent [ParameterResult]
150
+ # @param article [Article]
151
+ # @param value [Object]
152
+ def initialize(parent, article, value)
153
+ @parent = parent
154
+ @parent.add_result(self)
155
+ @article = article
156
+ @value = value
157
+ end
158
+
159
+ # @return [Symbol]
160
+ def art_id
161
+ @article.id
162
+ end
163
+ end
164
+
165
+ # Represents a Result Walker.
166
+ class Walker
167
+ # Constructs a new Walker.
168
+ def initialize
169
+ @anonymous_parameter_hook = nil
170
+ @anonymous_article_hook = nil
171
+ @parameter_hooks = {}
172
+ @finished_hook = nil
173
+ end
174
+
175
+ # Registers a parameter hook.
176
+ def parameter(param_id = nil, &block)
177
+ unless param_id
178
+ # Anonymous parameter hook
179
+ @anonymous_parameter_hook = block
180
+ return
133
181
  end
182
+
183
+ @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id)
184
+ @parameter_hooks[param_id].hook = block
134
185
  end
135
- # Shifts this one.
136
- # @param id [Symbol, Array<Symbol>]
137
- # @param opts [Hash] `:index`, `:multi`.
138
- # @option opts [Integer] :index The index of a multiple-occurrence level/parameter/article.
139
- # @return [TermUtils::AP::Result]
140
- # @raise [TermUtils::AP::NoSuchValueError]
141
- def shift(id, opts = {})
142
- index = opts.fetch(:index, nil)
143
- id = [id] if id.is_a? Symbol
144
- obj = fetch_syntax_object(id)
145
- raise TermUtils::AP::NoSuchValueError, "no such syntax object" unless obj
146
- node = @value.find_node(id)
147
- if node && node.child_nodes && index
148
- node = node.child_node(index)
186
+
187
+ # Registers an article hook.
188
+ def article(param_id = nil, art_id = nil, &block)
189
+ unless param_id
190
+ # Anonymous article hook
191
+ @anonymous_article_hook = block
192
+ return
149
193
  end
150
- raise TermUtils::AP::NoSuchValueError, "no such value" unless node
151
- catch :value do
152
- if obj.is_a? TermUtils::AP::Level
153
- throw :value, TermUtils::AP::Result.new(obj.syntax, nil, node)
154
- elsif obj.is_a? TermUtils::AP::Parameter
155
- throw :value, TermUtils::AP::Result.new(@syntax, obj, node)
156
- elsif obj.is_a? TermUtils::AP::Article
157
- throw :value, TermUtils::AP::Result.new(@syntax, obj, node)
158
- end
159
- raise TermUtils::AP::NoSuchValueError, "wrong id"
194
+
195
+ unless art_id
196
+ # Anonymous article hook
197
+ @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id)
198
+ @parameter_hooks[param_id].anonymous_article_hook = block
199
+ return
160
200
  end
201
+
202
+ @parameter_hooks[param_id] = TermUtils::AP::ParameterWalkerHooks.new unless @parameter_hooks.key?(param_id)
203
+ @parameter_hooks[param_id].article_hooks ||= {}
204
+ @parameter_hooks[param_id].article_hooks[art_id] = block
161
205
  end
162
- private
163
- # Fetches a given syntax object.
164
- # @param id_path [Array<Symbol>]
165
- # @return [TermUtils::AP::Level, TermUtils::AP::Parameter, TermUtils::AP::Article, nil]
166
- def fetch_syntax_object(id_path)
167
- id = id_path.dup
168
- id = [@element.id].concat(id) if @element
169
- catch :done do
170
- fetch_syntax_object0(@syntax, id)
171
- end
206
+
207
+ # Registers a walk finished hook.
208
+ def finished(&block)
209
+ @finished_hook = block
172
210
  end
173
- # Fetches a given syntax object.
174
- # @param syntax [TermUtils::AP::Syntax]
175
- # @param id_path [Array<Symbol>]
176
- # @return [TermUtils::AP::Level, TermUtils::AP::Parameter, TermUtils::AP::Article, nil]
177
- def fetch_syntax_object0(syntax, id_path)
178
- id = id_path.shift
179
- syntax.elements.each do |e|
180
- next unless e.id == id
181
- throw :done, e if id_path.empty?
182
- if e.is_a? TermUtils::AP::Level
183
- fetch_syntax_object0(e.syntax, id_path)
184
- elsif e.is_a? TermUtils::AP::Parameter
185
- throw :done if id_path.empty?
186
- id = id_path.shift
187
- throw :done unless id_path.empty?
188
- e.articles.each do |a|
189
- throw :done, a if a.id = id
190
- end
191
- throw :done
192
- end
211
+
212
+ # Calls parameter hooks.
213
+ def notify_parameter(parameter)
214
+ # (1of2) ID parameter hook
215
+ param_hooks = @parameter_hooks[parameter.param_id]
216
+ param_hooks.hook.call(parameter) if param_hooks && param_hooks.hook
217
+ # (2of2) Anonymous parameter hook
218
+ @anonymous_parameter_hook.call(parameter) if @anonymous_parameter_hook
219
+ end
220
+
221
+ # Calls article hooks.
222
+ def notify_article(article)
223
+ # (1of2) ID article hook
224
+ param_hooks = @parameter_hooks[article.parent.param_id]
225
+ if param_hooks
226
+ # ID article hook
227
+ param_hooks.article_hooks[article.art_id].call(article) if param_hooks.article_hooks && param_hooks.article_hooks.key?(article.art_id)
228
+ # Anonymous article hook
229
+ param_hooks.anonymous_article_hook.call(article) if param_hooks.anonymous_article_hook
193
230
  end
231
+ # (2of2) Anonymous article hook
232
+ @anonymous_article_hook.call(article) if @anonymous_article_hook
233
+ end
234
+
235
+ # Calls finished hook.
236
+ def notify_finished(remaining_arguments)
237
+ @finished_hook.call(remaining_arguments) if @finished_hook
194
238
  end
195
239
  end
240
+
241
+ # Parameter hooks for Walker.
242
+ ParameterWalkerHooks = Struct.new('ParameterWalkerHooks', :hook, :anonymous_article_hook, :article_hooks)
196
243
  end
197
244
  end
@@ -1,6 +1,6 @@
1
1
  # frozen-string-literal: true
2
- #
3
- # Copyright (C) 2019 Thomas Baron
2
+
3
+ # Copyright (C) 2020 Thomas Baron
4
4
  #
5
5
  # This file is part of term_utils.
6
6
  #
@@ -15,97 +15,81 @@
15
15
  #
16
16
  # You should have received a copy of the GNU General Public License
17
17
  # along with term_utils. If not, see <https://www.gnu.org/licenses/>.
18
+
18
19
  module TermUtils
19
20
  module AP
20
- # Represents the argument list syntax. It holds a list of parameters and
21
- # levels.
21
+ # Represents the argument list syntax. It holds a list of parameters.
22
22
  class Syntax
23
- # @return [Array<TermUtils::AP::Element>]
24
- attr_accessor :elements
23
+ # @return [Array<Parameter>]
24
+ attr_accessor :parameters
25
+
25
26
  # Constructs a new Syntax.
26
27
  def initialize
27
- @elements = []
28
+ @parameters = []
28
29
  end
30
+
29
31
  # For dup method.
30
32
  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
33
+ super(other)
34
+ @parameters = other.parameters.map(&:dup) if other.parameters
38
35
  end
36
+
39
37
  # Finalizes this one. Internal use.
40
38
  # @return [nil]
39
+ # @raise [SyntaxError]
41
40
  def finalize!(opts = {})
42
- opts[:anonymous] = 0 unless opts.has_key? :anonymous
43
- @elements.each { |e| e.finalize!(opts) }
41
+ opts[:anonymous] = 0 unless opts.key? :anonymous
42
+ opts[:flag_labels] = []
43
+ @parameters.each { |p| p.finalize!(opts) }
44
+ nil
44
45
  end
46
+
45
47
  # Creates and adds a new Parameter.
48
+ # @param id [Symbol, nil]
46
49
  # @param opts [Hash]
47
50
  # @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)
51
+ # @option opts [Integer] :min_occurs
52
+ # @option opts [Integer] :max_occurs
53
+ # @return [Parameter]
54
+ def define_parameter(id = nil, opts = {}, &block)
55
+ if id
56
+ param = @parameters.find { |p| p.id == id }
57
+ if param
58
+ block.call(param) if block
59
+ return param
60
+ end
61
+
62
+ opts[:id] = id
63
+ end
52
64
  new_parameter = TermUtils::AP::Parameter.new(opts)
53
- @elements << new_parameter
65
+ @parameters << new_parameter
54
66
  block.call(new_parameter) if block
55
67
  new_parameter
56
68
  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.
69
+
70
+ # Fetches all flagged parameters and unflagged parameters.
70
71
  # @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 = {}
72
+ def fetch_parameters
75
73
  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
74
+ flagged_params = {}
75
+ shortcut_flags = {}
76
+ @parameters.each do |p|
77
+ if p.flagged?
78
+ # Flagged
79
+ p.flags.each do |f|
80
+ flagged_params[f.label] = p
81
+ if f.long?
82
+ shortcut_flags["#{f.label}="] = f
83
+ else
84
+ shortcut_flags[f.label] = f
85
+ end
84
86
  end
87
+ else
88
+ # Unflagged
89
+ unflagged_params << p
85
90
  end
86
91
  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
92
+ [unflagged_params, flagged_params, shortcut_flags]
109
93
  end
110
94
  end
111
95
  end