term_utils 0.3.2 → 0.4.0

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.
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,4 +1,6 @@
1
- # Copyright (C) 2019 Thomas Baron
1
+ # frozen-string-literal: true
2
+
3
+ # Copyright (C) 2020 Thomas Baron
2
4
  #
3
5
  # This file is part of term_utils.
4
6
  #
@@ -13,6 +15,13 @@
13
15
  #
14
16
  # You should have received a copy of the GNU General Public License
15
17
  # along with term_utils. If not, see <https://www.gnu.org/licenses/>.
18
+
19
+ module TermUtils
20
+ # Provides a way to find files.
21
+ module FF
22
+ end
23
+ end
24
+
16
25
  require 'term_utils/ff/config'
17
- require 'term_utils/ff/cursor'
26
+ require 'term_utils/ff/entry'
18
27
  require 'term_utils/ff/query'
@@ -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,25 +15,37 @@
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
- # The ff module provides a way to find files.
20
20
  module FF
21
21
  # Represents a query configuration.
22
22
  class Config
23
23
  # @return [Array<Regexp>]
24
24
  attr_accessor :ignore_list
25
- # @return [Integer]
25
+ # @return [Integer, nil]
26
26
  attr_accessor :min_depth
27
- # @return [Integer]
27
+ # @return [Integer, nil]
28
28
  attr_accessor :max_depth
29
- # @return [Boolean]
30
- attr_accessor :sorted
29
+ # @return [Symbol, nil] Either `:forward`, `:reverse` or `nil` (default).
30
+ attr_accessor :sorting_mode
31
+ # @return [Proc, nil]
32
+ attr_accessor :sorting_compare
33
+
34
+ # Constructs a new Config.
31
35
  def initialize
32
36
  @ignore_list = []
33
37
  @min_depth = nil
34
38
  @max_depth = nil
35
- @sorted = false
39
+ @sorting_mode = nil
40
+ @sorting_compare = nil
41
+ end
42
+
43
+ # Returns whether the search is ordered.
44
+ # @return [Boolean]
45
+ def sorted?
46
+ (@sorting_mode == :forward) || (@sorting_mode == :reverse)
36
47
  end
48
+
37
49
  def initialize_copy(other)
38
50
  @ignore_list = other.ignore_list.dup
39
51
  super
@@ -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,12 +15,30 @@
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
- module AP
20
- # No such value error.
21
- class NoSuchValueError < StandardError
22
- def initialize(msg)
23
- super
20
+ module FF
21
+ # Represents an Entry of a Query result.
22
+ class Entry
23
+ # @return [Integer]
24
+ attr_accessor :index
25
+ # @return [String]
26
+ attr_accessor :name
27
+ # @return [Array<String>]
28
+ attr_accessor :relative_path_comps
29
+ # @return [String]
30
+ attr_accessor :path
31
+
32
+ def initialize
33
+ @index = nil
34
+ @name = nil
35
+ @relative_path_comps = nil
36
+ @path = nil
37
+ end
38
+
39
+ # @return [Integer]
40
+ def depth
41
+ @relative_path_comps.length
24
42
  end
25
43
  end
26
44
  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,51 +15,130 @@
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
- # The ff module provides a way to find files.
20
20
  module FF
21
+ # Query search context.
22
+ Context = Struct.new('Context', :config, :base_path, :block, :index_seq, :result)
21
23
  # Represents a file system query.
22
24
  class Query
25
+ # Constructs a new Query.
23
26
  def initialize
24
27
  @config = TermUtils::FF::Config.new
25
28
  end
29
+
26
30
  def initialize_copy(other)
27
31
  @config = other.config.dup
28
32
  super
29
33
  end
34
+
30
35
  # Adds a Regexp to ignore.
31
36
  # @param regexp [Regexp]
32
- # @return [TermUtils::FF::Query]
37
+ # @return [Query]
33
38
  def ignore(regexp)
34
39
  @config.ignore_list << regexp
35
40
  self
36
41
  end
42
+
37
43
  # Sets a minimum depth.
38
44
  # @param depth [Integer]
39
- # @return [TermUtils::FF::Query]
45
+ # @return [Query]
40
46
  def min_depth(depth)
41
47
  @config.min_depth = depth
42
48
  self
43
49
  end
50
+
44
51
  # Sets a maximum depth.
45
52
  # @param depth [Integer]
46
- # @return [TermUtils::FF::Query]
53
+ # @return [Query]
47
54
  def max_depth(depth)
48
55
  @config.max_depth = depth
49
56
  self
50
57
  end
51
- # Sets whether results shall be sorted.
52
- # @param sorted [Boolean]
53
- # @return [TermUtils::FF::Query]
54
- def sort(sorted = true)
55
- @config.sorted = sorted
58
+
59
+ # Sets the sorting mode.
60
+ # @param mode [Symbol] Either `:forward`, `:reverse` or `nil` (default).
61
+ # @return [Query]
62
+ def sort(mode = :forward, &block)
63
+ @config.sorting_mode = mode
64
+ @config.sorting_compare = block
56
65
  self
57
66
  end
67
+
58
68
  # Executes this one.
59
69
  # @param path [String]
60
- # @return [TermUtils::FF::Cursor]
61
- def exec(path)
62
- TermUtils::FF::Cursor.new(@config.dup, path).bootstrap
70
+ # @return [Array<Entry>]
71
+ def exec(path, &block)
72
+ ctx = Context.new
73
+ ctx.config = @config.dup
74
+ ctx.config.min_depth = 0 if ctx.config.min_depth.nil?
75
+ ctx.base_path = path
76
+ ctx.block = block
77
+ ctx.index_seq = 0
78
+ ctx.result = []
79
+ first_entry = TermUtils::FF::Entry.new
80
+ first_entry.name = path
81
+ first_entry.relative_path_comps = []
82
+ first_entry.path = path
83
+ if ctx.config.min_depth == 0
84
+ first_entry.index = ctx.index_seq
85
+ ctx.index_seq += 1
86
+ ctx.block.call(first_entry) if ctx.block
87
+ ctx.result << first_entry
88
+ end
89
+ if File.directory?(first_entry.path) && (ctx.config.max_depth.nil? || ctx.config.max_depth > 0)
90
+ TermUtils::FF::Query.search(ctx, first_entry)
91
+ end
92
+ ctx.result
93
+ end
94
+
95
+ # Searches a directory.
96
+ # @param ctx [Context]
97
+ # @param parent_entry [entry]
98
+ # @return [nil]
99
+ def self.search(ctx, parent_entry)
100
+ entries = Dir.entries(parent_entry.path)
101
+ unless ctx.config.sorting_mode.nil?
102
+ if ctx.config.sorting_compare.nil?
103
+ entries.sort!
104
+ else
105
+ entries.sort!(&ctx.config.sorting_compare)
106
+ end
107
+ if ctx.config.sorting_mode == :reverse
108
+ entries.reverse!
109
+ end
110
+ end
111
+ entries.each do |name|
112
+ next if %w[. ..].include? name
113
+ next unless accept_entry_name?(ctx, name)
114
+
115
+ new_entry = TermUtils::FF::Entry.new
116
+ new_entry.name = name
117
+ new_entry.relative_path_comps = parent_entry.relative_path_comps.dup.push(name)
118
+ new_entry.path = "#{ctx.base_path}/#{new_entry.relative_path_comps.join('/')}"
119
+ if ctx.config.min_depth <= new_entry.depth
120
+ new_entry.index = ctx.index_seq
121
+ ctx.index_seq += 1
122
+ ctx.block.call(new_entry) if ctx.block
123
+ ctx.result << new_entry
124
+ end
125
+ if File.directory?(new_entry.path) && (ctx.config.max_depth.nil? || ctx.config.max_depth > new_entry.depth)
126
+ TermUtils::FF::Query.search(ctx, new_entry)
127
+ end
128
+ end
129
+ end
130
+
131
+ # Tests whether a given entry should be accepted.
132
+ # @param ctx [Context]
133
+ # @param name [String]
134
+ # @return [Boolean]
135
+ def self.accept_entry_name?(ctx, name)
136
+ ctx.config.ignore_list.each do |i|
137
+ if i.match? name
138
+ return false
139
+ end
140
+ end
141
+ true
63
142
  end
64
143
  end
65
144
  end
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2019 Thomas Baron
1
+ # frozen-string-literal: true
2
+
3
+ # Copyright (C) 2020 Thomas Baron
2
4
  #
3
5
  # This file is part of term_utils.
4
6
  #
@@ -13,19 +15,21 @@
13
15
  #
14
16
  # You should have received a copy of the GNU General Public License
15
17
  # along with term_utils. If not, see <https://www.gnu.org/licenses/>.
18
+
16
19
  module TermUtils
17
20
  # Represents a general-purpose tree node that holds a key-value pair.
18
21
  class PropertyTreeNode
19
- # @return [TermUtils::PropertyTreeNode]
22
+ # @return [PropertyTreeNode]
20
23
  attr_accessor :parent_node
21
- # @return [Array<TermUtils::PropertyTreeNode>]
24
+ # @return [Array<PropertyTreeNode>]
22
25
  attr_accessor :child_nodes
23
26
  # @return [Object]
24
27
  attr_accessor :key
25
28
  # @return [Object]
26
29
  attr_accessor :value
27
- # Creates a new node.
28
- # @param opts [Hash<Symbol, Object>]
30
+
31
+ # Creates a new PropertyTreeNode.
32
+ # @param opts [Hash]
29
33
  # option opts [Object] :key
30
34
  # option opts [Object] :value
31
35
  def initialize(opts = {}, &block)
@@ -35,6 +39,7 @@ module TermUtils
35
39
  @value = opts.fetch(:value, nil)
36
40
  block.call(self) if block
37
41
  end
42
+
38
43
  # For dup method.
39
44
  def initialize_dup(other)
40
45
  @parent_node = nil
@@ -48,27 +53,33 @@ module TermUtils
48
53
  end
49
54
  super
50
55
  end
56
+
51
57
  # Tests whether this one is the head of the tree (i.e. has no parent).
52
58
  # @return [Boolean]
53
59
  def head?
54
60
  @parent_node == nil
55
61
  end
62
+
56
63
  # Tests whether this one is a leaf of the tree (i.e. has no child).
57
64
  # @return [Boolean]
58
65
  def leaf?
59
66
  @child_nodes == nil
60
67
  end
68
+
61
69
  # Returns the child node identified by a given key.
62
70
  # @param key [Object]
63
- # @return [TermUtils::PropertyTreeNode, nil]
71
+ # @return [PropertyTreeNode, nil]
64
72
  def child_node(key)
65
73
  if @child_nodes
66
74
  @child_nodes.find { |n| n.key == key }
67
75
  end
68
76
  end
77
+
69
78
  # Creates a new node and adds it as a child.
70
- # @param opts [Hash<Symbol,Object>] key value
71
- # @return [TermUtils::PropertyTreeNode]
79
+ # @param opts [Hash]
80
+ # @option opts [Object] :key
81
+ # @option opts [Object] :value
82
+ # @return [PropertyTreeNode]
72
83
  def define_node(opts = {}, &block)
73
84
  new_node = TermUtils::PropertyTreeNode.new(opts)
74
85
  new_node.parent_node = self
@@ -77,6 +88,7 @@ module TermUtils
77
88
  block.call(new_node) if block
78
89
  new_node
79
90
  end
91
+
80
92
  # Builds the path of keys.
81
93
  # @return [Array<Object>]
82
94
  def path
@@ -84,12 +96,15 @@ module TermUtils
84
96
  p << @key if @key
85
97
  p
86
98
  end
99
+
87
100
  # Iterates over every node.
88
- # @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
101
+ # @param opts [Hash]
102
+ # @option opts [Array] :path
103
+ # @option opts [Boolean] :leaf_only
89
104
  # @return [nil]
90
105
  def each_node(opts = {}, &block)
91
106
  rpath = nil
92
- if opts.has_key? :path
107
+ if opts.key? :path
93
108
  rpath = opts[:path].dup
94
109
  end
95
110
  dive = true
@@ -105,15 +120,15 @@ module TermUtils
105
120
  hide = true
106
121
  end
107
122
  end
108
- unless hide or (opts[:leaf_only] and @child_nodes)
109
- if opts.has_key? :block
123
+ unless hide || (opts[:leaf_only] && @child_nodes)
124
+ if opts.key? :block
110
125
  opts[:block].call(self)
111
126
  elsif block
112
127
  block.call(self)
113
128
  end
114
129
  end
115
130
  end # if @key
116
- if dive and @child_nodes
131
+ if dive && @child_nodes
117
132
  ropts = opts.dup
118
133
  if rpath
119
134
  if rpath.empty?
@@ -131,9 +146,12 @@ module TermUtils
131
146
  end
132
147
  nil
133
148
  end
149
+
134
150
  # Collects nodes.
135
- # @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
136
- # @return [Array<TermUtils::PropertyTreeNode>]
151
+ # @param opts [Hash]
152
+ # @option opts [Array] :path
153
+ # @option opts [Boolean] :leaf_only
154
+ # @return [Array<PropertyTreeNode>]
137
155
  def collect_nodes(opts = {})
138
156
  nodes = []
139
157
  each_node(opts) do |n|
@@ -141,8 +159,11 @@ module TermUtils
141
159
  end
142
160
  nodes
143
161
  end
162
+
144
163
  # Collects node paths.
145
- # @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
164
+ # @param opts [Hash]
165
+ # @option opts [Array] :path
166
+ # @option opts [Boolean] :leaf_only
146
167
  # @return [Array<Array<Object>>]
147
168
  def collect_paths(opts = {})
148
169
  paths = []
@@ -151,8 +172,11 @@ module TermUtils
151
172
  end
152
173
  paths
153
174
  end
175
+
154
176
  # Collect node values.
155
- # @param opts [Hash<Symbol,Object>] `:path`, `:leaf_only`
177
+ # @param opts [Hash]
178
+ # @option opts [Array] :path
179
+ # @option opts [Boolean] :leaf_only
156
180
  # @return [Array<Object>]
157
181
  def collect_values(opts = {})
158
182
  vals = []
@@ -161,23 +185,26 @@ module TermUtils
161
185
  end
162
186
  vals
163
187
  end
188
+
164
189
  # Finds the node identified by a given path of keys.
165
190
  # @param path [Array<Object>]
166
- # @return [TermUtils::PropertyTreeNode]
191
+ # @return [PropertyTreeNode]
167
192
  def find_node(path)
168
193
  catch :found do
169
- each_node(:path => path) do |n|
194
+ each_node(path: path) do |n|
170
195
  throw :found, n
171
196
  end
172
197
  nil
173
198
  end
174
199
  end
200
+
175
201
  # Tests whether the node identified by a given path of keys exists.
176
202
  # @param path [Array<Object>]
177
203
  # @return [Boolean]
178
204
  def node_exists?(path)
179
205
  find_node(path) != nil
180
206
  end
207
+
181
208
  # Evaluates the total number of nodes in the tree represented by this one.
182
209
  # @param path [Array<Object>]
183
210
  # @return [Integer]
@@ -187,6 +214,7 @@ module TermUtils
187
214
  node.child_nodes ? node.child_nodes.length : 0
188
215
  end
189
216
  end
217
+
190
218
  # Finds the node identified by a given path of keys and returns its value.
191
219
  # @param path [Array<Object>]
192
220
  # @return [Object]