yerba 0.2.1-arm-linux-gnu → 0.3.0-arm-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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b4932b50d51221f38a1e170e33a4220082dbfb83d6ca3e8657abe345cc8f9129
4
- data.tar.gz: d15e83275f688c4075595506fe9fd9f74e45cb79ff186a9e8299d0fb436dcea3
3
+ metadata.gz: cc6149b83a227c95769596f557eb340cfb9bf688f48e7e4cb71597e34a3f81ce
4
+ data.tar.gz: 7d96130e8ad306e3ee9c8fecac49f59c114c8287e4cc49859995787591a7a17d
5
5
  SHA512:
6
- metadata.gz: f998d3515c059514abeae4db08b6a61ec7a205adbb6470d0506f239bc29a35ff7c951c9d8b04ac7b0cb7a09142fa98b1ab0a780641bbd4950487247cbfd58e27
7
- data.tar.gz: 2a1bbe120c06378ec3ed8eee782d7128834736d99bec481738b3e8d82b0543beda526cba016199f3a5508892323317479cc5184e3bfa524111a14c4607d5d83d
6
+ metadata.gz: 57b2e57f4561ea5aec247ff2bf5957c032dd14191b3892f8e9d657f16b4b7775d968d9eec6da81e2c018f7a63ca3318475661d462e55e8117bb29420e60d8b93
7
+ data.tar.gz: d26289169658d82ec1bdf51fa1259c8b9c44eaf1afa7759c32002675e30f3a61eb589df29553da96f8e903e1023ddf19c5a55b6c8cb2b4f2694d68e3be61b708
data/README.md CHANGED
@@ -47,7 +47,7 @@ Use `yerba` as a library in your Rust project:
47
47
 
48
48
  ```toml
49
49
  [dependencies]
50
- yerba = "0.2"
50
+ yerba = "0.3"
51
51
  ```
52
52
 
53
53
  ```rust
@@ -162,6 +162,12 @@ Use `--condition` to only apply the change when a sibling field matches:
162
162
  yerba set config.yml "database.host" "0.0.0.0" --condition ".port == 5432"
163
163
  ```
164
164
 
165
+ Use `--all` to update all nodes matching a wildcard selector:
166
+
167
+ ```bash
168
+ yerba set videos.yml "[].description" "" --all
169
+ ```
170
+
165
171
  ### `insert`
166
172
 
167
173
  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 +255,25 @@ yerba move-key config.yml "database.pool" --after "database.name"
249
255
 
250
256
  ### `sort`
251
257
 
252
- Sort items in a sequence. For simple scalar sequences, no options are needed. For sequences of maps, use `--by` to specify sort fields. Append `:desc` for descending order:
258
+ 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
259
 
254
260
  ```bash
255
261
  yerba sort config.yml "tags"
256
- yerba sort videos.yml --by "title"
257
- yerba sort videos.yml --by "date:desc,title"
258
- yerba sort videos.yml "[].speakers" --by "name"
262
+ yerba sort videos.yml --by ".title"
263
+ yerba sort videos.yml --by ".date" --order desc --by ".title"
264
+ yerba sort videos.yml "[].speakers" --by ".name"
259
265
  ```
260
266
 
267
+ Use `--order` with a comma-separated list to specify an explicit custom order. All items must be listed:
268
+
269
+ ```bash
270
+ yerba sort videos.yml "[]" --by ".id" --order "talk-c,talk-a,talk-b"
271
+ yerba sort speakers.yml "[]" --by ".name" --order "Charlie,Alice,Bob"
272
+ yerba sort config.yml "tags" --by "." --order "yaml,ruby,rust"
273
+ ```
274
+
275
+ 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.
276
+
261
277
  ### `sort-keys`
262
278
 
263
279
  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:
@@ -295,6 +311,57 @@ yerba blank-lines videos.yml "[]" 1
295
311
  yerba blank-lines config.yml "tags" 0
296
312
  ```
297
313
 
314
+ ### `selectors`
315
+
316
+ 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:
317
+
318
+ ```bash
319
+ yerba selectors config.yml
320
+ ```
321
+
322
+ Output:
323
+ ```
324
+ database
325
+ database.host
326
+ database.port
327
+ tags
328
+ tags[]
329
+ ```
330
+
331
+ For sequences of objects:
332
+
333
+ ```bash
334
+ yerba selectors videos.yml
335
+ ```
336
+
337
+ Output:
338
+ ```
339
+ []
340
+ [].id
341
+ [].title
342
+ [].speakers
343
+ [].speakers[]
344
+ [].speakers[].name
345
+ [].speakers[].slug
346
+ [].video_id
347
+ [].video_provider
348
+ ```
349
+
350
+ Pass a selector to scope the output to a specific subtree:
351
+
352
+ ```bash
353
+ yerba selectors config.yml "database"
354
+ yerba selectors videos.yml "[]"
355
+ yerba selectors videos.yml "[].speakers"
356
+ ```
357
+
358
+ Works with glob patterns to show the union of selectors across multiple files:
359
+
360
+ ```bash
361
+ yerba selectors "data/**/videos.yml"
362
+ yerba selectors "data/**/videos.yml" "[]"
363
+ ```
364
+
298
365
  ## `Yerbafile`
299
366
 
300
367
  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.
@@ -428,6 +495,12 @@ document["database"]["host"].value = "0.0.0.0"
428
495
  document.set("database.port", 3306)
429
496
  ```
430
497
 
498
+ Set all matching nodes at once with `all: true`:
499
+
500
+ ```ruby
501
+ document.set("[].description", "", all: true)
502
+ ```
503
+
431
504
  Insert new keys with positional control:
432
505
 
433
506
  ```ruby
Binary file
data/ext/yerba/extconf.rb CHANGED
@@ -93,19 +93,27 @@ if target_platform
93
93
  end
94
94
  end
95
95
 
96
- lib_path = File.join(lib_dir, lib_name)
96
+ static_lib = File.join(lib_dir, "libyerba.a")
97
97
 
98
- unless File.exist?(lib_path)
99
- abort "ERROR: Shared library not found at #{lib_path}"
100
- end
98
+ if File.exist?(static_lib)
99
+ puts "yerba: Static library found at #{static_lib}"
100
+ $LDFLAGS << " #{static_lib}"
101
+ else
102
+ lib_path = File.join(lib_dir, lib_name)
101
103
 
102
- puts "yerba: Shared library found at #{lib_path}"
104
+ unless File.exist?(lib_path)
105
+ abort "ERROR: Shared library not found at #{lib_path}"
106
+ end
103
107
 
104
- $LDFLAGS << " -L#{lib_dir} -lyerba"
105
- $CFLAGS << " -I#{File.join(__dir__, "include")}"
108
+ puts "yerba: Shared library found at #{lib_path} (dynamic)"
106
109
 
107
- if RbConfig::CONFIG["host_os"].match?(/darwin|linux/)
108
- $LDFLAGS << " -Wl,-rpath,#{lib_dir}"
110
+ $LDFLAGS << " -L#{lib_dir} -lyerba"
111
+
112
+ if RbConfig::CONFIG["host_os"].match?(/darwin|linux/)
113
+ $LDFLAGS << " -Wl,-rpath,#{lib_dir}"
114
+ end
109
115
  end
110
116
 
117
+ $CFLAGS << " -I#{File.join(__dir__, "include")}"
118
+
111
119
  create_makefile("yerba/yerba")
@@ -0,0 +1,169 @@
1
+ /* Generated by cbindgen — do not edit manually */
2
+
3
+ #include <stdbool.h>
4
+ #include <stdint.h>
5
+ #include <stddef.h>
6
+
7
+ #ifndef YERBA_H
8
+ #define YERBA_H
9
+
10
+ typedef enum YerbaNodeType {
11
+ YERBA_NODE_TYPE_SCALAR = 0,
12
+ YERBA_NODE_TYPE_MAP = 1,
13
+ YERBA_NODE_TYPE_SEQUENCE = 2,
14
+ YERBA_NODE_TYPE_NOT_FOUND = 3,
15
+ } YerbaNodeType;
16
+
17
+ typedef enum YerbaValueType {
18
+ YERBA_VALUE_TYPE_NULL = 0,
19
+ YERBA_VALUE_TYPE_BOOLEAN = 1,
20
+ YERBA_VALUE_TYPE_INTEGER = 2,
21
+ YERBA_VALUE_TYPE_FLOAT = 3,
22
+ YERBA_VALUE_TYPE_STRING = 4,
23
+ } YerbaValueType;
24
+
25
+ typedef struct Document Document;
26
+
27
+ typedef struct YerbaParseResult {
28
+ struct Document *document;
29
+ char *error;
30
+ } YerbaParseResult;
31
+
32
+ typedef struct YerbaTypedValue {
33
+ char *text;
34
+ enum YerbaValueType value_type;
35
+ } YerbaTypedValue;
36
+
37
+ typedef struct YerbaTypedList {
38
+ char *json;
39
+ uintptr_t length;
40
+ } YerbaTypedList;
41
+
42
+ typedef struct YerbaLocation {
43
+ uintptr_t start_offset;
44
+ uintptr_t end_offset;
45
+ uintptr_t start_line;
46
+ uintptr_t start_column;
47
+ uintptr_t end_line;
48
+ uintptr_t end_column;
49
+ } YerbaLocation;
50
+
51
+ typedef struct YerbaGetResult {
52
+ bool is_list;
53
+ enum YerbaNodeType node_type;
54
+ struct YerbaTypedValue single;
55
+ struct YerbaTypedList list;
56
+ struct YerbaLocation location;
57
+ char *key_name;
58
+ struct YerbaLocation key_location;
59
+ char *error;
60
+ } YerbaGetResult;
61
+
62
+ typedef struct YerbaResult {
63
+ bool success;
64
+ char *error;
65
+ } YerbaResult;
66
+
67
+ struct YerbaParseResult yerba_document_parse_file(const char *path);
68
+
69
+ struct YerbaParseResult yerba_document_parse(const char *content);
70
+
71
+ void yerba_document_free(struct Document *document);
72
+
73
+ struct YerbaGetResult yerba_document_get(const struct Document *document, const char *path);
74
+
75
+ /**
76
+ * Caller must free with yerba_string_free.
77
+ */
78
+ char *yerba_document_get_value(const struct Document *document, const char *path);
79
+
80
+ /**
81
+ * Caller must free with yerba_string_free.
82
+ */
83
+ char *yerba_document_get_values(const struct Document *document, const char *path);
84
+
85
+ int32_t yerba_document_get_quote_style(const struct Document *document, const char *path);
86
+
87
+ struct YerbaResult yerba_document_set_quote_style(struct Document *document,
88
+ const char *path,
89
+ int32_t style);
90
+
91
+ bool yerba_document_evaluate_condition(const struct Document *document,
92
+ const char *parent_path,
93
+ const char *condition);
94
+
95
+ bool yerba_document_exists(const struct Document *document, const char *path);
96
+
97
+ char *yerba_document_find(const struct Document *document,
98
+ const char *path,
99
+ const char *condition,
100
+ const char *select);
101
+
102
+ struct YerbaResult yerba_document_set(struct Document *document,
103
+ const char *path,
104
+ const char *value,
105
+ enum YerbaValueType value_type,
106
+ bool all);
107
+
108
+ struct YerbaResult yerba_document_insert(struct Document *document,
109
+ const char *path,
110
+ const char *value,
111
+ const char *before,
112
+ const char *after,
113
+ int64_t at);
114
+
115
+ struct YerbaResult yerba_document_insert_object(struct Document *document,
116
+ const char *path,
117
+ const char *json,
118
+ const char *before,
119
+ const char *after,
120
+ int64_t at);
121
+
122
+ struct YerbaResult yerba_document_delete(struct Document *document, const char *path);
123
+
124
+ struct YerbaResult yerba_document_remove(struct Document *document,
125
+ const char *path,
126
+ const char *value);
127
+
128
+ struct YerbaResult yerba_document_remove_at(struct Document *document,
129
+ const char *path,
130
+ uintptr_t index);
131
+
132
+ struct YerbaResult yerba_document_rename(struct Document *document,
133
+ const char *source,
134
+ const char *dest);
135
+
136
+ struct YerbaResult yerba_document_sort(struct Document *document,
137
+ const char *path,
138
+ const char *by,
139
+ bool case_sensitive);
140
+
141
+ struct YerbaResult yerba_document_sort_keys(struct Document *document,
142
+ const char *path,
143
+ const char *order);
144
+
145
+ struct YerbaResult yerba_document_quote_style(struct Document *document,
146
+ const char *path,
147
+ const char *key_style,
148
+ const char *value_style);
149
+
150
+ struct YerbaResult yerba_document_blank_lines(struct Document *document,
151
+ const char *path,
152
+ uintptr_t count);
153
+
154
+ char *yerba_document_to_string(const struct Document *document);
155
+
156
+ void yerba_string_free(char *s);
157
+
158
+ void yerba_result_free(struct YerbaResult result);
159
+
160
+ void yerba_get_result_free(struct YerbaGetResult result);
161
+
162
+ struct YerbaTypedList yerba_glob_get(const char *glob_pattern, const char *path);
163
+
164
+ struct YerbaTypedList yerba_glob_find(const char *glob_pattern,
165
+ const char *path,
166
+ const char *condition,
167
+ const char *select);
168
+
169
+ #endif /* YERBA_H */
data/ext/yerba/yerba.c CHANGED
@@ -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
- YerbaResult result = yerba_document_set(document, StringValueCStr(path), c_value, value_type);
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;
Binary file
Binary file
Binary file
Binary file
data/lib/yerba/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yerba
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/yerba.rb CHANGED
@@ -12,9 +12,14 @@ require_relative "yerba/document"
12
12
  require_relative "yerba/collection"
13
13
 
14
14
  begin
15
- require "yerba/yerba"
15
+ major, minor, = RUBY_VERSION.split(".")
16
+ require "yerba/#{major}.#{minor}/yerba"
16
17
  rescue LoadError
17
- # C extension not available, fall back to CLI mode
18
+ begin
19
+ require "yerba/yerba"
20
+ rescue LoadError
21
+ # C extension not available, fall back to CLI mode
22
+ end
18
23
  end
19
24
 
20
25
  module Yerba
data/rust/Cargo.lock CHANGED
@@ -784,7 +784,7 @@ dependencies = [
784
784
 
785
785
  [[package]]
786
786
  name = "yerba"
787
- version = "0.2.1"
787
+ version = "0.3.0"
788
788
  dependencies = [
789
789
  "cbindgen",
790
790
  "clap",
data/rust/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "yerba"
3
- version = "0.2.1"
3
+ version = "0.3.0"
4
4
  edition = "2021"
5
5
  authors = ["Marco Roth <marco.roth@intergga.ch>"]
6
6
  description = "YAML Editing and Refactoring with Better Accuracy"
@@ -13,7 +13,7 @@ categories = ["parser-implementations", "development-tools"]
13
13
  [lib]
14
14
  name = "yerba"
15
15
  path = "src/lib.rs"
16
- crate-type = ["cdylib", "rlib"]
16
+ crate-type = ["cdylib", "staticlib", "rlib"]
17
17
 
18
18
  [[bin]]
19
19
  name = "yerba"
@@ -3,12 +3,13 @@ use std::sync::LazyLock;
3
3
  use indoc::indoc;
4
4
 
5
5
  use super::colorize_examples;
6
- use super::{output, parse_file, run_op};
6
+ use super::{output, parse_file, resolve_files, run_op};
7
7
 
8
8
  static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
9
9
  colorize_examples(indoc! {r#"
10
10
  yerba delete config.yml "database.pool"
11
11
  yerba delete videos.yml "[0].description"
12
+ yerba delete "data/**/event.yml" "date_precision"
12
13
  yerba delete config.yml "database.pool" --dry-run
13
14
  "#})
14
15
  });
@@ -28,8 +29,12 @@ pub struct Args {
28
29
 
29
30
  impl Args {
30
31
  pub fn run(self) {
31
- let mut document = parse_file(&self.file);
32
- run_op(|| document.delete(&self.selector));
33
- output(&self.file, &document, self.dry_run);
32
+ for resolved_file in resolve_files(&self.file) {
33
+ let mut document = parse_file(&resolved_file);
34
+ let result = document.delete(&self.selector);
35
+
36
+ run_op(&resolved_file, &document, result);
37
+ output(&resolved_file, &document, self.dry_run);
38
+ }
34
39
  }
35
40
  }
@@ -3,7 +3,7 @@ use std::sync::LazyLock;
3
3
 
4
4
  use indoc::indoc;
5
5
 
6
- use super::{colorize_examples, parse_file, resolve_files};
6
+ use super::{colorize_examples, parse_file, resolve_files, show_similar_selectors};
7
7
 
8
8
  static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
9
9
  colorize_examples(indoc! {r#"
@@ -64,9 +64,49 @@ impl Args {
64
64
 
65
65
  let search_path_string = search_path.to_selector_string();
66
66
  let mut all_results: Vec<serde_json::Value> = Vec::new();
67
+ let files = resolve_files(&self.file);
68
+ let is_glob = files.len() > 1;
67
69
 
68
- for resolved_file in resolve_files(&self.file) {
69
- let document = parse_file(&resolved_file);
70
+ for resolved_file in &files {
71
+ let document = parse_file(resolved_file);
72
+
73
+ if normalized_condition.is_none() && !document.exists(&self.selector) {
74
+ if is_glob {
75
+ continue;
76
+ }
77
+
78
+ use super::color::*;
79
+
80
+ eprintln!(
81
+ "{RED}Error:{RESET} selector \"{}\" not found in {}",
82
+ self.selector, resolved_file
83
+ );
84
+
85
+ show_similar_selectors(resolved_file, &document, &self.selector);
86
+ process::exit(1);
87
+ }
88
+
89
+ if let Some(fields) = &select_fields {
90
+ for field in fields {
91
+ let field_trimmed = field.trim().trim_start_matches('.');
92
+ let full_selector = if search_path_string.is_empty() {
93
+ field_trimmed.to_string()
94
+ } else {
95
+ format!("{}.{}", search_path_string, field_trimmed)
96
+ };
97
+
98
+ if !document.exists(&full_selector) {
99
+ use super::color::*;
100
+ eprintln!(
101
+ "{RED}Error:{RESET} select field \"{}\" not found in {}",
102
+ field.trim(),
103
+ resolved_file
104
+ );
105
+ show_similar_selectors(resolved_file, &document, &full_selector);
106
+ process::exit(1);
107
+ }
108
+ }
109
+ }
70
110
 
71
111
  let values: Vec<serde_yaml::Value> = if let Some(condition) = &normalized_condition {
72
112
  document.filter(&search_path_string, condition)
@@ -74,16 +114,6 @@ impl Args {
74
114
  document.get_values(&search_path_string)
75
115
  };
76
116
 
77
- if values.is_empty()
78
- && !selector.has_brackets()
79
- && normalized_condition.is_none()
80
- && !document.exists(&self.selector)
81
- {
82
- use super::color::*;
83
- eprintln!("{RED}Error:{RESET} path not found: {}", self.selector);
84
- process::exit(1);
85
- }
86
-
87
117
  for value in values {
88
118
  if let Some(field) = &extract_field {
89
119
  let field_string = field.to_selector_string();
@@ -121,6 +151,19 @@ impl Args {
121
151
  }
122
152
  }
123
153
 
154
+ if is_glob && all_results.is_empty() && normalized_condition.is_none() {
155
+ use super::color::*;
156
+
157
+ eprintln!(
158
+ "{RED}Error:{RESET} selector \"{}\" not found in any of the {} files matching \"{}\"",
159
+ self.selector,
160
+ files.len(),
161
+ self.file
162
+ );
163
+
164
+ process::exit(1);
165
+ }
166
+
124
167
  if self.raw {
125
168
  for value in &all_results {
126
169
  match value {
@@ -3,7 +3,7 @@ use std::sync::LazyLock;
3
3
  use indoc::indoc;
4
4
 
5
5
  use super::colorize_examples;
6
- use super::{output, parse_file, run_op};
6
+ use super::{output, parse_file, resolve_files, run_op};
7
7
 
8
8
  static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
9
9
  colorize_examples(indoc! {r#"
@@ -99,8 +99,12 @@ impl Args {
99
99
  .unwrap_or(yerba::InsertPosition::Last)
100
100
  };
101
101
 
102
- let mut document = parse_file(&self.file);
103
- run_op(|| document.insert_into(&self.selector, &resolved_value, position));
104
- output(&self.file, &document, self.dry_run);
102
+ for resolved_file in resolve_files(&self.file) {
103
+ let mut document = parse_file(&resolved_file);
104
+ let result = document.insert_into(&self.selector, &resolved_value, position.clone());
105
+
106
+ run_op(&resolved_file, &document, result);
107
+ output(&resolved_file, &document, self.dry_run);
108
+ }
105
109
  }
106
110
  }