yerba 0.9.1-arm-linux-gnu → 0.10.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 +4 -4
- data/README.md +60 -16
- data/exe/arm-linux-gnu/yerba +0 -0
- data/ext/yerba/include/yerba.h +67 -32
- data/ext/yerba/yerba.c +296 -186
- 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 +4 -4
- data/lib/yerba/document.rb +134 -0
- data/lib/yerba/formatting.rb +1 -0
- data/lib/yerba/location.rb +8 -1
- data/lib/yerba/map.rb +16 -6
- data/lib/yerba/node.rb +41 -0
- data/lib/yerba/query_result.rb +33 -10
- data/lib/yerba/scalar.rb +29 -0
- data/lib/yerba/selector.rb +142 -0
- data/lib/yerba/sequence.rb +38 -33
- data/lib/yerba/version.rb +1 -1
- data/lib/yerba.rb +1 -0
- data/rust/Cargo.lock +1 -1
- data/rust/Cargo.toml +1 -1
- data/rust/src/commands/get.rs +12 -12
- data/rust/src/commands/init.rs +8 -8
- data/rust/src/commands/insert.rs +4 -18
- data/rust/src/commands/location.rs +2 -0
- data/rust/src/commands/mod.rs +34 -6
- data/rust/src/commands/move_item.rs +1 -1
- data/rust/src/commands/move_key.rs +8 -8
- data/rust/src/commands/rename.rs +1 -1
- data/rust/src/commands/selectors.rs +1 -1
- data/rust/src/commands/set.rs +14 -6
- data/rust/src/document/condition.rs +25 -25
- data/rust/src/document/delete.rs +57 -43
- data/rust/src/document/get.rs +91 -82
- data/rust/src/document/insert.rs +77 -77
- data/rust/src/document/mod.rs +138 -64
- data/rust/src/document/nodes.rs +162 -0
- data/rust/src/document/schema.rs +8 -8
- data/rust/src/document/set.rs +49 -26
- data/rust/src/document/sort.rs +54 -54
- data/rust/src/document/style.rs +50 -49
- data/rust/src/document/unique.rs +5 -5
- data/rust/src/error.rs +8 -4
- data/rust/src/ffi.rs +272 -102
- data/rust/src/json.rs +62 -2
- data/rust/src/lib.rs +2 -1
- data/rust/src/main.rs +2 -1
- data/rust/src/selector.rs +48 -7
- data/rust/src/syntax.rs +449 -56
- data/rust/src/validation.rs +5 -3
- data/rust/src/yerbafile.rs +124 -76
- metadata +4 -2
data/rust/src/yerbafile.rs
CHANGED
|
@@ -15,13 +15,16 @@ pub struct Yerbafile {
|
|
|
15
15
|
pub rules: Vec<Rule>,
|
|
16
16
|
#[serde(skip)]
|
|
17
17
|
pub directory: Option<PathBuf>,
|
|
18
|
+
#[serde(skip)]
|
|
19
|
+
pub deprecated_path_keys: Vec<String>,
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
#[derive(Debug, Clone, Deserialize)]
|
|
21
23
|
pub struct Rule {
|
|
22
24
|
pub files: String,
|
|
23
25
|
#[serde(default)]
|
|
24
|
-
|
|
26
|
+
#[serde(alias = "path")]
|
|
27
|
+
pub selector: Option<String>,
|
|
25
28
|
pub pipeline: Vec<PipelineStep>,
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -48,7 +51,8 @@ pub enum PipelineStep {
|
|
|
48
51
|
#[derive(Debug, Clone, Deserialize)]
|
|
49
52
|
pub struct SortConfig {
|
|
50
53
|
#[serde(default)]
|
|
51
|
-
|
|
54
|
+
#[serde(alias = "path")]
|
|
55
|
+
pub selector: Option<String>,
|
|
52
56
|
#[serde(default)]
|
|
53
57
|
pub by: Option<String>,
|
|
54
58
|
#[serde(default)]
|
|
@@ -58,7 +62,8 @@ pub struct SortConfig {
|
|
|
58
62
|
#[derive(Debug, Clone, Deserialize)]
|
|
59
63
|
pub struct BlankLinesConfig {
|
|
60
64
|
#[serde(default)]
|
|
61
|
-
|
|
65
|
+
#[serde(alias = "path")]
|
|
66
|
+
pub selector: Option<String>,
|
|
62
67
|
pub count: usize,
|
|
63
68
|
#[serde(default)]
|
|
64
69
|
pub before: Vec<String>,
|
|
@@ -81,7 +86,8 @@ pub struct DirectivesConfig {
|
|
|
81
86
|
#[derive(Debug, Clone, Deserialize)]
|
|
82
87
|
pub struct UniqueConfig {
|
|
83
88
|
#[serde(default)]
|
|
84
|
-
|
|
89
|
+
#[serde(alias = "path")]
|
|
90
|
+
pub selector: Option<String>,
|
|
85
91
|
#[serde(default = "default_dot")]
|
|
86
92
|
pub by: String,
|
|
87
93
|
#[serde(default)]
|
|
@@ -98,7 +104,8 @@ fn default_dot() -> String {
|
|
|
98
104
|
pub struct SchemaConfig {
|
|
99
105
|
pub file: String,
|
|
100
106
|
#[serde(default)]
|
|
101
|
-
|
|
107
|
+
#[serde(alias = "path")]
|
|
108
|
+
pub selector: Option<String>,
|
|
102
109
|
#[serde(default)]
|
|
103
110
|
pub items: bool,
|
|
104
111
|
}
|
|
@@ -112,7 +119,8 @@ pub struct FinalNewlineConfig {
|
|
|
112
119
|
#[derive(Debug, Clone, Deserialize)]
|
|
113
120
|
pub struct EscapesConfig {
|
|
114
121
|
#[serde(default)]
|
|
115
|
-
|
|
122
|
+
#[serde(alias = "path")]
|
|
123
|
+
pub selector: Option<String>,
|
|
116
124
|
}
|
|
117
125
|
|
|
118
126
|
fn default_one() -> usize {
|
|
@@ -129,7 +137,8 @@ pub struct RenameConfig {
|
|
|
129
137
|
|
|
130
138
|
#[derive(Debug, Clone, Deserialize)]
|
|
131
139
|
pub struct RemoveConfig {
|
|
132
|
-
|
|
140
|
+
#[serde(alias = "path")]
|
|
141
|
+
pub selector: String,
|
|
133
142
|
pub value: String,
|
|
134
143
|
#[serde(default)]
|
|
135
144
|
pub condition: Option<String>,
|
|
@@ -231,7 +240,8 @@ impl<'de> Deserialize<'de> for PipelineStep {
|
|
|
231
240
|
#[derive(Debug, Clone, Deserialize)]
|
|
232
241
|
pub struct SortKeysConfig {
|
|
233
242
|
#[serde(default)]
|
|
234
|
-
|
|
243
|
+
#[serde(alias = "path")]
|
|
244
|
+
pub selector: Option<String>,
|
|
235
245
|
pub order: Vec<String>,
|
|
236
246
|
}
|
|
237
247
|
|
|
@@ -241,26 +251,30 @@ pub struct QuoteStyleConfig {
|
|
|
241
251
|
pub key_style: String,
|
|
242
252
|
pub value_style: String,
|
|
243
253
|
#[serde(default)]
|
|
244
|
-
|
|
254
|
+
#[serde(alias = "path")]
|
|
255
|
+
pub selector: Option<String>,
|
|
245
256
|
}
|
|
246
257
|
|
|
247
258
|
#[derive(Debug, Clone, Deserialize)]
|
|
248
259
|
pub struct CollectionStyleConfig {
|
|
249
260
|
pub style: String,
|
|
250
261
|
#[serde(default)]
|
|
251
|
-
|
|
262
|
+
#[serde(alias = "path")]
|
|
263
|
+
pub selector: Option<String>,
|
|
252
264
|
}
|
|
253
265
|
|
|
254
266
|
#[derive(Debug, Clone, Deserialize)]
|
|
255
267
|
pub struct SequenceIndentConfig {
|
|
256
268
|
pub style: String,
|
|
257
269
|
#[serde(default)]
|
|
258
|
-
|
|
270
|
+
#[serde(alias = "path")]
|
|
271
|
+
pub selector: Option<String>,
|
|
259
272
|
}
|
|
260
273
|
|
|
261
274
|
#[derive(Debug, Clone, Deserialize)]
|
|
262
275
|
pub struct SetConfig {
|
|
263
|
-
|
|
276
|
+
#[serde(alias = "path")]
|
|
277
|
+
pub selector: String,
|
|
264
278
|
pub value: String,
|
|
265
279
|
#[serde(default)]
|
|
266
280
|
pub condition: Option<String>,
|
|
@@ -270,7 +284,8 @@ pub struct SetConfig {
|
|
|
270
284
|
|
|
271
285
|
#[derive(Debug, Clone, Deserialize)]
|
|
272
286
|
pub struct InsertConfig {
|
|
273
|
-
|
|
287
|
+
#[serde(alias = "path")]
|
|
288
|
+
pub selector: String,
|
|
274
289
|
pub value: String,
|
|
275
290
|
#[serde(default)]
|
|
276
291
|
pub condition: Option<String>,
|
|
@@ -280,7 +295,8 @@ pub struct InsertConfig {
|
|
|
280
295
|
|
|
281
296
|
#[derive(Debug, Clone, Deserialize)]
|
|
282
297
|
pub struct DeleteConfig {
|
|
283
|
-
|
|
298
|
+
#[serde(alias = "path")]
|
|
299
|
+
pub selector: String,
|
|
284
300
|
#[serde(default)]
|
|
285
301
|
pub condition: Option<String>,
|
|
286
302
|
}
|
|
@@ -301,6 +317,7 @@ impl Yerbafile {
|
|
|
301
317
|
let content = fs::read_to_string(path.as_ref())?;
|
|
302
318
|
let mut yerbafile: Yerbafile = yaml_serde::from_str(&content).map_err(|error| YerbaError::ParseError(format!("{}", error)))?;
|
|
303
319
|
yerbafile.directory = path.as_ref().parent().map(|p| p.to_path_buf());
|
|
320
|
+
yerbafile.deprecated_path_keys = deprecated_path_keys(&content);
|
|
304
321
|
yerbafile.validate_conditions()?;
|
|
305
322
|
Ok(yerbafile)
|
|
306
323
|
}
|
|
@@ -359,7 +376,7 @@ impl Yerbafile {
|
|
|
359
376
|
}
|
|
360
377
|
}
|
|
361
378
|
|
|
362
|
-
pub fn sort_order_for(&self, file_path: &str,
|
|
379
|
+
pub fn sort_order_for(&self, file_path: &str, selector: &str) -> Option<Vec<String>> {
|
|
363
380
|
for rule in &self.rules {
|
|
364
381
|
let sort_keys_config = rule.pipeline.iter().find_map(|step| match step {
|
|
365
382
|
PipelineStep::SortKeys(config) => Some(config),
|
|
@@ -367,10 +384,10 @@ impl Yerbafile {
|
|
|
367
384
|
});
|
|
368
385
|
|
|
369
386
|
if let Some(config) = sort_keys_config {
|
|
370
|
-
let
|
|
371
|
-
let normalized =
|
|
387
|
+
let full_selector = resolve_step_selector(rule.selector.as_deref(), config.selector.as_deref());
|
|
388
|
+
let normalized = full_selector.trim_end_matches("[]").trim_end_matches('.');
|
|
372
389
|
|
|
373
|
-
if normalized !=
|
|
390
|
+
if normalized != selector && !normalized.is_empty() && !selector.is_empty() {
|
|
374
391
|
continue;
|
|
375
392
|
}
|
|
376
393
|
|
|
@@ -472,10 +489,10 @@ impl Yerbafile {
|
|
|
472
489
|
}
|
|
473
490
|
}
|
|
474
491
|
|
|
475
|
-
let
|
|
492
|
+
let base_selector = rule.selector.as_deref();
|
|
476
493
|
|
|
477
494
|
for step in &rule.pipeline {
|
|
478
|
-
if let Err(error) = execute_step(&mut document, step,
|
|
495
|
+
if let Err(error) = execute_step(&mut document, step, base_selector, file, self) {
|
|
479
496
|
return RuleResult {
|
|
480
497
|
file: file.to_string(),
|
|
481
498
|
changed: false,
|
|
@@ -635,10 +652,10 @@ impl Yerbafile {
|
|
|
635
652
|
}
|
|
636
653
|
}
|
|
637
654
|
|
|
638
|
-
let
|
|
655
|
+
let base_selector = rule.selector.as_deref();
|
|
639
656
|
|
|
640
657
|
for step in &rule.pipeline {
|
|
641
|
-
execute_step(document, step,
|
|
658
|
+
execute_step(document, step, base_selector, file_path, self)?;
|
|
642
659
|
}
|
|
643
660
|
}
|
|
644
661
|
|
|
@@ -652,7 +669,7 @@ fn control_character_error(source: &str) -> Option<YerbaError> {
|
|
|
652
669
|
(!found.is_empty()).then_some(YerbaError::ControlCharacters(found))
|
|
653
670
|
}
|
|
654
671
|
|
|
655
|
-
fn execute_pipeline(document: &mut Document, steps: &[PipelineStep],
|
|
672
|
+
fn execute_pipeline(document: &mut Document, steps: &[PipelineStep], base_selector: Option<&str>, file: &str, yerbafile: &Yerbafile) -> Result<(), YerbaError> {
|
|
656
673
|
use crate::document::style::StyleEnforcement;
|
|
657
674
|
|
|
658
675
|
let mut enforcement = StyleEnforcement {
|
|
@@ -667,17 +684,17 @@ fn execute_pipeline(document: &mut Document, steps: &[PipelineStep], base_path:
|
|
|
667
684
|
|
|
668
685
|
for step in steps {
|
|
669
686
|
match step {
|
|
670
|
-
PipelineStep::CollectionStyle(config) if config.
|
|
687
|
+
PipelineStep::CollectionStyle(config) if config.selector.is_none() && base_selector.is_none() => {
|
|
671
688
|
enforcement.collection_style = Some(config.style.clone());
|
|
672
689
|
has_enforcement = true;
|
|
673
690
|
}
|
|
674
691
|
|
|
675
|
-
PipelineStep::SequenceIndent(config) if config.
|
|
692
|
+
PipelineStep::SequenceIndent(config) if config.selector.is_none() && base_selector.is_none() => {
|
|
676
693
|
enforcement.sequence_indent = Some(config.style.clone());
|
|
677
694
|
has_enforcement = true;
|
|
678
695
|
}
|
|
679
696
|
|
|
680
|
-
PipelineStep::QuoteStyle(config) if config.
|
|
697
|
+
PipelineStep::QuoteStyle(config) if config.selector.is_none() && base_selector.is_none() => {
|
|
681
698
|
let key_style = config.key_style.parse::<crate::KeyStyle>().ok();
|
|
682
699
|
let value_style = config.value_style.parse::<QuoteStyle>().ok();
|
|
683
700
|
|
|
@@ -695,23 +712,23 @@ fn execute_pipeline(document: &mut Document, steps: &[PipelineStep], base_path:
|
|
|
695
712
|
}
|
|
696
713
|
|
|
697
714
|
for step in remaining_steps {
|
|
698
|
-
execute_step(document, step,
|
|
715
|
+
execute_step(document, step, base_selector, file, yerbafile)?;
|
|
699
716
|
}
|
|
700
717
|
|
|
701
718
|
Ok(())
|
|
702
719
|
}
|
|
703
720
|
|
|
704
|
-
fn execute_step(document: &mut Document, step: &PipelineStep,
|
|
721
|
+
fn execute_step(document: &mut Document, step: &PipelineStep, base_selector: Option<&str>, _file: &str, yerbafile: &Yerbafile) -> Result<(), YerbaError> {
|
|
705
722
|
match step {
|
|
706
723
|
PipelineStep::QuoteStyle(config) => {
|
|
707
|
-
let
|
|
724
|
+
let selector = config.selector.as_deref();
|
|
708
725
|
|
|
709
726
|
let key_style = config.key_style.parse::<crate::KeyStyle>().map_err(YerbaError::ParseError)?;
|
|
710
727
|
|
|
711
728
|
let value_style = config.value_style.parse::<QuoteStyle>().map_err(YerbaError::ParseError)?;
|
|
712
729
|
|
|
713
|
-
document.enforce_key_style(&key_style,
|
|
714
|
-
let warnings = document.enforce_quotes_at(&value_style,
|
|
730
|
+
document.enforce_key_style(&key_style, selector)?;
|
|
731
|
+
let warnings = document.enforce_quotes_at(&value_style, selector)?;
|
|
715
732
|
|
|
716
733
|
for warning in &warnings {
|
|
717
734
|
eprintln!(" warning: {}", warning);
|
|
@@ -721,52 +738,52 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
721
738
|
}
|
|
722
739
|
|
|
723
740
|
PipelineStep::CollectionStyle(config) => {
|
|
724
|
-
let
|
|
725
|
-
let path = if
|
|
741
|
+
let selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
742
|
+
let path = if selector.is_empty() { None } else { Some(selector.as_str()) };
|
|
726
743
|
|
|
727
744
|
document.enforce_collection_style(&config.style, path)
|
|
728
745
|
}
|
|
729
746
|
|
|
730
747
|
PipelineStep::SequenceIndent(config) => {
|
|
731
|
-
let
|
|
732
|
-
let path = if
|
|
748
|
+
let selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
749
|
+
let path = if selector.is_empty() { None } else { Some(selector.as_str()) };
|
|
733
750
|
|
|
734
751
|
document.enforce_sequence_indent(&config.style, path)
|
|
735
752
|
}
|
|
736
753
|
|
|
737
754
|
PipelineStep::SortKeys(config) => {
|
|
738
|
-
let
|
|
755
|
+
let full_selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
739
756
|
let key_order: Vec<&str> = config.order.iter().map(|key| key.as_str()).collect();
|
|
740
757
|
|
|
741
|
-
document.validate_sort_keys(&
|
|
742
|
-
document.sort_keys(&
|
|
758
|
+
document.validate_sort_keys(&full_selector, &key_order)?;
|
|
759
|
+
document.sort_keys(&full_selector, &key_order)
|
|
743
760
|
}
|
|
744
761
|
|
|
745
762
|
PipelineStep::Set(config) => {
|
|
746
|
-
let
|
|
763
|
+
let full_selector = resolve_step_selector(base_selector, Some(&config.selector));
|
|
747
764
|
|
|
748
765
|
if let Some(condition) = &config.condition {
|
|
749
|
-
let
|
|
766
|
+
let parent_selector = full_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
750
767
|
|
|
751
|
-
if !document.evaluate_condition(
|
|
768
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
752
769
|
return Ok(());
|
|
753
770
|
}
|
|
754
771
|
}
|
|
755
772
|
|
|
756
773
|
if config.plain {
|
|
757
|
-
document.set_plain(&
|
|
774
|
+
document.set_plain(&full_selector, &config.value)
|
|
758
775
|
} else {
|
|
759
|
-
document.set(&
|
|
776
|
+
document.set(&full_selector, &config.value)
|
|
760
777
|
}
|
|
761
778
|
}
|
|
762
779
|
|
|
763
780
|
PipelineStep::Insert(config) => {
|
|
764
|
-
let
|
|
781
|
+
let full_selector = resolve_step_selector(base_selector, Some(&config.selector));
|
|
765
782
|
|
|
766
783
|
if let Some(condition) = &config.condition {
|
|
767
|
-
let
|
|
784
|
+
let parent_selector = full_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
768
785
|
|
|
769
|
-
if !document.evaluate_condition(
|
|
786
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
770
787
|
return Ok(());
|
|
771
788
|
}
|
|
772
789
|
}
|
|
@@ -777,20 +794,20 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
777
794
|
crate::syntax::quote_scalar(&config.value)
|
|
778
795
|
};
|
|
779
796
|
|
|
780
|
-
document.insert_into(&
|
|
797
|
+
document.insert_into(&full_selector, &value, crate::InsertPosition::Last)
|
|
781
798
|
}
|
|
782
799
|
|
|
783
800
|
PipelineStep::Delete(config) => {
|
|
784
|
-
let
|
|
801
|
+
let full_selector = resolve_step_selector(base_selector, Some(&config.selector));
|
|
785
802
|
|
|
786
|
-
if
|
|
787
|
-
let concrete_selectors = document.resolve_selectors(&
|
|
803
|
+
if full_selector.contains("[]") {
|
|
804
|
+
let concrete_selectors = document.resolve_selectors(&full_selector);
|
|
788
805
|
|
|
789
806
|
for selector in concrete_selectors.into_iter().rev() {
|
|
790
807
|
if let Some(condition) = &config.condition {
|
|
791
|
-
let
|
|
808
|
+
let parent_selector = selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
792
809
|
|
|
793
|
-
if !document.evaluate_condition(
|
|
810
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
794
811
|
continue;
|
|
795
812
|
}
|
|
796
813
|
}
|
|
@@ -801,47 +818,47 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
801
818
|
Ok(())
|
|
802
819
|
} else {
|
|
803
820
|
if let Some(condition) = &config.condition {
|
|
804
|
-
let
|
|
821
|
+
let parent_selector = full_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
805
822
|
|
|
806
|
-
if !document.evaluate_condition(
|
|
823
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
807
824
|
return Ok(());
|
|
808
825
|
}
|
|
809
826
|
}
|
|
810
827
|
|
|
811
|
-
document.delete(&
|
|
828
|
+
document.delete(&full_selector)
|
|
812
829
|
}
|
|
813
830
|
}
|
|
814
831
|
|
|
815
832
|
PipelineStep::Rename(config) => {
|
|
816
|
-
let
|
|
833
|
+
let full_selector = resolve_step_selector(base_selector, Some(&config.from));
|
|
817
834
|
|
|
818
835
|
if let Some(condition) = &config.condition {
|
|
819
|
-
let
|
|
836
|
+
let parent_selector = full_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
820
837
|
|
|
821
|
-
if !document.evaluate_condition(
|
|
838
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
822
839
|
return Ok(());
|
|
823
840
|
}
|
|
824
841
|
}
|
|
825
842
|
|
|
826
|
-
document.rename(&
|
|
843
|
+
document.rename(&full_selector, &config.to)
|
|
827
844
|
}
|
|
828
845
|
|
|
829
846
|
PipelineStep::Remove(config) => {
|
|
830
|
-
let
|
|
847
|
+
let full_selector = resolve_step_selector(base_selector, Some(&config.selector));
|
|
831
848
|
|
|
832
849
|
if let Some(condition) = &config.condition {
|
|
833
|
-
let
|
|
850
|
+
let parent_selector = full_selector.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
834
851
|
|
|
835
|
-
if !document.evaluate_condition(
|
|
852
|
+
if !document.evaluate_condition(parent_selector, condition)? {
|
|
836
853
|
return Ok(());
|
|
837
854
|
}
|
|
838
855
|
}
|
|
839
856
|
|
|
840
|
-
document.remove(&
|
|
857
|
+
document.remove(&full_selector, &config.value)
|
|
841
858
|
}
|
|
842
859
|
|
|
843
860
|
PipelineStep::BlankLines(config) => {
|
|
844
|
-
let
|
|
861
|
+
let full_selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
845
862
|
|
|
846
863
|
let options = crate::BlankLineOptions {
|
|
847
864
|
before: config.before.clone(),
|
|
@@ -849,14 +866,14 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
849
866
|
skip_empty: config.skip_empty,
|
|
850
867
|
};
|
|
851
868
|
|
|
852
|
-
document.enforce_blank_lines_with(&
|
|
869
|
+
document.enforce_blank_lines_with(&full_selector, config.count, &options)
|
|
853
870
|
}
|
|
854
871
|
|
|
855
872
|
PipelineStep::Sort(config) => {
|
|
856
|
-
let
|
|
873
|
+
let full_selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
857
874
|
let sort_fields = config.by.as_deref().map(crate::SortField::parse_list).unwrap_or_default();
|
|
858
875
|
|
|
859
|
-
document.sort_items(&
|
|
876
|
+
document.sort_items(&full_selector, &sort_fields, config.case_sensitive)
|
|
860
877
|
}
|
|
861
878
|
|
|
862
879
|
PipelineStep::Directives(config) => {
|
|
@@ -868,7 +885,7 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
868
885
|
let locations = document.directive_locations();
|
|
869
886
|
|
|
870
887
|
if locations.len() > max {
|
|
871
|
-
let positions: Vec<String> = locations.iter().map(|(line,
|
|
888
|
+
let positions: Vec<String> = locations.iter().map(|(line, column)| format!("{}:{}", line, column + 1)).collect();
|
|
872
889
|
|
|
873
890
|
return Err(YerbaError::ParseError(format!(
|
|
874
891
|
"found {} directive markers (---) at {}, expected at most {}",
|
|
@@ -891,7 +908,7 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
891
908
|
PipelineStep::Schema(config) => {
|
|
892
909
|
let schema_path = yerbafile.resolve_path(&config.file);
|
|
893
910
|
let schema = crate::schema::load_schema(&schema_path)?;
|
|
894
|
-
let selector =
|
|
911
|
+
let selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
895
912
|
let errors = document.validate_schema(&schema, config.items, if selector.is_empty() { None } else { Some(&selector) });
|
|
896
913
|
|
|
897
914
|
if errors.is_empty() {
|
|
@@ -902,8 +919,8 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
902
919
|
}
|
|
903
920
|
|
|
904
921
|
PipelineStep::Unique(config) => {
|
|
905
|
-
let
|
|
906
|
-
let duplicates = document.unique_with_options(&
|
|
922
|
+
let full_selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
923
|
+
let duplicates = document.unique_with_options(&full_selector, &config.by, config.remove, config.allow_blank_duplicates)?;
|
|
907
924
|
|
|
908
925
|
if !duplicates.is_empty() && !config.remove {
|
|
909
926
|
return Err(YerbaError::DuplicateValues(duplicates));
|
|
@@ -915,17 +932,17 @@ fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<
|
|
|
915
932
|
PipelineStep::FinalNewline(config) => document.enforce_final_newline(config.count),
|
|
916
933
|
|
|
917
934
|
PipelineStep::Escapes(config) => {
|
|
918
|
-
let
|
|
919
|
-
let scope = if
|
|
935
|
+
let full_selector = resolve_step_selector(base_selector, config.selector.as_deref());
|
|
936
|
+
let scope = if full_selector.is_empty() { None } else { Some(full_selector.as_str()) };
|
|
920
937
|
|
|
921
938
|
document.decode_escapes(scope).map(|_| ())
|
|
922
939
|
}
|
|
923
940
|
}
|
|
924
941
|
}
|
|
925
942
|
|
|
926
|
-
fn
|
|
927
|
-
let base =
|
|
928
|
-
let step =
|
|
943
|
+
fn resolve_step_selector(base_selector: Option<&str>, step_selector: Option<&str>) -> String {
|
|
944
|
+
let base = base_selector.unwrap_or("");
|
|
945
|
+
let step = step_selector.unwrap_or("");
|
|
929
946
|
|
|
930
947
|
match (base.is_empty(), step.is_empty()) {
|
|
931
948
|
(true, true) => String::new(),
|
|
@@ -934,3 +951,34 @@ fn resolve_step_path(base_path: Option<&str>, step_path: Option<&str>) -> String
|
|
|
934
951
|
(false, false) => format!("{}.{}", base, step),
|
|
935
952
|
}
|
|
936
953
|
}
|
|
954
|
+
|
|
955
|
+
// TODO(v1.0): remove together with the `path` aliases on the rule and step configs.
|
|
956
|
+
fn deprecated_path_keys(content: &str) -> Vec<String> {
|
|
957
|
+
let Ok(yerbafile) = yaml_serde::from_str::<yaml_serde::Value>(content) else {
|
|
958
|
+
return Vec::new();
|
|
959
|
+
};
|
|
960
|
+
|
|
961
|
+
let mut found = Vec::new();
|
|
962
|
+
|
|
963
|
+
let check_pipeline = |pipeline: Option<&yaml_serde::Value>, prefix: &str, found: &mut Vec<String>| {
|
|
964
|
+
for (index, step) in pipeline.and_then(|pipeline| pipeline.as_sequence()).into_iter().flatten().enumerate() {
|
|
965
|
+
for (name, config) in step.as_mapping().into_iter().flatten() {
|
|
966
|
+
if config.get("path").is_some() {
|
|
967
|
+
found.push(format!("{}pipeline[{}].{}", prefix, index, name.as_str().unwrap_or_default()));
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
|
|
973
|
+
check_pipeline(yerbafile.get("pipeline"), "", &mut found);
|
|
974
|
+
|
|
975
|
+
for (index, rule) in yerbafile.get("rules").and_then(|rules| rules.as_sequence()).into_iter().flatten().enumerate() {
|
|
976
|
+
if rule.get("path").is_some() {
|
|
977
|
+
found.push(format!("rules[{}]", index));
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
check_pipeline(rule.get("pipeline"), &format!("rules[{}].", index), &mut found);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
found
|
|
984
|
+
}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yerba
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: arm-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Roth
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A CLI tool for editing YAML while preserving structure, comments, and
|
|
14
14
|
format.
|
|
@@ -39,6 +39,7 @@ files:
|
|
|
39
39
|
- lib/yerba/node.rb
|
|
40
40
|
- lib/yerba/query_result.rb
|
|
41
41
|
- lib/yerba/scalar.rb
|
|
42
|
+
- lib/yerba/selector.rb
|
|
42
43
|
- lib/yerba/sequence.rb
|
|
43
44
|
- lib/yerba/version.rb
|
|
44
45
|
- lib/yerba/yerbafile.rb
|
|
@@ -77,6 +78,7 @@ files:
|
|
|
77
78
|
- rust/src/document/get.rs
|
|
78
79
|
- rust/src/document/insert.rs
|
|
79
80
|
- rust/src/document/mod.rs
|
|
81
|
+
- rust/src/document/nodes.rs
|
|
80
82
|
- rust/src/document/schema.rs
|
|
81
83
|
- rust/src/document/set.rs
|
|
82
84
|
- rust/src/document/sort.rs
|