yerba 0.2.2-aarch64-linux-gnu → 0.4.0-aarch64-linux-gnu
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/README.md +167 -12
- data/exe/aarch64-linux-gnu/yerba +0 -0
- data/ext/yerba/extconf.rb +39 -12
- data/ext/yerba/include/yerba.h +21 -10
- data/ext/yerba/yerba.c +91 -25
- data/lib/yerba/3.2/yerba.so +0 -0
- data/lib/yerba/3.3/yerba.so +0 -0
- data/lib/yerba/3.4/yerba.so +0 -0
- data/lib/yerba/4.0/yerba.so +0 -0
- data/lib/yerba/collection.rb +35 -0
- data/lib/yerba/document.rb +16 -0
- data/lib/yerba/sequence.rb +169 -1
- data/lib/yerba/version.rb +1 -1
- data/lib/yerba.rb +7 -2
- data/rust/Cargo.lock +1 -1
- data/rust/Cargo.toml +2 -2
- data/rust/cbindgen.toml +1 -0
- data/rust/rustfmt.toml +1 -1
- data/rust/src/commands/blank_lines.rs +1 -4
- data/rust/src/commands/delete.rs +9 -4
- data/rust/src/commands/directives.rs +61 -0
- data/rust/src/commands/get.rs +52 -26
- data/rust/src/commands/insert.rs +8 -4
- data/rust/src/commands/mod.rs +71 -9
- data/rust/src/commands/move_item.rs +2 -1
- data/rust/src/commands/move_key.rs +2 -1
- data/rust/src/commands/quote_style.rs +12 -6
- data/rust/src/commands/remove.rs +8 -4
- data/rust/src/commands/rename.rs +8 -4
- data/rust/src/commands/selectors.rs +158 -0
- data/rust/src/commands/set.rs +33 -16
- data/rust/src/commands/sort.rs +342 -10
- data/rust/src/didyoumean.rs +53 -0
- data/rust/src/document/condition.rs +139 -0
- data/rust/src/document/delete.rs +91 -0
- data/rust/src/document/get.rs +262 -0
- data/rust/src/document/insert.rs +314 -0
- data/rust/src/document/mod.rs +784 -0
- data/rust/src/document/set.rs +90 -0
- data/rust/src/document/sort.rs +607 -0
- data/rust/src/document/style.rs +473 -0
- data/rust/src/error.rs +35 -7
- data/rust/src/ffi.rs +213 -520
- data/rust/src/json.rs +1 -7
- data/rust/src/lib.rs +89 -2
- data/rust/src/main.rs +2 -0
- data/rust/src/quote_style.rs +83 -7
- data/rust/src/selector.rs +2 -7
- data/rust/src/syntax.rs +41 -21
- data/rust/src/yerbafile.rs +39 -18
- metadata +13 -3
- data/rust/src/document.rs +0 -2237
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d03479e01e585ef3c9b732145696a285f8a06142c239e3ba5f00e1b146914389
|
|
4
|
+
data.tar.gz: 7f9ad50af81264bb9d1c8195fba77e2e4c08fac7d057a5769c11bf2023824229
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: daa8055162a44b0332784c71dd8649c9892fe9749ffa595871a093c15a5e50f4172ce4d4afceeaad11adc720a2c14545293a1e43c0dc7753b21f32100c4d082c
|
|
7
|
+
data.tar.gz: 4e870605584375aae588dfdba9fa3353e95a8b2fb7f5a73bc51a1d866b040fa4f9247c5faf796e075dcb4c4dc843124aac9224cafa6ac425b8e2d4a37d7b16d5
|
data/README.md
CHANGED
|
@@ -47,13 +47,15 @@ Use `yerba` as a library in your Rust project:
|
|
|
47
47
|
|
|
48
48
|
```toml
|
|
49
49
|
[dependencies]
|
|
50
|
-
yerba = "0.
|
|
50
|
+
yerba = "0.4"
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
```rust
|
|
54
54
|
let mut document = yerba::parse_file("config.yml")?;
|
|
55
55
|
document.set("database.host", "0.0.0.0")?;
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
document.save()?; // saves to original path
|
|
58
|
+
document.save_to("output.yml")?; // saves to new path
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
### Ruby Gem
|
|
@@ -162,6 +164,12 @@ Use `--condition` to only apply the change when a sibling field matches:
|
|
|
162
164
|
yerba set config.yml "database.host" "0.0.0.0" --condition ".port == 5432"
|
|
163
165
|
```
|
|
164
166
|
|
|
167
|
+
Use `--all` to update all nodes matching a wildcard selector:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
yerba set videos.yml "[].description" "" --all
|
|
171
|
+
```
|
|
172
|
+
|
|
165
173
|
### `insert`
|
|
166
174
|
|
|
167
175
|
Insert a new key into a map or a new item into a sequence. By default, new items are appended at the end.
|
|
@@ -249,15 +257,25 @@ yerba move-key config.yml "database.pool" --after "database.name"
|
|
|
249
257
|
|
|
250
258
|
### `sort`
|
|
251
259
|
|
|
252
|
-
Sort items in a sequence. For simple scalar sequences, no options are needed. For sequences of maps, use `--by` to specify sort
|
|
260
|
+
Sort items in a sequence. For simple scalar sequences, no options are needed. For sequences of maps, use `--by` to specify the sort field. Use `--order desc` for descending. Repeat `--by` and `--order` for tie-breakers:
|
|
253
261
|
|
|
254
262
|
```bash
|
|
255
263
|
yerba sort config.yml "tags"
|
|
256
|
-
yerba sort videos.yml --by "title"
|
|
257
|
-
yerba sort videos.yml --by "date
|
|
258
|
-
yerba sort videos.yml "[].speakers" --by "name"
|
|
264
|
+
yerba sort videos.yml --by ".title"
|
|
265
|
+
yerba sort videos.yml --by ".date" --order desc --by ".title"
|
|
266
|
+
yerba sort videos.yml "[].speakers" --by ".name"
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Use `--order` with a comma-separated list to specify an explicit custom order. All items must be listed:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
yerba sort videos.yml "[]" --by ".id" --order "talk-c,talk-a,talk-b"
|
|
273
|
+
yerba sort speakers.yml "[]" --by ".name" --order "Charlie,Alice,Bob"
|
|
274
|
+
yerba sort config.yml "tags" --by "." --order "yaml,ruby,rust"
|
|
259
275
|
```
|
|
260
276
|
|
|
277
|
+
This is useful for reordering items in a specific sequence (e.g., conference schedule order, priority lists) or when an LLM agent needs to rearrange items programmatically.
|
|
278
|
+
|
|
261
279
|
### `sort-keys`
|
|
262
280
|
|
|
263
281
|
Reorder the keys in a map to match a predefined order. If any key in the document is not present in the order list, the command aborts with an error, this ensures you account for every field:
|
|
@@ -270,7 +288,7 @@ yerba sort-keys "data/**/videos.yml" "[]" "id,title,speakers"
|
|
|
270
288
|
|
|
271
289
|
### `quote-style`
|
|
272
290
|
|
|
273
|
-
Enforce a consistent quote style across keys and/or values
|
|
291
|
+
Enforce a consistent quote style across keys and/or values:
|
|
274
292
|
|
|
275
293
|
```bash
|
|
276
294
|
yerba quote-style config.yml --values double
|
|
@@ -285,6 +303,36 @@ yerba quote-style config.yml "[].speakers" --values plain
|
|
|
285
303
|
yerba quote-style "data/**/*.yml" --keys plain --values double
|
|
286
304
|
```
|
|
287
305
|
|
|
306
|
+
Use block scalar styles to enforce multiline formatting on specific fields:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
yerba quote-style videos.yml "[].description" --values literal
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Key styles** (`--keys`):
|
|
313
|
+
|
|
314
|
+
| Style | Symbol | Example |
|
|
315
|
+
|-------|--------|---------|
|
|
316
|
+
| `plain` | — | `host: value` |
|
|
317
|
+
| `single` | `'` | `'host': value` |
|
|
318
|
+
| `double` | `"` | `"host": value` |
|
|
319
|
+
|
|
320
|
+
**Value styles** (`--values`):
|
|
321
|
+
|
|
322
|
+
| Style | Symbol | Example | Behavior |
|
|
323
|
+
|-------|--------|---------|----------|
|
|
324
|
+
| `plain` | — | `host: localhost` | Unquoted |
|
|
325
|
+
| `single` | `'` | `host: 'localhost'` | Single-quoted |
|
|
326
|
+
| `double` | `"` | `host: "localhost"` | Double-quoted, supports `\n` escapes |
|
|
327
|
+
| `literal` | `\|-` | Preserves newlines | Strip trailing newline |
|
|
328
|
+
| `literal-clip` | `\|` | Preserves newlines | Keep one trailing newline |
|
|
329
|
+
| `literal-keep` | `\|+` | Preserves newlines | Keep all trailing newlines |
|
|
330
|
+
| `folded` | `>-` | Folds newlines to spaces | Strip trailing newline |
|
|
331
|
+
| `folded-clip` | `>` | Folds newlines to spaces | Keep one trailing newline |
|
|
332
|
+
| `folded-keep` | `>+` | Folds newlines to spaces | Keep all trailing newlines |
|
|
333
|
+
|
|
334
|
+
Block scalars are only converted when scoped to a specific selector. An unscoped `--values double` will not touch existing block scalars.
|
|
335
|
+
|
|
288
336
|
### `blank-lines`
|
|
289
337
|
|
|
290
338
|
Enforce a consistent number of blank lines between sequence entries:
|
|
@@ -295,6 +343,67 @@ yerba blank-lines videos.yml "[]" 1
|
|
|
295
343
|
yerba blank-lines config.yml "tags" 0
|
|
296
344
|
```
|
|
297
345
|
|
|
346
|
+
### `directives`
|
|
347
|
+
|
|
348
|
+
Add or remove the document start marker (`---`):
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
yerba directives config.yml --ensure
|
|
352
|
+
yerba directives config.yml --remove
|
|
353
|
+
yerba directives "data/**/*.yml" --ensure
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### `selectors`
|
|
357
|
+
|
|
358
|
+
Show all valid selectors for a YAML file. Useful for discovering the structure of a file and knowing which selectors you can use with other commands:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
yerba selectors config.yml
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
Output:
|
|
365
|
+
```
|
|
366
|
+
database
|
|
367
|
+
database.host
|
|
368
|
+
database.port
|
|
369
|
+
tags
|
|
370
|
+
tags[]
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
For sequences of objects:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
yerba selectors videos.yml
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Output:
|
|
380
|
+
```
|
|
381
|
+
[]
|
|
382
|
+
[].id
|
|
383
|
+
[].title
|
|
384
|
+
[].speakers
|
|
385
|
+
[].speakers[]
|
|
386
|
+
[].speakers[].name
|
|
387
|
+
[].speakers[].slug
|
|
388
|
+
[].video_id
|
|
389
|
+
[].video_provider
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Pass a selector to scope the output to a specific subtree:
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
yerba selectors config.yml "database"
|
|
396
|
+
yerba selectors videos.yml "[]"
|
|
397
|
+
yerba selectors videos.yml "[].speakers"
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Works with glob patterns to show the union of selectors across multiple files:
|
|
401
|
+
|
|
402
|
+
```bash
|
|
403
|
+
yerba selectors "data/**/videos.yml"
|
|
404
|
+
yerba selectors "data/**/videos.yml" "[]"
|
|
405
|
+
```
|
|
406
|
+
|
|
298
407
|
## `Yerbafile`
|
|
299
408
|
|
|
300
409
|
A `Yerbafile` is a YAML configuration file that defines formatting and editing rules as pipelines of operations that are applied to your files across your project.
|
|
@@ -358,6 +467,7 @@ Available pipeline steps:
|
|
|
358
467
|
- `delete` Remove a key (supports conditions)
|
|
359
468
|
- `rename` Rename a key
|
|
360
469
|
- `remove` Remove an item from a sequence
|
|
470
|
+
- `directives` Add or remove the document start marker (`---`)
|
|
361
471
|
- `get` Read a value and store it as a variable for subsequent steps
|
|
362
472
|
|
|
363
473
|
This makes it easy to enforce project-wide YAML conventions in CI:
|
|
@@ -428,6 +538,12 @@ document["database"]["host"].value = "0.0.0.0"
|
|
|
428
538
|
document.set("database.port", 3306)
|
|
429
539
|
```
|
|
430
540
|
|
|
541
|
+
Set all matching nodes at once with `all: true`:
|
|
542
|
+
|
|
543
|
+
```ruby
|
|
544
|
+
document.set("[].description", "", all: true)
|
|
545
|
+
```
|
|
546
|
+
|
|
431
547
|
Insert new keys with positional control:
|
|
432
548
|
|
|
433
549
|
```ruby
|
|
@@ -441,7 +557,44 @@ tags = document["tags"]
|
|
|
441
557
|
tags << "yaml"
|
|
442
558
|
tags << { name: "Rust", version: "1.80" }
|
|
443
559
|
tags.remove("obsolete")
|
|
444
|
-
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
### Sorting
|
|
563
|
+
|
|
564
|
+
Sort sequences in place. Works on both the document and sequence level:
|
|
565
|
+
|
|
566
|
+
```ruby
|
|
567
|
+
document.sort(by: :name)
|
|
568
|
+
document.sort(by: :name, order: :desc)
|
|
569
|
+
document.sort(by: :name, order: ["Charlie", "Bob", "Alice"])
|
|
570
|
+
document.sort("tags")
|
|
571
|
+
document.sort("tags", order: :desc)
|
|
572
|
+
document.sort("tags", order: ["rust", "ruby", "go"])
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
The `by:` option accepts symbols, strings, or dot-prefixed strings (`:name`, `"name"`, `".name"`).
|
|
576
|
+
|
|
577
|
+
### Querying
|
|
578
|
+
|
|
579
|
+
Find and filter items in sequences with `find_by`, `where`, and `pluck`:
|
|
580
|
+
|
|
581
|
+
```ruby
|
|
582
|
+
document.find_by(name: "Alice")
|
|
583
|
+
document.where(role: "admin")
|
|
584
|
+
document.pluck(:name)
|
|
585
|
+
|
|
586
|
+
document.find_by(speakers: { name: "Alice" })
|
|
587
|
+
document.where(tags: ["ruby"])
|
|
588
|
+
document.find_by("database.host": "localhost")
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
These methods work on `Document` (delegates to root), `Sequence`, and `Collection` (searches across files):
|
|
592
|
+
|
|
593
|
+
```ruby
|
|
594
|
+
collection = Yerba.files("data/**/*.yml")
|
|
595
|
+
collection.find_by(name: "Alice")
|
|
596
|
+
collection.where(kind: "talk")
|
|
597
|
+
collection.pluck(:name)
|
|
445
598
|
```
|
|
446
599
|
|
|
447
600
|
### Quote Style Control
|
|
@@ -450,7 +603,7 @@ Read and set the quote style on individual scalars:
|
|
|
450
603
|
|
|
451
604
|
```ruby
|
|
452
605
|
scalar = document["database.host"]
|
|
453
|
-
scalar.quote_style
|
|
606
|
+
scalar.quote_style # => :double
|
|
454
607
|
scalar.quote_style = :single
|
|
455
608
|
```
|
|
456
609
|
|
|
@@ -474,6 +627,10 @@ collection.each do |document|
|
|
|
474
627
|
puts document.get("[0].title")
|
|
475
628
|
end
|
|
476
629
|
|
|
630
|
+
collection.find_by(name: "Alice")
|
|
631
|
+
collection.where(kind: "talk")
|
|
632
|
+
collection.pluck(:name)
|
|
633
|
+
|
|
477
634
|
collection.apply! do |document|
|
|
478
635
|
document.set("status", "published")
|
|
479
636
|
end
|
|
@@ -499,10 +656,9 @@ After checking out the repo, run `bundle install` to install Ruby dependencies,
|
|
|
499
656
|
|
|
500
657
|
### Building from source
|
|
501
658
|
|
|
502
|
-
The Rust core is in the `rust/` directory:
|
|
659
|
+
The Rust core is in the `rust/` directory, with a workspace `Cargo.toml` at the root so all cargo commands work from the project root:
|
|
503
660
|
|
|
504
661
|
```bash
|
|
505
|
-
cd rust
|
|
506
662
|
cargo build
|
|
507
663
|
cargo test
|
|
508
664
|
```
|
|
@@ -518,7 +674,6 @@ cargo run -- get config.yml "database.host"
|
|
|
518
674
|
Or build a release binary:
|
|
519
675
|
|
|
520
676
|
```bash
|
|
521
|
-
cd rust
|
|
522
677
|
cargo build --release
|
|
523
678
|
./target/release/yerba --help
|
|
524
679
|
```
|
data/exe/aarch64-linux-gnu/yerba
CHANGED
|
Binary file
|
data/ext/yerba/extconf.rb
CHANGED
|
@@ -44,22 +44,41 @@ if cross_compiling && target_platform.nil?
|
|
|
44
44
|
end
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
workspace_target_dir = File.join(root_dir, "target")
|
|
48
|
+
crate_target_dir = File.join(rust_dir, "target")
|
|
49
|
+
|
|
47
50
|
if target_platform
|
|
48
51
|
puts "yerba: Cross-compiling Rust for target: #{target_platform}"
|
|
49
52
|
system("rustup target add #{target_platform}") || warn("yerba: Failed to add Rust target #{target_platform}")
|
|
50
53
|
|
|
51
54
|
cargo_args = "--release --target #{target_platform}"
|
|
52
|
-
lib_dir =
|
|
55
|
+
lib_dir = [workspace_target_dir, crate_target_dir]
|
|
56
|
+
.map { |dir| File.join(dir, target_platform, "release") }
|
|
57
|
+
.find { |dir| Dir.exist?(dir) } || File.join(crate_target_dir, target_platform, "release")
|
|
53
58
|
else
|
|
54
59
|
puts "yerba: Compiling Rust library for native platform..."
|
|
60
|
+
|
|
55
61
|
cargo_args = "--release"
|
|
56
|
-
|
|
62
|
+
|
|
63
|
+
lib_dir = [workspace_target_dir, crate_target_dir]
|
|
64
|
+
.map { |dir| File.join(dir, "release") }
|
|
65
|
+
.find { |dir| Dir.exist?(dir) } || File.join(crate_target_dir, "release")
|
|
57
66
|
end
|
|
58
67
|
|
|
59
|
-
unless system("cd #{
|
|
68
|
+
unless system("cd #{root_dir} && cargo build #{cargo_args}")
|
|
60
69
|
abort "ERROR: Failed to compile yerba from Rust source."
|
|
61
70
|
end
|
|
62
71
|
|
|
72
|
+
lib_dir = if target_platform
|
|
73
|
+
[workspace_target_dir, crate_target_dir]
|
|
74
|
+
.map { |dir| File.join(dir, target_platform, "release") }
|
|
75
|
+
.find { |dir| Dir.exist?(dir) } || lib_dir
|
|
76
|
+
else
|
|
77
|
+
[workspace_target_dir, crate_target_dir]
|
|
78
|
+
.map { |dir| File.join(dir, "release") }
|
|
79
|
+
.find { |dir| Dir.exist?(dir) } || lib_dir
|
|
80
|
+
end
|
|
81
|
+
|
|
63
82
|
if target_platform
|
|
64
83
|
platform_key = ENV.fetch("RCD_PLATFORM", "")
|
|
65
84
|
else
|
|
@@ -93,19 +112,27 @@ if target_platform
|
|
|
93
112
|
end
|
|
94
113
|
end
|
|
95
114
|
|
|
96
|
-
|
|
115
|
+
static_lib = File.join(lib_dir, "libyerba.a")
|
|
97
116
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
117
|
+
if File.exist?(static_lib)
|
|
118
|
+
puts "yerba: Static library found at #{static_lib}"
|
|
119
|
+
$LDFLAGS << " #{static_lib}"
|
|
120
|
+
else
|
|
121
|
+
lib_path = File.join(lib_dir, lib_name)
|
|
101
122
|
|
|
102
|
-
|
|
123
|
+
unless File.exist?(lib_path)
|
|
124
|
+
abort "ERROR: Shared library not found at #{lib_path}"
|
|
125
|
+
end
|
|
103
126
|
|
|
104
|
-
|
|
105
|
-
|
|
127
|
+
puts "yerba: Shared library found at #{lib_path} (dynamic)"
|
|
128
|
+
|
|
129
|
+
$LDFLAGS << " -L#{lib_dir} -lyerba"
|
|
106
130
|
|
|
107
|
-
if RbConfig::CONFIG["host_os"].match?(/darwin|linux/)
|
|
108
|
-
|
|
131
|
+
if RbConfig::CONFIG["host_os"].match?(/darwin|linux/)
|
|
132
|
+
$LDFLAGS << " -Wl,-rpath,#{lib_dir}"
|
|
133
|
+
end
|
|
109
134
|
end
|
|
110
135
|
|
|
136
|
+
$CFLAGS << " -I#{File.join(__dir__, "include")}"
|
|
137
|
+
|
|
111
138
|
create_makefile("yerba/yerba")
|
data/ext/yerba/include/yerba.h
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
#ifndef YERBA_H
|
|
8
8
|
#define YERBA_H
|
|
9
9
|
|
|
10
|
-
typedef enum
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
10
|
+
typedef enum NodeType {
|
|
11
|
+
NODE_TYPE_SCALAR = 0,
|
|
12
|
+
NODE_TYPE_MAP = 1,
|
|
13
|
+
NODE_TYPE_SEQUENCE = 2,
|
|
14
|
+
NODE_TYPE_NOT_FOUND = 3,
|
|
15
|
+
} NodeType;
|
|
16
16
|
|
|
17
17
|
typedef enum YerbaValueType {
|
|
18
18
|
YERBA_VALUE_TYPE_NULL = 0,
|
|
@@ -50,7 +50,7 @@ typedef struct YerbaLocation {
|
|
|
50
50
|
|
|
51
51
|
typedef struct YerbaGetResult {
|
|
52
52
|
bool is_list;
|
|
53
|
-
enum
|
|
53
|
+
enum NodeType node_type;
|
|
54
54
|
struct YerbaTypedValue single;
|
|
55
55
|
struct YerbaTypedList list;
|
|
56
56
|
struct YerbaLocation location;
|
|
@@ -82,11 +82,11 @@ char *yerba_document_get_value(const struct Document *document, const char *path
|
|
|
82
82
|
*/
|
|
83
83
|
char *yerba_document_get_values(const struct Document *document, const char *path);
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
char *yerba_document_get_quote_style(const struct Document *document, const char *path);
|
|
86
86
|
|
|
87
87
|
struct YerbaResult yerba_document_set_quote_style(struct Document *document,
|
|
88
88
|
const char *path,
|
|
89
|
-
|
|
89
|
+
const char *style);
|
|
90
90
|
|
|
91
91
|
bool yerba_document_evaluate_condition(const struct Document *document,
|
|
92
92
|
const char *parent_path,
|
|
@@ -102,7 +102,8 @@ char *yerba_document_find(const struct Document *document,
|
|
|
102
102
|
struct YerbaResult yerba_document_set(struct Document *document,
|
|
103
103
|
const char *path,
|
|
104
104
|
const char *value,
|
|
105
|
-
enum YerbaValueType value_type
|
|
105
|
+
enum YerbaValueType value_type,
|
|
106
|
+
bool all);
|
|
106
107
|
|
|
107
108
|
struct YerbaResult yerba_document_insert(struct Document *document,
|
|
108
109
|
const char *path,
|
|
@@ -128,6 +129,11 @@ struct YerbaResult yerba_document_remove_at(struct Document *document,
|
|
|
128
129
|
const char *path,
|
|
129
130
|
uintptr_t index);
|
|
130
131
|
|
|
132
|
+
struct YerbaResult yerba_document_move_item(struct Document *document,
|
|
133
|
+
const char *path,
|
|
134
|
+
uintptr_t from,
|
|
135
|
+
uintptr_t to);
|
|
136
|
+
|
|
131
137
|
struct YerbaResult yerba_document_rename(struct Document *document,
|
|
132
138
|
const char *source,
|
|
133
139
|
const char *dest);
|
|
@@ -137,6 +143,11 @@ struct YerbaResult yerba_document_sort(struct Document *document,
|
|
|
137
143
|
const char *by,
|
|
138
144
|
bool case_sensitive);
|
|
139
145
|
|
|
146
|
+
struct YerbaResult yerba_document_reorder(struct Document *document,
|
|
147
|
+
const char *path,
|
|
148
|
+
const char *by,
|
|
149
|
+
const char *order_csv);
|
|
150
|
+
|
|
140
151
|
struct YerbaResult yerba_document_sort_keys(struct Document *document,
|
|
141
152
|
const char *path,
|
|
142
153
|
const char *order);
|
data/ext/yerba/yerba.c
CHANGED
|
@@ -230,7 +230,7 @@ static VALUE document_bracket(VALUE self, VALUE path) {
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
switch (result.node_type) {
|
|
233
|
-
case
|
|
233
|
+
case NODE_TYPE_SCALAR: {
|
|
234
234
|
VALUE klass = rb_path2class("Yerba::Scalar");
|
|
235
235
|
VALUE value = typed_value_to_ruby(result.single);
|
|
236
236
|
yerba_get_result_free(result);
|
|
@@ -240,7 +240,7 @@ static VALUE document_bracket(VALUE self, VALUE path) {
|
|
|
240
240
|
return instance;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
case
|
|
243
|
+
case NODE_TYPE_MAP: {
|
|
244
244
|
yerba_get_result_free(result);
|
|
245
245
|
VALUE klass = rb_path2class("Yerba::Map");
|
|
246
246
|
|
|
@@ -249,7 +249,7 @@ static VALUE document_bracket(VALUE self, VALUE path) {
|
|
|
249
249
|
return instance;
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
case
|
|
252
|
+
case NODE_TYPE_SEQUENCE: {
|
|
253
253
|
yerba_get_result_free(result);
|
|
254
254
|
VALUE klass = rb_path2class("Yerba::Sequence");
|
|
255
255
|
|
|
@@ -298,35 +298,35 @@ static VALUE document_get_values(VALUE self, VALUE path) {
|
|
|
298
298
|
return rb_funcall(rb_path2class("JSON"), rb_intern("parse"), 1, json_string);
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
/* document.get_quote_style(path) → :plain, :single, :double, or nil */
|
|
301
|
+
/* document.get_quote_style(path) → :plain, :single, :double, :literal, etc. or nil */
|
|
302
302
|
static VALUE document_get_quote_style(VALUE self, VALUE path) {
|
|
303
303
|
struct Document *document = get_document(self);
|
|
304
|
-
|
|
304
|
+
char *style = yerba_document_get_quote_style(document, StringValueCStr(path));
|
|
305
305
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
306
|
+
if (style == NULL) return Qnil;
|
|
307
|
+
|
|
308
|
+
VALUE symbol = ID2SYM(rb_intern(style));
|
|
309
|
+
|
|
310
|
+
yerba_string_free(style);
|
|
311
|
+
|
|
312
|
+
return symbol;
|
|
312
313
|
}
|
|
313
314
|
|
|
314
315
|
/* document.set_quote_style(path, style) */
|
|
315
316
|
static VALUE document_set_quote_style(VALUE self, VALUE path, VALUE style) {
|
|
316
317
|
struct Document *document = get_document(self);
|
|
317
318
|
|
|
318
|
-
|
|
319
|
+
const char *style_string;
|
|
320
|
+
|
|
319
321
|
if (RB_TYPE_P(style, T_SYMBOL)) {
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
else if (style_id == rb_intern("double")) style_int = 2;
|
|
324
|
-
else rb_raise(rb_eError, "Invalid quote style (use :plain, :single, or :double)");
|
|
322
|
+
style_string = rb_id2name(SYM2ID(style));
|
|
323
|
+
} else if (RB_TYPE_P(style, T_STRING)) {
|
|
324
|
+
style_string = StringValueCStr(style);
|
|
325
325
|
} else {
|
|
326
|
-
|
|
326
|
+
rb_raise(rb_eError, "Invalid quote style (expected Symbol or String)");
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
YerbaResult result = yerba_document_set_quote_style(document, StringValueCStr(path),
|
|
329
|
+
YerbaResult result = yerba_document_set_quote_style(document, StringValueCStr(path), style_string);
|
|
330
330
|
|
|
331
331
|
check_result(result);
|
|
332
332
|
|
|
@@ -399,6 +399,7 @@ static VALUE document_set(int argc, VALUE *argv, VALUE self) {
|
|
|
399
399
|
const char *c_value;
|
|
400
400
|
YerbaValueType value_type;
|
|
401
401
|
char number_buffer[64];
|
|
402
|
+
bool all = false;
|
|
402
403
|
|
|
403
404
|
if (value == Qnil) {
|
|
404
405
|
c_value = "null";
|
|
@@ -422,7 +423,13 @@ static VALUE document_set(int argc, VALUE *argv, VALUE self) {
|
|
|
422
423
|
value_type = YERBA_VALUE_TYPE_STRING;
|
|
423
424
|
}
|
|
424
425
|
|
|
425
|
-
|
|
426
|
+
if (!NIL_P(opts)) {
|
|
427
|
+
VALUE v_all = rb_hash_aref(opts, ID2SYM(rb_intern("all")));
|
|
428
|
+
|
|
429
|
+
if (RTEST(v_all)) all = true;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
YerbaResult result = yerba_document_set(document, StringValueCStr(path), c_value, value_type, all);
|
|
426
433
|
check_result(result);
|
|
427
434
|
|
|
428
435
|
return self;
|
|
@@ -526,24 +533,83 @@ static VALUE document_rename(VALUE self, VALUE source, VALUE destination) {
|
|
|
526
533
|
return self;
|
|
527
534
|
}
|
|
528
535
|
|
|
529
|
-
/* document.sort(path, by: nil, case_sensitive: false) */
|
|
536
|
+
/* document.sort(path = "", by: nil, order: nil, case_sensitive: false) */
|
|
530
537
|
static VALUE document_sort(int argc, VALUE *argv, VALUE self) {
|
|
531
538
|
VALUE path, opts;
|
|
532
|
-
rb_scan_args(argc, argv, "
|
|
539
|
+
rb_scan_args(argc, argv, "01:", &path, &opts);
|
|
540
|
+
|
|
541
|
+
if (NIL_P(path)) path = rb_str_new_cstr("");
|
|
533
542
|
|
|
534
543
|
const char *by = NULL;
|
|
535
544
|
bool case_sensitive = false;
|
|
545
|
+
VALUE v_order = Qnil;
|
|
536
546
|
|
|
537
547
|
if (!NIL_P(opts)) {
|
|
538
548
|
VALUE v_by = rb_hash_aref(opts, ID2SYM(rb_intern("by")));
|
|
549
|
+
v_order = rb_hash_aref(opts, ID2SYM(rb_intern("order")));
|
|
539
550
|
VALUE v_case_sensitive = rb_hash_aref(opts, ID2SYM(rb_intern("case_sensitive")));
|
|
540
551
|
|
|
541
|
-
if (
|
|
542
|
-
|
|
552
|
+
if (SYMBOL_P(v_by)) {
|
|
553
|
+
VALUE by_string = rb_sym2str(v_by);
|
|
554
|
+
by = StringValueCStr(by_string);
|
|
555
|
+
} else if (!NIL_P(v_by)) {
|
|
556
|
+
by = StringValueCStr(v_by);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (RTEST(v_case_sensitive)) {
|
|
560
|
+
case_sensitive = true;
|
|
561
|
+
}
|
|
543
562
|
}
|
|
544
563
|
|
|
545
564
|
struct Document *document = get_document(self);
|
|
546
|
-
|
|
565
|
+
const char *path_string = StringValueCStr(path);
|
|
566
|
+
|
|
567
|
+
if (RB_TYPE_P(v_order, T_ARRAY)) {
|
|
568
|
+
VALUE order_csv = rb_ary_join(v_order, rb_str_new_cstr(","));
|
|
569
|
+
const char *order_string = StringValueCStr(order_csv);
|
|
570
|
+
const char *reorder_path = StringValueCStr(path);
|
|
571
|
+
const char *reorder_by;
|
|
572
|
+
|
|
573
|
+
if (by) {
|
|
574
|
+
VALUE reorder_by_value = rb_hash_aref(opts, ID2SYM(rb_intern("by")));
|
|
575
|
+
|
|
576
|
+
if (SYMBOL_P(reorder_by_value)) {
|
|
577
|
+
reorder_by_value = rb_sym2str(reorder_by_value);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
reorder_by = StringValueCStr(reorder_by_value);
|
|
581
|
+
} else {
|
|
582
|
+
reorder_by = ".";
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
YerbaResult result = yerba_document_reorder(document, reorder_path, reorder_by, order_string);
|
|
586
|
+
check_result(result);
|
|
587
|
+
|
|
588
|
+
return self;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const char *order = NULL;
|
|
592
|
+
|
|
593
|
+
if (SYMBOL_P(v_order)) {
|
|
594
|
+
VALUE order_string = rb_sym2str(v_order);
|
|
595
|
+
order = StringValueCStr(order_string);
|
|
596
|
+
} else if (!NIL_P(v_order)) {
|
|
597
|
+
order = StringValueCStr(v_order);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
VALUE by_with_order = Qnil;
|
|
601
|
+
|
|
602
|
+
if (order && strcmp(order, "desc") == 0) {
|
|
603
|
+
if (by) {
|
|
604
|
+
by_with_order = rb_sprintf("%s:desc", by);
|
|
605
|
+
} else {
|
|
606
|
+
by_with_order = rb_str_new_cstr(":desc");
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
by = StringValueCStr(by_with_order);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
YerbaResult result = yerba_document_sort(document, path_string, by, case_sensitive);
|
|
547
613
|
|
|
548
614
|
check_result(result);
|
|
549
615
|
|
data/lib/yerba/3.2/yerba.so
CHANGED
|
Binary file
|
data/lib/yerba/3.3/yerba.so
CHANGED
|
Binary file
|
data/lib/yerba/3.4/yerba.so
CHANGED
|
Binary file
|
data/lib/yerba/4.0/yerba.so
CHANGED
|
Binary file
|
data/lib/yerba/collection.rb
CHANGED
|
@@ -20,6 +20,41 @@ module Yerba
|
|
|
20
20
|
self.class.find(@glob, path, condition: condition, select: select)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
def find_by(...)
|
|
24
|
+
each do |document|
|
|
25
|
+
next unless document.sequence?
|
|
26
|
+
|
|
27
|
+
result = document.root.find_by(...)
|
|
28
|
+
return result if result
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def where(...)
|
|
35
|
+
results = []
|
|
36
|
+
|
|
37
|
+
each do |document|
|
|
38
|
+
next unless document.sequence?
|
|
39
|
+
|
|
40
|
+
results.concat(document.root.where(...))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
results
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def pluck(...)
|
|
47
|
+
results = []
|
|
48
|
+
|
|
49
|
+
each do |document|
|
|
50
|
+
next unless document.sequence?
|
|
51
|
+
|
|
52
|
+
results.concat(document.root.pluck(...))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
results
|
|
56
|
+
end
|
|
57
|
+
|
|
23
58
|
def apply!
|
|
24
59
|
each do |document|
|
|
25
60
|
yield document
|