yerba 0.8.0-x86_64-linux-gnu → 0.8.1-x86_64-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.
@@ -1,3 +1,4 @@
1
+ use super::ui;
1
2
  use std::process;
2
3
  use std::sync::LazyLock;
3
4
 
@@ -53,14 +54,14 @@ fn is_explicit_reorder(orders: &[String]) -> bool {
53
54
 
54
55
  impl Args {
55
56
  pub fn run(self) {
56
- use super::color::*;
57
+ use super::ui;
57
58
 
58
59
  if self.by.is_empty() && self.order.is_empty() && self.selector.is_none() {
59
60
  let document = parse_file(&self.file);
60
61
 
61
- eprintln!("{RED}Error:{RESET} specify a selector, --by, or --order");
62
+ eprintln!("{} specify a selector, --by, or --order", ui::failure("Error:"));
62
63
  eprintln!();
63
- eprintln!(" {BOLD}Examples:{RESET}");
64
+ eprintln!(" {}", ui::strong("Examples:"));
64
65
  eprintln!(" yerba sort \"{}\" \"tags\"", self.file);
65
66
  eprintln!(" yerba sort \"{}\" --by \".title\" --order asc", self.file);
66
67
  eprintln!();
@@ -80,10 +81,8 @@ impl Args {
80
81
  }
81
82
 
82
83
  fn show_values(self) {
83
- use super::color::*;
84
-
85
84
  if self.by.len() != 1 {
86
- eprintln!("{RED}Error:{RESET} --order is required when using --by");
85
+ eprintln!("{} --order is required when using --by", ui::failure("Error:"));
87
86
  process::exit(1);
88
87
  }
89
88
 
@@ -94,14 +93,14 @@ impl Args {
94
93
  let (labels, context_values, selector_display) = self.resolve_labels(&document, by, selector, &items_selector);
95
94
 
96
95
  let context_hint = if self.context.is_empty() {
97
- format!("\n\n {DIM}Add --context \".field\" to show additional fields alongside values{RESET}")
96
+ format!("\n\n {}", ui::subtle("Add --context \".field\" to show additional fields alongside values"))
98
97
  } else {
99
98
  String::new()
100
99
  };
101
100
 
102
- eprintln!("{RED}Error:{RESET} --order is required when using --by");
101
+ eprintln!("{} --order is required when using --by", ui::failure("Error:"));
103
102
  eprintln!();
104
- eprintln!(" {BOLD}Current values (by {by}):{RESET}");
103
+ eprintln!(" {}", ui::strong(format!("Current values (by {}):", by)));
105
104
 
106
105
  for (index, label) in labels.iter().enumerate() {
107
106
  let context = context_values.get(index).map(|c| c.as_slice()).unwrap_or(&[]);
@@ -113,22 +112,20 @@ impl Args {
113
112
 
114
113
  eprintln!("{context_hint}");
115
114
  eprintln!();
116
- eprintln!(" {BOLD}To sort alphabetically:{RESET}");
115
+ eprintln!(" {}", ui::strong("To sort alphabetically:"));
117
116
  eprintln!(" yerba sort \"{}\"{selector_display} --by \"{by}\" --order asc", self.file);
118
117
  eprintln!(" yerba sort \"{}\"{selector_display} --by \"{by}\" --order desc", self.file);
119
118
  eprintln!();
120
- eprintln!(" {BOLD}To reorder explicitly:{RESET}");
119
+ eprintln!(" {}", ui::strong("To reorder explicitly:"));
121
120
  eprintln!(" yerba sort \"{}\"{selector_display} --by \"{by}\" --order \"{csv}\"", self.file);
122
121
  eprintln!();
123
- eprintln!(" {BOLD}To move individual items:{RESET}");
122
+ eprintln!(" {}", ui::strong("To move individual items:"));
124
123
  eprintln!(" yerba move \"{}\"{selector_display} <item> --before/--after <target>", self.file);
125
124
 
126
125
  process::exit(1);
127
126
  }
128
127
 
129
128
  fn run_sort(self) {
130
- use super::color::*;
131
-
132
129
  let selector = self.selector.as_deref().unwrap_or("");
133
130
 
134
131
  let sort_fields: Vec<yerba::SortField> = if self.by.is_empty() {
@@ -145,7 +142,7 @@ impl Args {
145
142
  Some("desc" | "descending") => yerba::SortField::desc(field),
146
143
  Some("asc" | "ascending") | None => yerba::SortField::asc(field),
147
144
  Some(other) => {
148
- eprintln!("{RED}Error:{RESET} invalid sort direction \"{other}\". Use \"asc\" or \"desc\"");
145
+ eprintln!("{} invalid sort direction \"{other}\". Use \"asc\" or \"desc\"", ui::failure("Error:"));
149
146
  process::exit(1);
150
147
  }
151
148
  }
@@ -161,7 +158,7 @@ impl Args {
161
158
 
162
159
  match document.get_value(&first_item_selector) {
163
160
  Some(first) if first.is_mapping() => {
164
- eprintln!("{RED}Error:{RESET} --by is required to sort a sequence of maps");
161
+ eprintln!("{} --by is required to sort a sequence of maps", ui::failure("Error:"));
165
162
  eprintln!();
166
163
 
167
164
  let selectors = document.selectors();
@@ -175,7 +172,7 @@ impl Args {
175
172
  .collect();
176
173
 
177
174
  if !fields.is_empty() {
178
- eprintln!(" {BOLD}Available fields:{RESET}");
175
+ eprintln!(" {}", ui::strong("Available fields:"));
179
176
 
180
177
  for field in &fields {
181
178
  let short = field.rsplit_once('.').map(|(_, f)| f).unwrap_or(field);
@@ -187,9 +184,9 @@ impl Args {
187
184
  }
188
185
 
189
186
  None if selector.is_empty() => {
190
- eprintln!("{RED}Error:{RESET} no sequence found at root level in {}", resolved_file);
187
+ eprintln!("{} no sequence found at root level in {}", ui::failure("Error:"), resolved_file);
191
188
  eprintln!();
192
- eprintln!(" {DIM}Specify a selector for the sequence to sort:{RESET}");
189
+ eprintln!(" {}", ui::subtle("Specify a selector for the sequence to sort:"));
193
190
  eprintln!(" yerba sort \"{}\" \"<selector>\"", self.file);
194
191
  eprintln!();
195
192
 
@@ -209,16 +206,14 @@ impl Args {
209
206
  }
210
207
 
211
208
  fn run_reorder(self) {
212
- use super::color::*;
213
-
214
209
  if self.by.len() != 1 {
215
- eprintln!("{RED}Error:{RESET} explicit --order requires exactly one --by field");
210
+ eprintln!("{} explicit --order requires exactly one --by field", ui::failure("Error:"));
216
211
 
217
212
  process::exit(1);
218
213
  }
219
214
 
220
215
  if self.order.len() != 1 {
221
- eprintln!("{RED}Error:{RESET} explicit --order must be a single comma-separated list");
216
+ eprintln!("{} explicit --order must be a single comma-separated list", ui::failure("Error:"));
222
217
 
223
218
  process::exit(1);
224
219
  }
@@ -236,17 +231,17 @@ impl Args {
236
231
  let duplicates: Vec<&String> = labels.iter().filter(|label| !seen.insert(label.as_str())).collect();
237
232
 
238
233
  if !duplicates.is_empty() {
239
- eprintln!("{RED}Error:{RESET} --order requires unique values for {by}, but found duplicates");
234
+ eprintln!("{} --order requires unique values for {by}, but found duplicates", ui::failure("Error:"));
240
235
  eprintln!();
241
- eprintln!(" {BOLD}Duplicate values:{RESET}");
236
+ eprintln!(" {}", ui::strong("Duplicate values:"));
242
237
 
243
238
  for label in &duplicates {
244
239
  eprintln!(" {label}");
245
240
  }
246
241
 
247
242
  eprintln!();
248
- eprintln!(" {DIM}Use \"yerba sort\" with --by instead to sort by field, or");
249
- eprintln!(" choose a --by field with unique values (e.g. \".id\"){RESET}");
243
+ eprintln!(" {}", ui::subtle("Use \"yerba sort\" with --by instead to sort by field, or"));
244
+ eprintln!(" {}", ui::subtle("choose a --by field with unique values (e.g. \".id\")"));
250
245
 
251
246
  process::exit(1);
252
247
  }
@@ -256,16 +251,19 @@ impl Args {
256
251
  if !values_with_commas.is_empty() {
257
252
  let selector_display = if selector.is_empty() { String::new() } else { format!(" \"{selector}\"") };
258
253
 
259
- eprintln!("{RED}Error:{RESET} some values for {by} contain commas, which conflicts with --order parsing");
254
+ eprintln!(
255
+ "{} some values for {by} contain commas, which conflicts with --order parsing",
256
+ ui::failure("Error:")
257
+ );
260
258
  eprintln!();
261
- eprintln!(" {BOLD}Values with commas:{RESET}");
259
+ eprintln!(" {}", ui::strong("Values with commas:"));
262
260
 
263
261
  for label in &values_with_commas {
264
262
  eprintln!(" {label}");
265
263
  }
266
264
 
267
265
  eprintln!();
268
- eprintln!(" {BOLD}Use yerba move to reorder individual items instead:{RESET}");
266
+ eprintln!(" {}", ui::strong("Use yerba move to reorder individual items instead:"));
269
267
  eprintln!(" yerba move \"{}\"{selector_display} <item> --before/--after <target>", self.file);
270
268
 
271
269
  process::exit(1);
@@ -277,28 +275,26 @@ impl Args {
277
275
  match document.reorder_items(container, by, &desired_order) {
278
276
  Ok(()) => output(&self.file, &document, self.dry_run),
279
277
  Err(error) => {
280
- eprintln!("{RED}Error:{RESET} {}", error);
278
+ eprintln!("{} {}", ui::failure("Error:"), error);
281
279
  process::exit(1);
282
280
  }
283
281
  }
284
282
  }
285
283
 
286
284
  fn resolve_labels(&self, document: &yerba::Document, by: &str, selector: &str, items_selector: &str) -> (Vec<String>, Vec<Vec<String>>, String) {
287
- use super::color::*;
288
-
289
285
  let items = document.get_values(items_selector);
290
286
 
291
287
  if items.is_empty() {
292
288
  if selector.is_empty() {
293
- eprintln!("{RED}Error:{RESET} no sequence found at root level");
289
+ eprintln!("{} no sequence found at root level", ui::failure("Error:"));
294
290
  eprintln!();
295
- eprintln!(" {DIM}If the file is a map, specify which sequence to sort:{RESET}");
291
+ eprintln!(" {}", ui::subtle("If the file is a map, specify which sequence to sort:"));
296
292
  eprintln!(" yerba sort \"{}\" \"<selector>\" --by \"{by}\" --order asc", self.file);
297
293
  eprintln!();
298
294
 
299
295
  super::show_similar_selectors(&self.file, document, "[]");
300
296
  } else {
301
- eprintln!("{RED}Error:{RESET} no sequence found at selector: {selector}");
297
+ eprintln!("{} no sequence found at selector: {selector}", ui::failure("Error:"));
302
298
 
303
299
  super::show_similar_selectors(&self.file, document, selector);
304
300
  }
@@ -316,7 +312,7 @@ impl Args {
316
312
  };
317
313
 
318
314
  if !document.exists(&by_selector) {
319
- eprintln!("{RED}Error:{RESET} field \"{by}\" not found in items");
315
+ eprintln!("{} field \"{by}\" not found in items", ui::failure("Error:"));
320
316
 
321
317
  super::show_similar_selectors(&self.file, document, &by_selector);
322
318
 
@@ -367,17 +363,15 @@ impl Args {
367
363
  }
368
364
 
369
365
  fn format_label_line(&self, index: usize, label: &str, context: &[String]) -> String {
370
- use super::color::*;
371
-
372
366
  if context.is_empty() {
373
- format!("{DIM}[{index}]{RESET} {label}")
367
+ format!("{} {}", ui::subtle(format!("[{}]", index)), label)
374
368
  } else {
375
369
  let context = context.iter().filter(|c| !c.is_empty()).cloned().collect::<Vec<_>>().join(", ");
376
370
 
377
371
  if context.is_empty() {
378
- format!("{DIM}[{index}]{RESET} {label}")
372
+ format!("{} {}", ui::subtle(format!("[{}]", index)), label)
379
373
  } else {
380
- format!("{DIM}[{index}]{RESET} {label} {DIM}{context}{RESET}")
374
+ format!("{} {} {}", ui::subtle(format!("[{}]", index)), label, ui::subtle(context))
381
375
  }
382
376
  }
383
377
  }
@@ -1,3 +1,4 @@
1
+ use super::ui;
1
2
  use std::process;
2
3
  use std::sync::LazyLock;
3
4
 
@@ -41,8 +42,7 @@ impl Args {
41
42
  let document = parse_file(resolved_file);
42
43
 
43
44
  if let Err(error) = document.validate_sort_keys(&self.selector, &key_order) {
44
- use super::color::*;
45
- eprintln!("{RED}Error in {}{RESET}: {}", resolved_file, error);
45
+ eprintln!("{}: {}", ui::failure(format!("Error in {}", resolved_file)), error);
46
46
  has_errors = true;
47
47
  }
48
48
  }
@@ -0,0 +1,157 @@
1
+ use std::io::IsTerminal;
2
+ use std::sync::OnceLock;
3
+
4
+ fn colored() -> bool {
5
+ static COLORED: OnceLock<bool> = OnceLock::new();
6
+
7
+ *COLORED.get_or_init(|| {
8
+ if std::env::var_os("NO_COLOR").is_some() {
9
+ return false;
10
+ }
11
+
12
+ if std::env::var_os("CLICOLOR_FORCE").is_some_and(|value| value != "0") {
13
+ return true;
14
+ }
15
+
16
+ std::io::stderr().is_terminal() || super::is_github_actions()
17
+ })
18
+ }
19
+
20
+ #[derive(Clone, Copy)]
21
+ pub struct Color(&'static str);
22
+
23
+ pub const GREEN: Color = Color("32");
24
+ pub const YELLOW: Color = Color("33");
25
+ pub const RED: Color = Color("31");
26
+ pub const CYAN: Color = Color("36");
27
+
28
+ pub struct Style {
29
+ color: Option<Color>,
30
+ bold: bool,
31
+ dim: bool,
32
+ }
33
+
34
+ impl Style {
35
+ pub const fn plain() -> Self {
36
+ Style {
37
+ color: None,
38
+ bold: false,
39
+ dim: false,
40
+ }
41
+ }
42
+
43
+ pub const fn fg(color: Color) -> Self {
44
+ Style {
45
+ color: Some(color),
46
+ bold: false,
47
+ dim: false,
48
+ }
49
+ }
50
+
51
+ pub const fn bold(mut self) -> Self {
52
+ self.bold = true;
53
+ self
54
+ }
55
+
56
+ pub const fn dim(mut self) -> Self {
57
+ self.dim = true;
58
+ self
59
+ }
60
+
61
+ pub fn paint(&self, text: impl std::fmt::Display) -> String {
62
+ if !colored() {
63
+ return text.to_string();
64
+ }
65
+
66
+ let mut codes: Vec<&str> = Vec::new();
67
+
68
+ if self.bold {
69
+ codes.push("1");
70
+ }
71
+
72
+ if self.dim {
73
+ codes.push("2");
74
+ }
75
+
76
+ if let Some(color) = &self.color {
77
+ codes.push(color.0);
78
+ }
79
+
80
+ if codes.is_empty() {
81
+ return text.to_string();
82
+ }
83
+
84
+ format!("\x1b[{}m{}\x1b[0m", codes.join(";"), text)
85
+ }
86
+ }
87
+
88
+ pub fn success(text: impl std::fmt::Display) -> String {
89
+ Style::fg(GREEN).bold().paint(text)
90
+ }
91
+
92
+ pub fn pending(text: impl std::fmt::Display) -> String {
93
+ Style::fg(YELLOW).bold().paint(text)
94
+ }
95
+
96
+ pub fn failure(text: impl std::fmt::Display) -> String {
97
+ Style::fg(RED).bold().paint(text)
98
+ }
99
+
100
+ pub fn muted(text: impl std::fmt::Display) -> String {
101
+ Style::fg(CYAN).paint(text)
102
+ }
103
+
104
+ pub fn subtle(text: impl std::fmt::Display) -> String {
105
+ Style::plain().dim().paint(text)
106
+ }
107
+
108
+ pub fn strong(text: impl std::fmt::Display) -> String {
109
+ Style::plain().bold().paint(text)
110
+ }
111
+
112
+ pub fn banner() -> String {
113
+ format!("🧉 {} {}", Style::fg(GREEN).bold().paint("yerba"), subtle(format!("v{}", yerba::version())))
114
+ }
115
+
116
+ pub const INDENT: &str = " ";
117
+ pub const STATUS_INDENT: &str = " ";
118
+
119
+ pub mod glyph {
120
+ pub const OK: &str = "✓";
121
+ pub const PENDING: &str = "~";
122
+ pub const FAIL: &str = "✗";
123
+ }
124
+
125
+ pub mod raw {
126
+ fn sequence(code: &'static str) -> &'static str {
127
+ if super::colored() {
128
+ code
129
+ } else {
130
+ ""
131
+ }
132
+ }
133
+
134
+ pub fn green() -> &'static str {
135
+ sequence("\x1b[32m")
136
+ }
137
+
138
+ pub fn yellow() -> &'static str {
139
+ sequence("\x1b[33m")
140
+ }
141
+
142
+ pub fn bold() -> &'static str {
143
+ sequence("\x1b[1m")
144
+ }
145
+
146
+ pub fn dim() -> &'static str {
147
+ sequence("\x1b[2m")
148
+ }
149
+
150
+ pub fn italic() -> &'static str {
151
+ sequence("\x1b[3m")
152
+ }
153
+
154
+ pub fn reset() -> &'static str {
155
+ sequence("\x1b[0m")
156
+ }
157
+ }
@@ -37,7 +37,7 @@ pub struct Args {
37
37
 
38
38
  impl Args {
39
39
  pub fn run(self) {
40
- use super::color::*;
40
+ use super::ui;
41
41
 
42
42
  let selector = self.selector.as_deref().unwrap_or("");
43
43
  let by = self.by.as_deref().unwrap_or(".");
@@ -50,20 +50,20 @@ impl Args {
50
50
  let noun = if duplicates.len() == 1 { "duplicate" } else { "duplicates" };
51
51
 
52
52
  if duplicates.is_empty() {
53
- eprintln!("{GREEN}No duplicates found{RESET} in {}", resolved_file);
53
+ eprintln!("{} in {}", ui::success("No duplicates found"), resolved_file);
54
54
  } else if self.remove {
55
- eprintln!("{YELLOW}Removed {} {noun}{RESET} from {}", duplicates.len(), resolved_file);
55
+ eprintln!("{} from {}", ui::pending(format!("Removed {} {noun}", duplicates.len())), resolved_file);
56
56
 
57
57
  for duplicate in &duplicates {
58
- eprintln!(" {DIM}line {}: {} == {}{RESET}", duplicate.line, by, duplicate.value);
58
+ eprintln!(" {}", ui::subtle(format!("line {}: {} == {}", duplicate.line, by, duplicate.value)));
59
59
  }
60
60
 
61
61
  output(&resolved_file, &document, self.dry_run);
62
62
  } else {
63
- eprintln!("{RED}Found {} {noun}{RESET} in {}", duplicates.len(), resolved_file);
63
+ eprintln!("{} in {}", ui::failure(format!("Found {} {noun}", duplicates.len())), resolved_file);
64
64
 
65
65
  for duplicate in &duplicates {
66
- eprintln!(" {DIM}line {}: {} == {}{RESET}", duplicate.line, by, duplicate.value);
66
+ eprintln!(" {}", ui::subtle(format!("line {}: {} == {}", duplicate.line, by, duplicate.value)));
67
67
  }
68
68
 
69
69
  process::exit(1);
@@ -71,7 +71,7 @@ impl Args {
71
71
  }
72
72
 
73
73
  Err(error) => {
74
- eprintln!("{RED}Error:{RESET} {}", error);
74
+ eprintln!("{} {}", ui::failure("Error:"), error);
75
75
  process::exit(1);
76
76
  }
77
77
  }
@@ -1,8 +1,18 @@
1
- use super::color::*;
1
+ use super::ui;
2
2
 
3
3
  pub fn run() {
4
- println!("🧉 {BOLD}yerba{RESET} {DIM}v{}{RESET}", yerba::version());
4
+ println!("{}", ui::banner());
5
5
  println!(
6
- " {BOLD}Y{RESET}{DIM}AML{RESET} {BOLD}E{RESET}{DIM}diting and{RESET} {BOLD}R{RESET}{DIM}efactoring with{RESET} {BOLD}B{RESET}{DIM}etter{RESET} {BOLD}A{RESET}{DIM}ccuracy{RESET}"
6
+ " {}{} {}{} {}{} {}{} {}{}",
7
+ ui::strong("Y"),
8
+ ui::subtle("AML"),
9
+ ui::strong("E"),
10
+ ui::subtle("diting and"),
11
+ ui::strong("R"),
12
+ ui::subtle("efactoring with"),
13
+ ui::strong("B"),
14
+ ui::subtle("etter"),
15
+ ui::strong("A"),
16
+ ui::subtle("ccuracy")
7
17
  );
8
18
  }
@@ -570,6 +570,10 @@ impl Document {
570
570
  let is_block_value = value.contains('\n') || value.starts_with("- ");
571
571
 
572
572
  if !is_block_value {
573
+ if !crate::syntax::is_valid_inline_value(value) {
574
+ return format!("{}: {}", key, crate::syntax::quote_if_needed(value));
575
+ }
576
+
573
577
  return format!("{}: {}", key, value);
574
578
  }
575
579
 
@@ -1,13 +1,17 @@
1
1
  mod condition;
2
- pub use condition::{validate_condition, validate_item_condition};
3
2
  mod delete;
4
3
  mod get;
5
4
  mod insert;
6
- mod schema;
7
5
  mod set;
8
6
  mod sort;
9
- pub mod style;
10
7
  mod unique;
8
+
9
+ #[cfg(feature = "schema")]
10
+ mod schema;
11
+
12
+ pub mod style;
13
+
14
+ pub use condition::{validate_condition, validate_item_condition};
11
15
  pub use unique::DuplicateInfo;
12
16
 
13
17
  use crate::syntax::YerbaValueType;
@@ -1,5 +1,13 @@
1
1
  use super::*;
2
2
 
3
+ fn scalar_replacement_text(value: &str, kind: SyntaxKind) -> String {
4
+ if kind == SyntaxKind::PLAIN_SCALAR && !crate::syntax::is_inline_scalar_safe(value) {
5
+ return format_scalar_value(value, SyntaxKind::DOUBLE_QUOTED_SCALAR);
6
+ }
7
+
8
+ format_scalar_value(value, kind)
9
+ }
10
+
3
11
  fn holds_collection(node: &SyntaxNode) -> bool {
4
12
  node.descendants().any(|descendant| {
5
13
  matches!(
@@ -84,7 +92,7 @@ impl Document {
84
92
 
85
93
  let scalar_token = find_scalar_token(&current_node).ok_or_else(|| YerbaError::SelectorNotFound(dot_path.to_string()))?;
86
94
 
87
- let new_text = format_scalar_value(value, scalar_token.kind());
95
+ let new_text = scalar_replacement_text(value, scalar_token.kind());
88
96
 
89
97
  self.replace_token(&scalar_token, &new_text)
90
98
  }
@@ -107,7 +115,7 @@ impl Document {
107
115
  edits.push((span.range, replacement_text(&span, value)));
108
116
  }
109
117
  } else if let Some(scalar_token) = find_scalar_token(&node) {
110
- edits.push((scalar_token.text_range(), format_scalar_value(value, scalar_token.kind())));
118
+ edits.push((scalar_token.text_range(), scalar_replacement_text(value, scalar_token.kind())));
111
119
  }
112
120
  }
113
121
 
data/rust/src/error.rs CHANGED
@@ -10,6 +10,7 @@ pub enum YerbaError {
10
10
  IndexOutOfBounds(usize, usize),
11
11
  UnknownKeys(Vec<String>),
12
12
  DuplicateValues(Vec<crate::DuplicateInfo>),
13
+ #[cfg(feature = "schema")]
13
14
  SchemaValidation(Vec<crate::schema::ValidationError>),
14
15
  DuplicateKey {
15
16
  key: String,
@@ -78,6 +79,7 @@ impl std::fmt::Display for YerbaError {
78
79
  write!(f, "index {} out of bounds (length {})", index, length)
79
80
  }
80
81
 
82
+ #[cfg(feature = "schema")]
81
83
  YerbaError::SchemaValidation(errors) => {
82
84
  let details: Vec<String> = errors.iter().map(|error| error.to_string()).collect();
83
85
 
@@ -137,6 +139,7 @@ impl GitHubAnnotations for YerbaError {
137
139
  })
138
140
  .collect(),
139
141
 
142
+ #[cfg(feature = "schema")]
140
143
  YerbaError::SchemaValidation(errors) => errors
141
144
  .iter()
142
145
  .map(|error| GitHubAnnotation {
data/rust/src/ffi.rs CHANGED
@@ -746,6 +746,7 @@ pub unsafe extern "C" fn yerba_document_blank_lines(document: *mut Document, pat
746
746
  }
747
747
 
748
748
  /// Caller must free with yerba_string_free.
749
+ #[cfg(feature = "schema")]
749
750
  #[no_mangle]
750
751
  pub unsafe extern "C" fn yerba_document_validate_schema(document: *const Document, schema_json: *const c_char, selector: *const c_char) -> *mut c_char {
751
752
  let document = &*document;
@@ -784,6 +785,7 @@ pub unsafe extern "C" fn yerba_document_validate_schema(document: *const Documen
784
785
  }
785
786
 
786
787
  /// Caller must free with yerba_string_free.
788
+ #[cfg(feature = "cli")]
787
789
  #[no_mangle]
788
790
  pub unsafe extern "C" fn yerba_yerbafile_find(directory: *const c_char) -> *mut c_char {
789
791
  let start = if directory.is_null() {
@@ -803,6 +805,7 @@ pub unsafe extern "C" fn yerba_yerbafile_find(directory: *const c_char) -> *mut
803
805
  }
804
806
  }
805
807
 
808
+ #[cfg(feature = "cli")]
806
809
  #[no_mangle]
807
810
  pub unsafe extern "C" fn yerba_document_apply_yerbafile(document: *mut Document, file_path: *const c_char, yerbafile_path: *const c_char) -> YerbaResult {
808
811
  let document = &mut *document;
@@ -924,6 +927,7 @@ fn located_nodes_to_list(nodes: &[crate::LocatedNode]) -> YerbaTypedList {
924
927
  }
925
928
  }
926
929
 
930
+ #[cfg(feature = "glob")]
927
931
  #[no_mangle]
928
932
  pub unsafe extern "C" fn yerba_glob_get(glob_pattern: *const c_char, path: *const c_char) -> YerbaTypedList {
929
933
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
@@ -940,6 +944,7 @@ pub unsafe extern "C" fn yerba_document_get_all(document: *const Document, path:
940
944
  located_nodes_to_list(&document.get_all_located(selector_string))
941
945
  }
942
946
 
947
+ #[cfg(feature = "glob")]
943
948
  #[no_mangle]
944
949
  pub unsafe extern "C" fn yerba_glob_find(glob_pattern: *const c_char, path: *const c_char, condition: *const c_char, select: *const c_char) -> YerbaTypedList {
945
950
  let pattern = CStr::from_ptr(glob_pattern).to_str().unwrap_or("");
data/rust/src/lib.rs CHANGED
@@ -4,10 +4,12 @@ pub mod error;
4
4
  pub mod ffi;
5
5
  pub mod json;
6
6
  mod quote_style;
7
+ #[cfg(feature = "schema")]
7
8
  pub mod schema;
8
9
  pub mod selector;
9
10
  mod syntax;
10
11
  mod yaml_writer;
12
+ #[cfg(feature = "cli")]
11
13
  pub mod yerbafile;
12
14
 
13
15
  pub use document::style::StyleEnforcement;
@@ -17,8 +19,12 @@ pub use document::{
17
19
  pub use error::YerbaError;
18
20
  pub use quote_style::{KeyStyle, QuoteStyle};
19
21
  pub use selector::Selector;
20
- pub use syntax::{detect_yaml_type, ScalarValue, YerbaValueType};
22
+ pub use syntax::{
23
+ detect_yaml_type, is_flow_collection, is_inline_scalar_safe, is_plain_safe, is_plain_safe_in_flow, is_quoted_scalar, is_raw_yaml_text, is_valid_inline_value,
24
+ needs_quoting, needs_quoting_in_flow, quote_if_needed, ScalarValue, YerbaValueType,
25
+ };
21
26
  pub use yaml_writer::json_to_yaml_text;
27
+ #[cfg(feature = "cli")]
22
28
  pub use yerbafile::Yerbafile;
23
29
 
24
30
  pub fn version() -> &'static str {
@@ -33,6 +39,7 @@ pub fn parse_file(path: impl AsRef<std::path::Path>) -> Result<Document, YerbaEr
33
39
  Document::parse_file(path)
34
40
  }
35
41
 
42
+ #[cfg(feature = "glob")]
36
43
  pub fn glob_get(pattern: &str, selector: &str) -> Vec<document::LocatedNode> {
37
44
  use rayon::prelude::*;
38
45
 
@@ -55,6 +62,7 @@ pub fn glob_get(pattern: &str, selector: &str) -> Vec<document::LocatedNode> {
55
62
  .collect()
56
63
  }
57
64
 
65
+ #[cfg(feature = "glob")]
58
66
  pub fn glob_find(pattern: &str, selector: &str, condition: Option<&str>, select: Option<&str>) -> Result<Vec<serde_json::Value>, YerbaError> {
59
67
  use rayon::prelude::*;
60
68