yerba 0.1.1 → 0.2.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/README.md +492 -15
- data/ext/yerba/extconf.rb +87 -30
- data/ext/yerba/include/yerba.h +168 -0
- data/ext/yerba/yerba.c +752 -0
- data/lib/yerba/collection.rb +31 -0
- data/lib/yerba/document.rb +59 -0
- data/lib/yerba/formatting.rb +18 -0
- data/lib/yerba/location.rb +5 -0
- data/lib/yerba/map.rb +166 -0
- data/lib/yerba/scalar.rb +85 -0
- data/lib/yerba/sequence.rb +182 -0
- data/lib/yerba/version.rb +1 -1
- data/lib/yerba.rb +30 -4
- data/rust/Cargo.lock +378 -2
- data/rust/Cargo.toml +5 -1
- data/rust/build.rs +11 -0
- data/rust/cbindgen.toml +27 -0
- data/rust/src/commands/apply.rs +5 -0
- data/rust/src/commands/blank_lines.rs +58 -0
- data/rust/src/commands/check.rs +5 -0
- data/rust/src/commands/delete.rs +35 -0
- data/rust/src/commands/get.rs +194 -0
- data/rust/src/commands/init.rs +89 -0
- data/rust/src/commands/insert.rs +106 -0
- data/rust/src/commands/mate.rs +55 -0
- data/rust/src/commands/mod.rs +349 -0
- data/rust/src/commands/move_item.rs +54 -0
- data/rust/src/commands/move_key.rs +87 -0
- data/rust/src/commands/quote_style.rs +62 -0
- data/rust/src/commands/remove.rs +35 -0
- data/rust/src/commands/rename.rs +37 -0
- data/rust/src/commands/set.rs +59 -0
- data/rust/src/commands/sort.rs +52 -0
- data/rust/src/commands/sort_keys.rs +62 -0
- data/rust/src/commands/version.rs +8 -0
- data/rust/src/document.rs +798 -340
- data/rust/src/error.rs +0 -5
- data/rust/src/ffi.rs +991 -0
- data/rust/src/json.rs +49 -90
- data/rust/src/lib.rs +9 -2
- data/rust/src/main.rs +55 -839
- data/rust/src/selector.rs +241 -0
- data/rust/src/syntax.rs +97 -21
- data/rust/src/yaml_writer.rs +89 -0
- data/rust/src/yerbafile.rs +34 -122
- data/yerba.gemspec +4 -0
- metadata +33 -1
data/rust/src/yerbafile.rs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
use rayon::prelude::*;
|
|
2
2
|
use serde::Deserialize;
|
|
3
|
-
use std::collections::HashMap;
|
|
4
3
|
use std::fs;
|
|
5
4
|
use std::path::{Path, PathBuf};
|
|
6
5
|
|
|
@@ -22,7 +21,6 @@ pub struct Rule {
|
|
|
22
21
|
|
|
23
22
|
#[derive(Debug, Clone)]
|
|
24
23
|
pub enum PipelineStep {
|
|
25
|
-
Get(GetConfig),
|
|
26
24
|
SortKeys(SortKeysConfig),
|
|
27
25
|
QuoteStyle(QuoteStyleConfig),
|
|
28
26
|
Set(SetConfig),
|
|
@@ -31,28 +29,24 @@ pub enum PipelineStep {
|
|
|
31
29
|
Rename(RenameConfig),
|
|
32
30
|
Remove(RemoveConfig),
|
|
33
31
|
BlankLines(BlankLinesConfig),
|
|
32
|
+
Sort(SortConfig),
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
#[derive(Debug, Clone, Deserialize)]
|
|
37
|
-
pub struct
|
|
36
|
+
pub struct SortConfig {
|
|
38
37
|
#[serde(default)]
|
|
39
38
|
pub path: Option<String>,
|
|
40
|
-
|
|
39
|
+
#[serde(default)]
|
|
40
|
+
pub by: Option<String>,
|
|
41
|
+
#[serde(default)]
|
|
42
|
+
pub case_sensitive: bool,
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
#[derive(Debug, Clone, Deserialize)]
|
|
44
|
-
pub struct
|
|
45
|
-
pub path: String,
|
|
46
|
-
#[serde(rename = "as")]
|
|
47
|
-
pub as_name: String,
|
|
46
|
+
pub struct BlankLinesConfig {
|
|
48
47
|
#[serde(default)]
|
|
49
|
-
pub
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
#[derive(Debug, Clone)]
|
|
53
|
-
pub enum Variable {
|
|
54
|
-
Single(String),
|
|
55
|
-
List(Vec<String>),
|
|
48
|
+
pub path: Option<String>,
|
|
49
|
+
pub count: usize,
|
|
56
50
|
}
|
|
57
51
|
|
|
58
52
|
#[derive(Debug, Clone, Deserialize)]
|
|
@@ -78,11 +72,6 @@ impl<'de> Deserialize<'de> for PipelineStep {
|
|
|
78
72
|
{
|
|
79
73
|
let mapping = serde_yaml::Mapping::deserialize(deserializer)?;
|
|
80
74
|
|
|
81
|
-
if let Some(value) = mapping.get(serde_yaml::Value::String("get".to_string())) {
|
|
82
|
-
let config: GetConfig = serde_yaml::from_value(value.clone()).map_err(serde::de::Error::custom)?;
|
|
83
|
-
return Ok(PipelineStep::Get(config));
|
|
84
|
-
}
|
|
85
|
-
|
|
86
75
|
if let Some(value) = mapping.get(serde_yaml::Value::String("sort_keys".to_string())) {
|
|
87
76
|
let config: SortKeysConfig = serde_yaml::from_value(value.clone()).map_err(serde::de::Error::custom)?;
|
|
88
77
|
return Ok(PipelineStep::SortKeys(config));
|
|
@@ -123,8 +112,13 @@ impl<'de> Deserialize<'de> for PipelineStep {
|
|
|
123
112
|
return Ok(PipelineStep::BlankLines(config));
|
|
124
113
|
}
|
|
125
114
|
|
|
115
|
+
if let Some(value) = mapping.get(serde_yaml::Value::String("sort".to_string())) {
|
|
116
|
+
let config: SortConfig = serde_yaml::from_value(value.clone()).map_err(serde::de::Error::custom)?;
|
|
117
|
+
return Ok(PipelineStep::Sort(config));
|
|
118
|
+
}
|
|
119
|
+
|
|
126
120
|
Err(serde::de::Error::custom(
|
|
127
|
-
"unknown pipeline step: expected
|
|
121
|
+
"unknown pipeline step: expected sort_keys, quote_style, set, insert, delete, rename, remove, blank_lines, or sort",
|
|
128
122
|
))
|
|
129
123
|
}
|
|
130
124
|
}
|
|
@@ -322,10 +316,9 @@ impl Yerbafile {
|
|
|
322
316
|
|
|
323
317
|
let original = document.to_string();
|
|
324
318
|
let base_path = rule.path.as_deref();
|
|
325
|
-
let mut variables: HashMap<String, Variable> = HashMap::new();
|
|
326
319
|
|
|
327
320
|
for step in &rule.pipeline {
|
|
328
|
-
if let Err(error) = execute_step(&mut document, step, base_path
|
|
321
|
+
if let Err(error) = execute_step(&mut document, step, base_path) {
|
|
329
322
|
return RuleResult {
|
|
330
323
|
file: file.to_string(),
|
|
331
324
|
changed: false,
|
|
@@ -355,46 +348,8 @@ impl Yerbafile {
|
|
|
355
348
|
}
|
|
356
349
|
}
|
|
357
350
|
|
|
358
|
-
fn execute_step(
|
|
359
|
-
document: &mut Document,
|
|
360
|
-
step: &PipelineStep,
|
|
361
|
-
base_path: Option<&str>,
|
|
362
|
-
variables: &mut HashMap<String, Variable>,
|
|
363
|
-
) -> Result<(), YerbaError> {
|
|
351
|
+
fn execute_step(document: &mut Document, step: &PipelineStep, base_path: Option<&str>) -> Result<(), YerbaError> {
|
|
364
352
|
match step {
|
|
365
|
-
PipelineStep::Get(config) => {
|
|
366
|
-
let full_path = resolve_step_path(base_path, Some(&config.path));
|
|
367
|
-
|
|
368
|
-
if let Some(file_pattern) = &config.file {
|
|
369
|
-
let mut all_values = Vec::new();
|
|
370
|
-
|
|
371
|
-
let files =
|
|
372
|
-
glob::glob(file_pattern).map_err(|error| YerbaError::ParseError(format!("invalid glob: {}", error)))?;
|
|
373
|
-
|
|
374
|
-
for entry in files.flatten() {
|
|
375
|
-
let external_document = Document::parse_file(&entry)?;
|
|
376
|
-
all_values.extend(external_document.get_all(&config.path));
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if all_values.len() == 1 && !config.path.contains('[') {
|
|
380
|
-
variables.insert(config.as_name.clone(), Variable::Single(all_values.remove(0)));
|
|
381
|
-
} else {
|
|
382
|
-
variables.insert(config.as_name.clone(), Variable::List(all_values));
|
|
383
|
-
}
|
|
384
|
-
} else if config.path.contains('[') {
|
|
385
|
-
let values = document.get_all(&full_path);
|
|
386
|
-
|
|
387
|
-
variables.insert(config.as_name.clone(), Variable::List(values));
|
|
388
|
-
} else {
|
|
389
|
-
let value = document
|
|
390
|
-
.get(&full_path)
|
|
391
|
-
.ok_or_else(|| YerbaError::PathNotFound(full_path.clone()))?;
|
|
392
|
-
variables.insert(config.as_name.clone(), Variable::Single(value));
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
Ok(())
|
|
396
|
-
}
|
|
397
|
-
|
|
398
353
|
PipelineStep::QuoteStyle(config) => {
|
|
399
354
|
let dot_path = config.path.as_deref();
|
|
400
355
|
|
|
@@ -420,44 +375,39 @@ fn execute_step(
|
|
|
420
375
|
|
|
421
376
|
PipelineStep::Set(config) => {
|
|
422
377
|
let full_path = resolve_step_path(base_path, Some(&config.path));
|
|
423
|
-
let resolved_value = resolve_template(&config.value, document, base_path, variables)?;
|
|
424
378
|
|
|
425
379
|
if let Some(condition) = &config.condition {
|
|
426
|
-
let resolved_condition = resolve_template(condition, document, base_path, variables)?;
|
|
427
380
|
let parent_path = full_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
428
381
|
|
|
429
|
-
if !document.evaluate_condition(parent_path,
|
|
382
|
+
if !document.evaluate_condition(parent_path, condition) {
|
|
430
383
|
return Ok(());
|
|
431
384
|
}
|
|
432
385
|
}
|
|
433
386
|
|
|
434
|
-
document.set(&full_path, &
|
|
387
|
+
document.set(&full_path, &config.value)
|
|
435
388
|
}
|
|
436
389
|
|
|
437
390
|
PipelineStep::Insert(config) => {
|
|
438
391
|
let full_path = resolve_step_path(base_path, Some(&config.path));
|
|
439
|
-
let resolved_value = resolve_template(&config.value, document, base_path, variables)?;
|
|
440
392
|
|
|
441
393
|
if let Some(condition) = &config.condition {
|
|
442
|
-
let resolved_condition = resolve_template(condition, document, base_path, variables)?;
|
|
443
394
|
let parent_path = full_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
444
395
|
|
|
445
|
-
if !document.evaluate_condition(parent_path,
|
|
396
|
+
if !document.evaluate_condition(parent_path, condition) {
|
|
446
397
|
return Ok(());
|
|
447
398
|
}
|
|
448
399
|
}
|
|
449
400
|
|
|
450
|
-
document.insert_into(&full_path, &
|
|
401
|
+
document.insert_into(&full_path, &config.value, crate::InsertPosition::Last)
|
|
451
402
|
}
|
|
452
403
|
|
|
453
404
|
PipelineStep::Delete(config) => {
|
|
454
405
|
let full_path = resolve_step_path(base_path, Some(&config.path));
|
|
455
406
|
|
|
456
407
|
if let Some(condition) = &config.condition {
|
|
457
|
-
let resolved_condition = resolve_template(condition, document, base_path, variables)?;
|
|
458
408
|
let parent_path = full_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
459
409
|
|
|
460
|
-
if !document.evaluate_condition(parent_path,
|
|
410
|
+
if !document.evaluate_condition(parent_path, condition) {
|
|
461
411
|
return Ok(());
|
|
462
412
|
}
|
|
463
413
|
}
|
|
@@ -469,10 +419,9 @@ fn execute_step(
|
|
|
469
419
|
let full_path = resolve_step_path(base_path, Some(&config.from));
|
|
470
420
|
|
|
471
421
|
if let Some(condition) = &config.condition {
|
|
472
|
-
let resolved_condition = resolve_template(condition, document, base_path, variables)?;
|
|
473
422
|
let parent_path = full_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
474
423
|
|
|
475
|
-
if !document.evaluate_condition(parent_path,
|
|
424
|
+
if !document.evaluate_condition(parent_path, condition) {
|
|
476
425
|
return Ok(());
|
|
477
426
|
}
|
|
478
427
|
}
|
|
@@ -482,18 +431,16 @@ fn execute_step(
|
|
|
482
431
|
|
|
483
432
|
PipelineStep::Remove(config) => {
|
|
484
433
|
let full_path = resolve_step_path(base_path, Some(&config.path));
|
|
485
|
-
let resolved_value = resolve_template(&config.value, document, base_path, variables)?;
|
|
486
434
|
|
|
487
435
|
if let Some(condition) = &config.condition {
|
|
488
|
-
let resolved_condition = resolve_template(condition, document, base_path, variables)?;
|
|
489
436
|
let parent_path = full_path.rsplit_once('.').map(|(parent, _)| parent).unwrap_or("");
|
|
490
437
|
|
|
491
|
-
if !document.evaluate_condition(parent_path,
|
|
438
|
+
if !document.evaluate_condition(parent_path, condition) {
|
|
492
439
|
return Ok(());
|
|
493
440
|
}
|
|
494
441
|
}
|
|
495
442
|
|
|
496
|
-
document.remove(&full_path, &
|
|
443
|
+
document.remove(&full_path, &config.value)
|
|
497
444
|
}
|
|
498
445
|
|
|
499
446
|
PipelineStep::BlankLines(config) => {
|
|
@@ -501,53 +448,18 @@ fn execute_step(
|
|
|
501
448
|
|
|
502
449
|
document.enforce_blank_lines(&full_path, config.count)
|
|
503
450
|
}
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
pub fn resolve_template(
|
|
508
|
-
template: &str,
|
|
509
|
-
document: &Document,
|
|
510
|
-
base_path: Option<&str>,
|
|
511
|
-
variables: &HashMap<String, Variable>,
|
|
512
|
-
) -> Result<String, YerbaError> {
|
|
513
|
-
if !template.contains("${") {
|
|
514
|
-
return Ok(template.to_string());
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
let mut result = String::new();
|
|
518
|
-
let mut rest = template;
|
|
519
|
-
|
|
520
|
-
while let Some(start) = rest.find("${") {
|
|
521
|
-
result.push_str(&rest[..start]);
|
|
522
451
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
let resolved = if let Some(variable) = variables.get(reference) {
|
|
532
|
-
match variable {
|
|
533
|
-
Variable::Single(value) => value.clone(),
|
|
534
|
-
Variable::List(values) => values.join(", "),
|
|
535
|
-
}
|
|
536
|
-
} else {
|
|
537
|
-
let full_path = resolve_step_path(base_path, Some(reference));
|
|
538
|
-
|
|
539
|
-
document
|
|
540
|
-
.get(&full_path)
|
|
541
|
-
.ok_or_else(|| YerbaError::ReferenceNotFound(reference.to_string()))?
|
|
542
|
-
};
|
|
452
|
+
PipelineStep::Sort(config) => {
|
|
453
|
+
let full_path = resolve_step_path(base_path, config.path.as_deref());
|
|
454
|
+
let sort_fields = config
|
|
455
|
+
.by
|
|
456
|
+
.as_deref()
|
|
457
|
+
.map(crate::SortField::parse_list)
|
|
458
|
+
.unwrap_or_default();
|
|
543
459
|
|
|
544
|
-
|
|
545
|
-
|
|
460
|
+
document.sort_items(&full_path, &sort_fields, config.case_sensitive)
|
|
461
|
+
}
|
|
546
462
|
}
|
|
547
|
-
|
|
548
|
-
result.push_str(rest);
|
|
549
|
-
|
|
550
|
-
Ok(result)
|
|
551
463
|
}
|
|
552
464
|
|
|
553
465
|
fn resolve_step_path(base_path: Option<&str>, step_path: Option<&str>) -> String {
|
data/yerba.gemspec
CHANGED
|
@@ -28,6 +28,10 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
"sig/**/*.rbs",
|
|
29
29
|
"exe/yerba",
|
|
30
30
|
"ext/yerba/extconf.rb",
|
|
31
|
+
"ext/yerba/yerba.c",
|
|
32
|
+
"ext/yerba/include/**/*.h",
|
|
33
|
+
"rust/build.rs",
|
|
34
|
+
"rust/cbindgen.toml",
|
|
31
35
|
"rust/Cargo.toml",
|
|
32
36
|
"rust/Cargo.lock",
|
|
33
37
|
"rust/src/**/*.rs",
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: yerba
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Marco Roth
|
|
@@ -23,18 +23,50 @@ files:
|
|
|
23
23
|
- README.md
|
|
24
24
|
- exe/yerba
|
|
25
25
|
- ext/yerba/extconf.rb
|
|
26
|
+
- ext/yerba/include/yerba.h
|
|
27
|
+
- ext/yerba/yerba.c
|
|
26
28
|
- lib/yerba.rb
|
|
29
|
+
- lib/yerba/collection.rb
|
|
30
|
+
- lib/yerba/document.rb
|
|
31
|
+
- lib/yerba/formatting.rb
|
|
32
|
+
- lib/yerba/location.rb
|
|
33
|
+
- lib/yerba/map.rb
|
|
34
|
+
- lib/yerba/scalar.rb
|
|
35
|
+
- lib/yerba/sequence.rb
|
|
27
36
|
- lib/yerba/version.rb
|
|
28
37
|
- rust/Cargo.lock
|
|
29
38
|
- rust/Cargo.toml
|
|
39
|
+
- rust/build.rs
|
|
40
|
+
- rust/cbindgen.toml
|
|
30
41
|
- rust/rustfmt.toml
|
|
42
|
+
- rust/src/commands/apply.rs
|
|
43
|
+
- rust/src/commands/blank_lines.rs
|
|
44
|
+
- rust/src/commands/check.rs
|
|
45
|
+
- rust/src/commands/delete.rs
|
|
46
|
+
- rust/src/commands/get.rs
|
|
47
|
+
- rust/src/commands/init.rs
|
|
48
|
+
- rust/src/commands/insert.rs
|
|
49
|
+
- rust/src/commands/mate.rs
|
|
50
|
+
- rust/src/commands/mod.rs
|
|
51
|
+
- rust/src/commands/move_item.rs
|
|
52
|
+
- rust/src/commands/move_key.rs
|
|
53
|
+
- rust/src/commands/quote_style.rs
|
|
54
|
+
- rust/src/commands/remove.rs
|
|
55
|
+
- rust/src/commands/rename.rs
|
|
56
|
+
- rust/src/commands/set.rs
|
|
57
|
+
- rust/src/commands/sort.rs
|
|
58
|
+
- rust/src/commands/sort_keys.rs
|
|
59
|
+
- rust/src/commands/version.rs
|
|
31
60
|
- rust/src/document.rs
|
|
32
61
|
- rust/src/error.rs
|
|
62
|
+
- rust/src/ffi.rs
|
|
33
63
|
- rust/src/json.rs
|
|
34
64
|
- rust/src/lib.rs
|
|
35
65
|
- rust/src/main.rs
|
|
36
66
|
- rust/src/quote_style.rs
|
|
67
|
+
- rust/src/selector.rs
|
|
37
68
|
- rust/src/syntax.rs
|
|
69
|
+
- rust/src/yaml_writer.rs
|
|
38
70
|
- rust/src/yerbafile.rs
|
|
39
71
|
- sig/yerba.rbs
|
|
40
72
|
- yerba.gemspec
|