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,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]