yaml_smith 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/AGENTS.md +6 -1
- data/README.md +13 -1
- data/lib/yaml_smith/add_key.rb +5 -3
- data/lib/yaml_smith/file_command.rb +43 -0
- data/lib/yaml_smith/set_key.rb +4 -2
- data/lib/yaml_smith/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1ae84128e5a9fd8e27052c2ae46fd0c824360a603a8e83bc939758c084ee9ca1
|
|
4
|
+
data.tar.gz: 1790ba5fa65a520ac3a55aa0ca0c718d65794c4abb007343b7e3a46cf5d740b2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 73c9db95bdbcbd3c7396e65387ef77d20dc64bef997db73700df90590b852db1f6c9461d1ef18f60a0c8e6d7c7d81eeeac6c0f88539556b39faccd946a62a395
|
|
7
|
+
data.tar.gz: 9746fcbffa82ccf28b8f8b1e21bba0286f7b5f3c5f157e46cf036368fa98b5f2de5d27098ad5064e26180de5c0fe2ff7b9881f967ee3e0ec2b16675528159212
|
data/AGENTS.md
CHANGED
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
- `exe/yaml-smith` is only the executable wrapper; CLI dispatch and error handling belong in `lib/yaml_smith/cli.rb`.
|
|
13
13
|
- Each command has its own class and file: `AddKey`, `SetKey`, and `DeleteKey`.
|
|
14
14
|
- Shared file loading, validation, and atomic writing live in `YamlSmith::FileCommand`.
|
|
15
|
-
-
|
|
15
|
+
- `AddKey` and `SetKey` accept a nested path in their `key` argument using dot
|
|
16
|
+
notation (e.g. `services.0.name`) or bracket notation (e.g. `services[0].name`).
|
|
17
|
+
Numeric segments index into arrays. `FileCommand#resolve_container` navigates
|
|
18
|
+
intermediate segments of the path, which must already exist; the final key may
|
|
19
|
+
be missing (for `set`, it is then added). `DeleteKey` searches matching keys
|
|
20
|
+
recursively and does not take a path.
|
|
16
21
|
|
|
17
22
|
## YAML Behavior
|
|
18
23
|
|
data/README.md
CHANGED
|
@@ -28,12 +28,24 @@ yaml-smith add config.yml timeout 30
|
|
|
28
28
|
The value is parsed as YAML, so values such as `true`, `null`, arrays, and
|
|
29
29
|
objects retain their YAML types. Existing keys are not overwritten.
|
|
30
30
|
|
|
31
|
-
Set or replace a
|
|
31
|
+
Set or replace a key:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
34
|
yaml-smith set config.yml timeout 60
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
Add and set also accept a nested path using dot notation, with numeric
|
|
38
|
+
segments indexing into arrays. For example, this renames the web service in a
|
|
39
|
+
Render configuration:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
yaml-smith set render.yaml services.0.name rails_foo
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Bracket notation is accepted as well: `services[0].name`. Intermediate
|
|
46
|
+
segments of the path must already exist; the final key may be missing (for
|
|
47
|
+
`set`, it is added).
|
|
48
|
+
|
|
37
49
|
Delete matching keys recursively:
|
|
38
50
|
|
|
39
51
|
```bash
|
data/lib/yaml_smith/add_key.rb
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module YamlSmith
|
|
4
|
-
# Adds a
|
|
4
|
+
# Adds a key to a YAML file. The key may be a top-level key or a nested
|
|
5
|
+
# path such as `services.0.name`.
|
|
5
6
|
class AddKey < FileCommand
|
|
6
7
|
def call
|
|
7
8
|
document = load_file(@path)
|
|
8
9
|
value = load(@value)
|
|
9
10
|
|
|
10
11
|
ensure_mapping(document)
|
|
11
|
-
|
|
12
|
+
container, final_key = resolve_container(document)
|
|
13
|
+
raise Error, "key already exists: #{@key}" if container.key?(final_key)
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
container[final_key] = value
|
|
14
16
|
write(Psych::Pure.dump(document))
|
|
15
17
|
end
|
|
16
18
|
end
|
|
@@ -33,6 +33,49 @@ module YamlSmith
|
|
|
33
33
|
raise Error, 'YAML document must contain a top-level mapping'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def resolve_container(document)
|
|
37
|
+
container = document
|
|
38
|
+
segments[0..-2].each { |segment| container = navigate(container, segment) }
|
|
39
|
+
[container, segments.last]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def navigate(container, segment)
|
|
43
|
+
if integer?(segment)
|
|
44
|
+
raise Error, "expected an array at '#{segment}'" unless container.instance_of?(Psych::Pure::LoadedArray)
|
|
45
|
+
|
|
46
|
+
index = Integer(segment)
|
|
47
|
+
raise Error, "segment does not exist: #{segment}" if index >= container.length
|
|
48
|
+
|
|
49
|
+
container[index]
|
|
50
|
+
else
|
|
51
|
+
raise Error, "expected a mapping at '#{segment}'" unless container.instance_of?(Psych::Pure::LoadedHash)
|
|
52
|
+
raise Error, "segment does not exist: #{segment}" unless container.key?(segment)
|
|
53
|
+
|
|
54
|
+
container[segment]
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def integer?(segment)
|
|
59
|
+
segment.match?(/\A\d+\z/)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def segments
|
|
63
|
+
@segments ||= parse_segments(@key)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def parse_segments(key)
|
|
67
|
+
return [key] unless key.include?('.') || key.include?('[')
|
|
68
|
+
|
|
69
|
+
key.scan(/[^.\s]+/).each_with_object([]) do |token, result|
|
|
70
|
+
segments = token.split('[')
|
|
71
|
+
result << segments[0] unless segments[0].empty?
|
|
72
|
+
|
|
73
|
+
segments[1..].each do |part|
|
|
74
|
+
result << part.delete_suffix(']')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
36
79
|
def write(contents)
|
|
37
80
|
mode = File.stat(@path).mode & 0o7777
|
|
38
81
|
|
data/lib/yaml_smith/set_key.rb
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module YamlSmith
|
|
4
|
-
# Sets a
|
|
4
|
+
# Sets a key in a YAML file, adding or replacing it. The key may be a
|
|
5
|
+
# top-level key or a nested path such as `services.0.name`.
|
|
5
6
|
class SetKey < FileCommand
|
|
6
7
|
def call
|
|
7
8
|
document = load_file(@path)
|
|
8
9
|
value = load(@value)
|
|
9
10
|
|
|
10
11
|
ensure_mapping(document)
|
|
11
|
-
|
|
12
|
+
container, final_key = resolve_container(document)
|
|
13
|
+
container[final_key] = value
|
|
12
14
|
write(Psych::Pure.dump(document))
|
|
13
15
|
end
|
|
14
16
|
end
|
data/lib/yaml_smith/version.rb
CHANGED