glob 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1364c317c2dde1a64f6f201956383cd023185d64349b101e8d167326701cc4fa
4
- data.tar.gz: 76c07526698da02bb9792d29f3bafaa170fe03750f5bd335f7f80efb06114167
3
+ metadata.gz: 45093c60b816f8216b7f61ecf9a87d682ebed8e355812d5f182d951f5573fa50
4
+ data.tar.gz: 7cbeef3c989d6b06217a127ef54fca2e04dc0e26f60fb0bca27fdc69a4cc24ed
5
5
  SHA512:
6
- metadata.gz: 4fcc6b11d949bb8e941794c39b6e83efc39c7fd94be7d51a2314d3b50cd7afe680448759cd28c6abe17f4f8566ba5ff31332c0806a014b1c1f4fa8a490117332
7
- data.tar.gz: 5a15abeb7a6a9845fb00563f4b7ef5a53e0d432ca92f6fc239315ba38bd76fa84e1f68f9128c3aeec94834df1a2a94b50d32b3e929021af004fe1fbaab32d256
6
+ metadata.gz: d0fa710b8631ec0b85e9d86fb55fb666e82a709946b9209621e7da54cf41c6417056daeeba007b1b977b239e79cb86261f1af9eebe30d00b8e1926cee05f9af2
7
+ data.tar.gz: cb099c539ea6b9317ed8622a22c9eddd1bf25ca5ca058eb1b9a5d328aa63924c10ac825c5fcc8c3a63d4c962de1c31109d31fb03fa59412851552a531f41fbb9
data/CHANGELOG.md CHANGED
@@ -11,6 +11,19 @@ Prefix your message with one of the following:
11
11
  - [Security] in case of vulnerabilities.
12
12
  -->
13
13
 
14
+ ## v0.4.0 - 2022-12-05
15
+
16
+ - [Changed] `Glob::Query` has been renamed to `Glob::Object`.
17
+ - [Added] Allow adding new keys with `glob.set(path, value)`.
18
+
19
+ ## v0.3.1 - 2022-09-01
20
+
21
+ - [Fixed] Handle keys with dots properly by using `\\.` as a escape sequence.
22
+
23
+ ## v0.3.0 - 2022-08-01
24
+
25
+ - [Added] Patterns can have groups like in `{a,b}.*`.
26
+
14
27
  ## v0.2.2 - 2022-02-01
15
28
 
16
29
  - [Fixed] Properly handle numeric keys.
data/README.md CHANGED
@@ -72,6 +72,61 @@ glob.to_h
72
72
 
73
73
  Notice that the return result will have symbolized keys.
74
74
 
75
+ If the key contain dots, then the result will use `\\.` as the escape sequence.
76
+ Similarly, you need to escape keys with dots when filtering results.
77
+
78
+ ```ruby
79
+ glob = Glob.new(
80
+ formats: {
81
+ ".txt" => "Text",
82
+ ".json" => "JSON",
83
+ ".rb" => "Ruby"
84
+ }
85
+ )
86
+
87
+ glob << "*"
88
+
89
+ glob.paths
90
+ #=> ["formats.\\.json", "formats.\\.rb", "formats.\\.txt"]
91
+
92
+ glob.to_h
93
+ #=> {:formats=>{:".json"=>"JSON", :".rb"=>"Ruby", :".txt"=>"Text"}}
94
+
95
+ # Remove all existing matchers
96
+ glob.matchers.clear
97
+
98
+ glob << "formats.\\.rb"
99
+
100
+ glob.paths
101
+ #=> ["formats.\\.rb"]
102
+
103
+ glob.to_h
104
+ #=> {:formats=>{:".rb"=>"Ruby"}}
105
+ ```
106
+
107
+ You can set new keys by using `.set(path, value)`:
108
+
109
+ ```ruby
110
+ glob = Glob.new
111
+ glob << "*"
112
+ glob.set "a.b.c", "hello"
113
+
114
+ glob.to_h
115
+ #=> {:a=>{:b=>{:c=>"hello"}}}
116
+
117
+ glob.paths
118
+ #=> ["a.b.c"]
119
+
120
+ # The non-hash value will be replaced in case the new path overlaps it
121
+ glob.set "a.b.c.d.e", "hello"
122
+
123
+ glob.to_h
124
+ #=> {:a=>{:b=>{:c=>{:d=>{:e=>"hello"}}}}}
125
+
126
+ glob.paths
127
+ #=> ["a.b.c.d.e"]
128
+ ```
129
+
75
130
  ## Maintainer
76
131
 
77
132
  - [Nando Vieira](https://github.com/fnando)
data/lib/glob/map.rb CHANGED
@@ -7,21 +7,24 @@ module Glob
7
7
  end
8
8
 
9
9
  def initialize(target)
10
- @keys = []
11
10
  @target = target
12
11
  end
13
12
 
14
13
  def call
15
14
  @target
16
- .map {|(key, value)| compute(value, key) }
15
+ .map {|(key, value)| compute(value, escape(key)) }
17
16
  .flatten
18
17
  .sort
19
18
  end
20
19
 
20
+ private def escape(key)
21
+ key.to_s.gsub(".", "\\.")
22
+ end
23
+
21
24
  private def compute(value, path)
22
25
  if value.is_a?(Hash)
23
26
  value.map do |key, other_value|
24
- compute(other_value, "#{path}.#{key}")
27
+ compute(other_value, "#{path}.#{escape(key)}")
25
28
  end
26
29
  else
27
30
  path.to_s
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Glob
4
- class Query
4
+ class Object
5
+ PATH_SPLIT_RE = /(?<!\\)\./.freeze
6
+
5
7
  attr_reader :matchers
6
8
 
7
9
  def initialize(target)
@@ -18,13 +20,20 @@ module Glob
18
20
  symbolized_target = SymbolizeKeys.call(@target)
19
21
 
20
22
  paths.each_with_object({}) do |path, buffer|
21
- segments = path.split(".").map(&:to_sym)
23
+ segments = path.split(PATH_SPLIT_RE).map {|key| unescape(key).to_sym }
22
24
  value = symbolized_target.dig(*segments)
23
25
  set_path_value(segments, buffer, value)
24
26
  end
25
27
  end
26
28
  alias to_hash to_h
27
29
 
30
+ def set(path, value)
31
+ set_path_value(path.split(PATH_SPLIT_RE), @target, value)
32
+ @map = Map.call(@target)
33
+
34
+ nil
35
+ end
36
+
28
37
  def paths
29
38
  matches = map.map do |path|
30
39
  results = matchers.select {|matcher| matcher.match?(path) } # rubocop:disable Style/SelectByRegexp
@@ -41,12 +50,19 @@ module Glob
41
50
  @map ||= Map.call(@target)
42
51
  end
43
52
 
53
+ private def unescape(key)
54
+ key.to_s.gsub(/\\\./, ".")
55
+ end
56
+
44
57
  private def set_path_value(segments, target, value)
58
+ segments = segments.dup.map(&:to_sym)
59
+
45
60
  while (segment = segments.shift)
46
61
  if segments.empty?
47
62
  target[segment] = value
48
63
  else
49
64
  target[segment] ||= {}
65
+ target[segment] = {} unless target[segment].is_a?(Hash)
50
66
  target = target[segment]
51
67
  end
52
68
  end
data/lib/glob/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Glob
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
data/lib/glob.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "glob/map"
4
- require "glob/query"
5
- require "glob/matcher"
6
- require "glob/symbolize_keys"
7
- require "glob/version"
3
+ require_relative "glob/map"
4
+ require_relative "glob/object"
5
+ require_relative "glob/matcher"
6
+ require_relative "glob/symbolize_keys"
7
+ require_relative "glob/version"
8
8
 
9
9
  module Glob
10
10
  def self.filter(target, paths = ["*"])
@@ -13,7 +13,7 @@ module Glob
13
13
  glob.to_h
14
14
  end
15
15
 
16
- def self.new(target)
17
- Query.new(target)
16
+ def self.new(target = {})
17
+ Object.new(target)
18
18
  end
19
19
  end
data/test/glob_test.rb CHANGED
@@ -220,4 +220,60 @@ class GlobTest < Minitest::Test
220
220
 
221
221
  assert_equal expected, glob.paths
222
222
  end
223
+
224
+ test "with keys that contain dots" do
225
+ data = {
226
+ "keys.with.dots" => "dots",
227
+ node: {
228
+ "more.keys.with.dots" => "more dots"
229
+ }
230
+ }
231
+
232
+ glob = Glob.new(data)
233
+
234
+ glob << "*"
235
+
236
+ assert_equal %w[keys\\.with\\.dots node.more\\.keys\\.with\\.dots],
237
+ glob.paths
238
+ assert_equal Glob::SymbolizeKeys.call(data), glob.to_h
239
+
240
+ assert_equal ({node: {"more.keys.with.dots": "more dots"}}),
241
+ Glob.filter(data, ["node.more\\.keys\\.with\\.dots"])
242
+ end
243
+
244
+ test "sorts set when setting new keys" do
245
+ data = {d: "d", a: "a", b: "b"}
246
+
247
+ glob = Glob.new(data)
248
+ glob << "*"
249
+
250
+ assert_equal({a: "a", b: "b", d: "d"}, glob.to_h)
251
+
252
+ glob.set("c", "c")
253
+ glob.set("e.b1.b2.b3", "e---b")
254
+ glob.set("e.a1.a2.a3", "e---a")
255
+
256
+ expected = {
257
+ a: "a", b: "b", c: "c", d: "d",
258
+ e: {a1: {a2: {a3: "e---a"}}, b1: {b2: {b3: "e---b"}}}
259
+ }
260
+
261
+ assert_equal(expected, glob.to_h)
262
+ assert_equal ["a", "b", "c", "d", "e.a1.a2.a3", "e.b1.b2.b3"], glob.paths
263
+ end
264
+
265
+ test "replaces existing node when setting a new path" do
266
+ glob = Glob.new(a: 1, b: {b1: {b2: 2}})
267
+ glob << "*"
268
+ glob.set("a.a1.a2", 4)
269
+ glob.set("b.b1.b2.b3", {b4: 5})
270
+
271
+ expected = {
272
+ a: {a1: {a2: 4}},
273
+ b: {b1: {b2: {b3: {b4: 5}}}}
274
+ }
275
+
276
+ assert_equal expected, glob.to_h
277
+ assert_equal ["a.a1.a2", "b.b1.b2.b3.b4"], glob.paths
278
+ end
223
279
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glob
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-01 00:00:00.000000000 Z
11
+ date: 2022-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -138,7 +138,7 @@ files:
138
138
  - lib/glob.rb
139
139
  - lib/glob/map.rb
140
140
  - lib/glob/matcher.rb
141
- - lib/glob/query.rb
141
+ - lib/glob/object.rb
142
142
  - lib/glob/symbolize_keys.rb
143
143
  - lib/glob/version.rb
144
144
  - test/glob/map_test.rb
@@ -152,10 +152,10 @@ metadata:
152
152
  rubygems_mfa_required: 'true'
153
153
  homepage_uri: https://github.com/fnando/glob
154
154
  bug_tracker_uri: https://github.com/fnando/glob/issues
155
- source_code_uri: https://github.com/fnando/glob/tree/v0.3.0
156
- changelog_uri: https://github.com/fnando/glob/tree/v0.3.0/CHANGELOG.md
157
- documentation_uri: https://github.com/fnando/glob/tree/v0.3.0/README.md
158
- license_uri: https://github.com/fnando/glob/tree/v0.3.0/LICENSE.md
155
+ source_code_uri: https://github.com/fnando/glob/tree/v0.4.0
156
+ changelog_uri: https://github.com/fnando/glob/tree/v0.4.0/CHANGELOG.md
157
+ documentation_uri: https://github.com/fnando/glob/tree/v0.4.0/README.md
158
+ license_uri: https://github.com/fnando/glob/tree/v0.4.0/LICENSE.md
159
159
  post_install_message:
160
160
  rdoc_options: []
161
161
  require_paths:
@@ -171,7 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubygems_version: 3.3.7
174
+ rubygems_version: 3.3.26
175
175
  signing_key:
176
176
  specification_version: 4
177
177
  summary: Create a list of hash paths that match a given pattern. You can also generate