yerba 0.8.0-arm-linux-gnu → 0.9.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 +170 -19
- data/exe/arm-linux-gnu/yerba +0 -0
- data/ext/yerba/include/yerba.h +7 -0
- data/ext/yerba/yerba.c +54 -5
- 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/formatting.rb +9 -13
- data/lib/yerba/map.rb +11 -8
- data/lib/yerba/sequence.rb +2 -7
- data/lib/yerba/version.rb +1 -1
- data/rust/Cargo.lock +2 -342
- data/rust/Cargo.toml +15 -6
- data/rust/src/commands/blank_lines.rs +23 -3
- data/rust/src/commands/directives.rs +4 -4
- data/rust/src/commands/get.rs +7 -10
- data/rust/src/commands/init.rs +10 -4
- data/rust/src/commands/insert.rs +18 -12
- data/rust/src/commands/location.rs +2 -2
- data/rust/src/commands/mate.rs +7 -7
- data/rust/src/commands/mod.rs +118 -90
- data/rust/src/commands/move_key.rs +9 -6
- data/rust/src/commands/quote_style.rs +4 -5
- data/rust/src/commands/schema.rs +6 -6
- data/rust/src/commands/selectors.rs +2 -2
- data/rust/src/commands/set.rs +18 -7
- data/rust/src/commands/sort.rs +36 -42
- data/rust/src/commands/sort_keys.rs +2 -2
- data/rust/src/commands/ui.rs +156 -0
- data/rust/src/commands/unique.rs +7 -7
- data/rust/src/commands/version.rs +13 -3
- data/rust/src/document/insert.rs +25 -9
- data/rust/src/document/mod.rs +7 -3
- data/rust/src/document/set.rs +115 -33
- data/rust/src/document/style.rs +131 -11
- data/rust/src/error.rs +27 -0
- data/rust/src/ffi.rs +55 -12
- data/rust/src/lib.rs +12 -2
- data/rust/src/quote_style.rs +12 -11
- data/rust/src/syntax.rs +285 -11
- data/rust/src/validation.rs +30 -0
- data/rust/src/yaml_writer.rs +9 -21
- data/rust/src/yerbafile.rs +76 -4
- metadata +4 -2
data/rust/src/commands/insert.rs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use super::ui;
|
|
1
2
|
use std::sync::LazyLock;
|
|
2
3
|
|
|
3
4
|
use indoc::indoc;
|
|
@@ -7,13 +8,13 @@ use super::{output, parse_file, resolve_files, run_op};
|
|
|
7
8
|
|
|
8
9
|
static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
|
|
9
10
|
colorize_examples(indoc! {r#"
|
|
10
|
-
yerba insert config.yml "database.ssl" true
|
|
11
|
-
yerba insert config.yml "database.ssl" true --after "host"
|
|
12
|
-
yerba insert config.yml "database.ssl" true --before "port"
|
|
11
|
+
yerba insert config.yml "database.ssl" true --plain
|
|
12
|
+
yerba insert config.yml "database.ssl" true --plain --after "host"
|
|
13
|
+
yerba insert config.yml "database.ssl" true --plain --before "port"
|
|
13
14
|
yerba insert config.yml "tags" "yaml"
|
|
14
15
|
yerba insert config.yml "tags" "yaml" --at 0
|
|
15
16
|
yerba insert config.yml "tags" "yaml" --after "ruby"
|
|
16
|
-
yerba insert speakers.yml "" "name: Bob" --after ".name == Alice"
|
|
17
|
+
yerba insert speakers.yml "" "name: Bob" --plain --after ".name == Alice"
|
|
17
18
|
yerba insert videos.yml "[0].speakers" "Diana" --before ".name == Charlie"
|
|
18
19
|
yerba insert videos.yml "" --from "new_talk.yml" --after ".id == first-talk"
|
|
19
20
|
"#})
|
|
@@ -28,6 +29,7 @@ static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
|
|
|
28
29
|
pub struct Args {
|
|
29
30
|
file: String,
|
|
30
31
|
selector: String,
|
|
32
|
+
#[arg(allow_hyphen_values = true)]
|
|
31
33
|
value: Option<String>,
|
|
32
34
|
#[arg(long, help = "Read value from a file (use - for stdin)")]
|
|
33
35
|
from: Option<String>,
|
|
@@ -37,6 +39,8 @@ pub struct Args {
|
|
|
37
39
|
after: Option<String>,
|
|
38
40
|
#[arg(long)]
|
|
39
41
|
at: Option<usize>,
|
|
42
|
+
#[arg(long, help = "Write the value as raw YAML, for literals like null, true or 42 and for map or sequence fragments")]
|
|
43
|
+
plain: bool,
|
|
40
44
|
#[arg(long)]
|
|
41
45
|
dry_run: bool,
|
|
42
46
|
}
|
|
@@ -49,8 +53,8 @@ impl Args {
|
|
|
49
53
|
let mut buffer = String::new();
|
|
50
54
|
|
|
51
55
|
std::io::stdin().read_to_string(&mut buffer).unwrap_or_else(|error| {
|
|
52
|
-
use super::
|
|
53
|
-
eprintln!("{
|
|
56
|
+
use super::ui;
|
|
57
|
+
eprintln!("{} reading stdin: {}", ui::failure("Error:"), error);
|
|
54
58
|
|
|
55
59
|
std::process::exit(1);
|
|
56
60
|
});
|
|
@@ -59,18 +63,20 @@ impl Args {
|
|
|
59
63
|
} else {
|
|
60
64
|
std::fs::read_to_string(&from_path)
|
|
61
65
|
.unwrap_or_else(|error| {
|
|
62
|
-
|
|
63
|
-
eprintln!("{RED}Error:{RESET} reading {}: {}", from_path, error);
|
|
66
|
+
eprintln!("{} reading {}: {}", ui::failure("Error:"), from_path, error);
|
|
64
67
|
std::process::exit(1);
|
|
65
68
|
})
|
|
66
69
|
.trim()
|
|
67
70
|
.to_string()
|
|
68
71
|
}
|
|
69
|
-
} else if let Some(
|
|
70
|
-
|
|
72
|
+
} else if let Some(value) = self.value {
|
|
73
|
+
if self.plain {
|
|
74
|
+
value
|
|
75
|
+
} else {
|
|
76
|
+
yerba::quote_scalar(&value)
|
|
77
|
+
}
|
|
71
78
|
} else {
|
|
72
|
-
|
|
73
|
-
eprintln!("{RED}Error:{RESET} either a value argument or --from is required");
|
|
79
|
+
eprintln!("{} either a value argument or --from is required", ui::failure("Error:"));
|
|
74
80
|
|
|
75
81
|
std::process::exit(1);
|
|
76
82
|
};
|
|
@@ -28,13 +28,13 @@ pub struct Args {
|
|
|
28
28
|
|
|
29
29
|
impl Args {
|
|
30
30
|
pub fn run(self) {
|
|
31
|
-
use super::
|
|
31
|
+
use super::ui;
|
|
32
32
|
|
|
33
33
|
let document = parse_file(&self.file);
|
|
34
34
|
let info = document.get_node_info(&self.selector);
|
|
35
35
|
|
|
36
36
|
if info.location.start_line == 0 && info.location.end_line == 0 {
|
|
37
|
-
eprintln!("{
|
|
37
|
+
eprintln!("{} selector \"{}\" not found in {}", ui::failure("Error:"), self.selector, self.file);
|
|
38
38
|
|
|
39
39
|
super::show_similar_selectors(&self.file, &document, &self.selector);
|
|
40
40
|
process::exit(1);
|
data/rust/src/commands/mate.rs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
use super::
|
|
1
|
+
use super::ui;
|
|
2
2
|
|
|
3
3
|
pub fn run() {
|
|
4
|
-
let g =
|
|
5
|
-
let b =
|
|
6
|
-
let d =
|
|
7
|
-
let i =
|
|
8
|
-
let y =
|
|
9
|
-
let r =
|
|
4
|
+
let g = ui::raw::green();
|
|
5
|
+
let b = ui::raw::bold();
|
|
6
|
+
let d = ui::raw::dim();
|
|
7
|
+
let i = ui::raw::italic();
|
|
8
|
+
let y = ui::raw::yellow();
|
|
9
|
+
let r = ui::raw::reset();
|
|
10
10
|
let hr = format!(" {d}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}\u{2500}{r}");
|
|
11
11
|
|
|
12
12
|
println!();
|
data/rust/src/commands/mod.rs
CHANGED
|
@@ -18,6 +18,7 @@ pub mod selectors;
|
|
|
18
18
|
pub mod set;
|
|
19
19
|
pub mod sort;
|
|
20
20
|
pub mod sort_keys;
|
|
21
|
+
pub mod ui;
|
|
21
22
|
pub mod unique;
|
|
22
23
|
pub mod version;
|
|
23
24
|
|
|
@@ -30,56 +31,15 @@ pub(crate) fn is_github_actions() -> bool {
|
|
|
30
31
|
std::env::var("GITHUB_ACTIONS").is_ok()
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
pub(crate)
|
|
34
|
-
|
|
35
|
-
pub const RED: &str = "\x1b[31m";
|
|
36
|
-
pub const YELLOW: &str = "\x1b[33m";
|
|
37
|
-
pub const DIM: &str = "\x1b[2m";
|
|
38
|
-
pub const BOLD: &str = "\x1b[1m";
|
|
39
|
-
pub const RESET: &str = "\x1b[0m";
|
|
34
|
+
pub(crate) fn pluralize(count: usize, singular: &str, plural: &str) -> String {
|
|
35
|
+
format!("{} {}", count, if count == 1 { singular } else { plural })
|
|
40
36
|
}
|
|
41
37
|
|
|
42
|
-
// Compile-time ANSI macros for use in concat!() / clap attributes (used in main.rs)
|
|
43
|
-
#[allow(unused_macros)]
|
|
44
|
-
macro_rules! h {
|
|
45
|
-
() => {
|
|
46
|
-
"\x1b[1;32m"
|
|
47
|
-
};
|
|
48
|
-
} // header (bold green)
|
|
49
|
-
#[allow(unused_macros)]
|
|
50
|
-
macro_rules! b {
|
|
51
|
-
() => {
|
|
52
|
-
"\x1b[1m"
|
|
53
|
-
};
|
|
54
|
-
} // bold
|
|
55
|
-
#[allow(unused_macros)]
|
|
56
|
-
macro_rules! c {
|
|
57
|
-
() => {
|
|
58
|
-
"\x1b[36m"
|
|
59
|
-
};
|
|
60
|
-
} // cyan
|
|
61
|
-
#[allow(unused_macros)]
|
|
62
|
-
macro_rules! d {
|
|
63
|
-
() => {
|
|
64
|
-
"\x1b[2m"
|
|
65
|
-
};
|
|
66
|
-
} // dim
|
|
67
|
-
#[allow(unused_macros)]
|
|
68
|
-
macro_rules! r {
|
|
69
|
-
() => {
|
|
70
|
-
"\x1b[0m"
|
|
71
|
-
};
|
|
72
|
-
} // reset
|
|
73
|
-
#[allow(unused_imports)]
|
|
74
|
-
pub(crate) use {b, c, d, h, r};
|
|
75
|
-
|
|
76
38
|
pub(crate) fn colorize_examples(input: &str) -> String {
|
|
77
39
|
colorize_help(&format!("Examples:\n{}", input.trim()))
|
|
78
40
|
}
|
|
79
41
|
|
|
80
42
|
pub(crate) fn colorize_help(input: &str) -> String {
|
|
81
|
-
use color::*;
|
|
82
|
-
|
|
83
43
|
let mut output = String::new();
|
|
84
44
|
|
|
85
45
|
for line in input.lines() {
|
|
@@ -91,7 +51,7 @@ pub(crate) fn colorize_help(input: &str) -> String {
|
|
|
91
51
|
}
|
|
92
52
|
|
|
93
53
|
if trimmed.ends_with(':') && !trimmed.contains(' ') {
|
|
94
|
-
output.push_str(&format!("{
|
|
54
|
+
output.push_str(&format!("{}\n", ui::success(trimmed)));
|
|
95
55
|
continue;
|
|
96
56
|
}
|
|
97
57
|
|
|
@@ -100,11 +60,11 @@ pub(crate) fn colorize_help(input: &str) -> String {
|
|
|
100
60
|
|
|
101
61
|
match (parts.next(), parts.next(), parts.next()) {
|
|
102
62
|
(Some(cmd), Some(sub), Some(rest)) => {
|
|
103
|
-
output.push_str(&format!(" {
|
|
63
|
+
output.push_str(&format!(" {} {} {}\n", ui::strong(cmd), ui::muted(sub), rest));
|
|
104
64
|
}
|
|
105
65
|
|
|
106
66
|
(Some(cmd), Some(sub), None) => {
|
|
107
|
-
output.push_str(&format!(" {
|
|
67
|
+
output.push_str(&format!(" {} {}\n", ui::strong(cmd), ui::muted(sub)));
|
|
108
68
|
}
|
|
109
69
|
|
|
110
70
|
_ => {
|
|
@@ -134,9 +94,14 @@ pub(crate) fn colorize_help(input: &str) -> String {
|
|
|
134
94
|
}
|
|
135
95
|
|
|
136
96
|
if columns.len() == 3 {
|
|
137
|
-
output.push_str(&format!(
|
|
97
|
+
output.push_str(&format!(
|
|
98
|
+
" {} {:<21} {}\n",
|
|
99
|
+
ui::muted(format!("{:<20}", columns[0])),
|
|
100
|
+
columns[1],
|
|
101
|
+
ui::subtle(columns[2])
|
|
102
|
+
));
|
|
138
103
|
} else if columns.len() == 2 {
|
|
139
|
-
output.push_str(&format!("
|
|
104
|
+
output.push_str(&format!(" {} {}\n", ui::muted(format!("{:<20}", columns[0])), columns[1]));
|
|
140
105
|
} else {
|
|
141
106
|
output.push_str(&format!(" {trimmed}\n"));
|
|
142
107
|
}
|
|
@@ -204,19 +169,34 @@ impl Command {
|
|
|
204
169
|
}
|
|
205
170
|
|
|
206
171
|
pub(crate) fn run_yerbafile(write: bool, files: Vec<String>) {
|
|
207
|
-
use color::*;
|
|
208
|
-
|
|
209
172
|
let yerbafile_path = yerba::Yerbafile::find().unwrap_or_else(|| {
|
|
210
|
-
eprintln!(
|
|
173
|
+
eprintln!(
|
|
174
|
+
"{} No Yerbafile found. Run {} to create one.",
|
|
175
|
+
ui::failure(ui::glyph::FAIL),
|
|
176
|
+
ui::strong("yerba init")
|
|
177
|
+
);
|
|
211
178
|
process::exit(1);
|
|
212
179
|
});
|
|
213
180
|
|
|
214
181
|
let yerbafile = yerba::Yerbafile::load(&yerbafile_path).unwrap_or_else(|error| {
|
|
215
|
-
eprintln!(
|
|
182
|
+
eprintln!(
|
|
183
|
+
"{} {}",
|
|
184
|
+
ui::failure(ui::glyph::FAIL),
|
|
185
|
+
ui::strong(format!("Could not read {}", yerbafile_path.display()))
|
|
186
|
+
);
|
|
187
|
+
eprintln!(" {}", error);
|
|
216
188
|
process::exit(1);
|
|
217
189
|
});
|
|
218
190
|
|
|
219
|
-
eprintln!("
|
|
191
|
+
eprintln!("\n{}\n", ui::banner());
|
|
192
|
+
|
|
193
|
+
eprintln!(
|
|
194
|
+
"{} {}\n",
|
|
195
|
+
ui::strong("Using Yerbafile rules"),
|
|
196
|
+
ui::subtle(format!("(from {})", yerbafile_path.display()))
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
let started = std::time::Instant::now();
|
|
220
200
|
|
|
221
201
|
let results = if files.is_empty() {
|
|
222
202
|
yerbafile.apply(write)
|
|
@@ -224,6 +204,8 @@ pub(crate) fn run_yerbafile(write: bool, files: Vec<String>) {
|
|
|
224
204
|
files.iter().flat_map(|file| yerbafile.apply_file(file, write)).collect()
|
|
225
205
|
};
|
|
226
206
|
|
|
207
|
+
let elapsed = started.elapsed();
|
|
208
|
+
|
|
227
209
|
let mut has_changes = false;
|
|
228
210
|
let mut has_errors = false;
|
|
229
211
|
|
|
@@ -231,7 +213,8 @@ pub(crate) fn run_yerbafile(write: bool, files: Vec<String>) {
|
|
|
231
213
|
|
|
232
214
|
for result in &results {
|
|
233
215
|
if let Some(error) = &result.error {
|
|
234
|
-
eprintln!(" {
|
|
216
|
+
eprintln!(" {} {}", ui::failure(ui::glyph::FAIL), ui::strong(&result.file));
|
|
217
|
+
eprintln!(" {}", ui::muted(error));
|
|
235
218
|
|
|
236
219
|
if github {
|
|
237
220
|
use yerba::error::GitHubAnnotations;
|
|
@@ -244,12 +227,15 @@ pub(crate) fn run_yerbafile(write: bool, files: Vec<String>) {
|
|
|
244
227
|
has_errors = true;
|
|
245
228
|
} else if result.changed {
|
|
246
229
|
if write {
|
|
247
|
-
eprintln!(" {
|
|
230
|
+
eprintln!(" {} {}", ui::success(ui::glyph::OK), result.file);
|
|
248
231
|
} else {
|
|
249
|
-
eprintln!(" {
|
|
232
|
+
eprintln!(" {} {}", ui::pending(ui::glyph::PENDING), result.file);
|
|
250
233
|
|
|
251
234
|
if github {
|
|
252
|
-
eprintln!(
|
|
235
|
+
eprintln!(
|
|
236
|
+
"::error file={}::File does not match Yerbafile rules. Run `yerba apply` to update it.",
|
|
237
|
+
result.file
|
|
238
|
+
);
|
|
253
239
|
}
|
|
254
240
|
}
|
|
255
241
|
|
|
@@ -257,19 +243,70 @@ pub(crate) fn run_yerbafile(write: bool, files: Vec<String>) {
|
|
|
257
243
|
}
|
|
258
244
|
}
|
|
259
245
|
|
|
260
|
-
|
|
261
|
-
|
|
246
|
+
let changed = results.iter().filter(|result| result.error.is_none() && result.changed).count();
|
|
247
|
+
let seen: std::collections::HashSet<&String> = results.iter().map(|result| &result.file).collect();
|
|
248
|
+
let rules = yerbafile.rules.len() + usize::from(!yerbafile.pipeline.is_empty());
|
|
249
|
+
let steps = yerbafile.pipeline.len() + yerbafile.rules.iter().map(|rule| rule.pipeline.len()).sum::<usize>();
|
|
250
|
+
|
|
251
|
+
if seen.is_empty() {
|
|
252
|
+
eprintln!(
|
|
253
|
+
"{} {} {}",
|
|
254
|
+
ui::pending(ui::glyph::PENDING),
|
|
255
|
+
ui::pending("No files matched."),
|
|
256
|
+
ui::subtle("Check the `files:` patterns in your Yerbafile.")
|
|
257
|
+
);
|
|
258
|
+
} else if !has_changes && !has_errors {
|
|
259
|
+
eprintln!("{} {}", ui::success(ui::glyph::OK), ui::success("Everything's up to date."));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if write && has_changes {
|
|
263
|
+
eprintln!(
|
|
264
|
+
"\n{} {}",
|
|
265
|
+
ui::success(ui::glyph::OK),
|
|
266
|
+
ui::success(format!("Freshly brewed {}.", pluralize(changed, "file", "files")))
|
|
267
|
+
);
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
if !write && has_changes {
|
|
265
|
-
|
|
271
|
+
let command = if files.is_empty() {
|
|
272
|
+
"yerba apply".to_string()
|
|
273
|
+
} else {
|
|
274
|
+
format!("yerba apply {}", files.join(" "))
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
eprintln!(
|
|
278
|
+
"\n{} {} {}",
|
|
279
|
+
ui::pending(ui::glyph::PENDING),
|
|
280
|
+
ui::pending(format!("{} out of date.", pluralize(changed, "file", "files"))),
|
|
281
|
+
ui::subtle(format!("Run {} to update {}.", command, if changed == 1 { "it" } else { "them" }))
|
|
282
|
+
);
|
|
266
283
|
}
|
|
267
284
|
|
|
268
|
-
|
|
285
|
+
eprintln!(
|
|
286
|
+
"{}{}",
|
|
287
|
+
ui::STATUS_INDENT,
|
|
288
|
+
ui::subtle(format!(
|
|
289
|
+
"{} · {} · {} · {}",
|
|
290
|
+
pluralize(seen.len(), "file", "files"),
|
|
291
|
+
pluralize(rules, "rule", "rules"),
|
|
292
|
+
pluralize(steps, "step", "steps"),
|
|
293
|
+
format_duration(elapsed)
|
|
294
|
+
))
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
if has_errors || (!write && has_changes) {
|
|
269
298
|
process::exit(1);
|
|
270
299
|
}
|
|
271
300
|
}
|
|
272
301
|
|
|
302
|
+
fn format_duration(elapsed: std::time::Duration) -> String {
|
|
303
|
+
if elapsed.as_secs() == 0 {
|
|
304
|
+
format!("{}ms", elapsed.as_millis())
|
|
305
|
+
} else {
|
|
306
|
+
format!("{:.1}s", elapsed.as_secs_f64())
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
273
310
|
pub(crate) fn resolve_move_indexes(
|
|
274
311
|
document: &yerba::Document,
|
|
275
312
|
path: &str,
|
|
@@ -279,10 +316,8 @@ pub(crate) fn resolve_move_indexes(
|
|
|
279
316
|
to: Option<usize>,
|
|
280
317
|
resolve: impl Fn(&yerba::Document, &str, &str) -> Result<usize, yerba::YerbaError>,
|
|
281
318
|
) -> (usize, usize) {
|
|
282
|
-
use color::*;
|
|
283
|
-
|
|
284
319
|
let from_index = resolve(document, path, item).unwrap_or_else(|error| {
|
|
285
|
-
eprintln!("{
|
|
320
|
+
eprintln!("{} {}", ui::failure("Error:"), error);
|
|
286
321
|
process::exit(1);
|
|
287
322
|
});
|
|
288
323
|
|
|
@@ -290,7 +325,7 @@ pub(crate) fn resolve_move_indexes(
|
|
|
290
325
|
index
|
|
291
326
|
} else if let Some(target) = &before {
|
|
292
327
|
let target_index = resolve(document, path, target).unwrap_or_else(|error| {
|
|
293
|
-
eprintln!("{
|
|
328
|
+
eprintln!("{} {}", ui::failure("Error:"), error);
|
|
294
329
|
process::exit(1);
|
|
295
330
|
});
|
|
296
331
|
|
|
@@ -301,7 +336,7 @@ pub(crate) fn resolve_move_indexes(
|
|
|
301
336
|
}
|
|
302
337
|
} else if let Some(target) = &after {
|
|
303
338
|
let target_index = resolve(document, path, target).unwrap_or_else(|error| {
|
|
304
|
-
eprintln!("{
|
|
339
|
+
eprintln!("{} {}", ui::failure("Error:"), error);
|
|
305
340
|
process::exit(1);
|
|
306
341
|
});
|
|
307
342
|
|
|
@@ -311,7 +346,7 @@ pub(crate) fn resolve_move_indexes(
|
|
|
311
346
|
target_index + 1
|
|
312
347
|
}
|
|
313
348
|
} else {
|
|
314
|
-
eprintln!("{
|
|
349
|
+
eprintln!("{} specify --before, --after, or --to", ui::failure("Error:"));
|
|
315
350
|
process::exit(1);
|
|
316
351
|
};
|
|
317
352
|
|
|
@@ -319,12 +354,10 @@ pub(crate) fn resolve_move_indexes(
|
|
|
319
354
|
}
|
|
320
355
|
|
|
321
356
|
pub(crate) fn resolve_files(pattern: &str) -> Vec<String> {
|
|
322
|
-
use color::*;
|
|
323
|
-
|
|
324
357
|
if pattern.contains('*') || pattern.contains('?') || pattern.contains('[') {
|
|
325
358
|
let paths: Vec<String> = glob::glob(pattern)
|
|
326
359
|
.unwrap_or_else(|error| {
|
|
327
|
-
eprintln!("{
|
|
360
|
+
eprintln!("{} invalid glob pattern '{}': {}", ui::failure("Error:"), pattern, error);
|
|
328
361
|
process::exit(1);
|
|
329
362
|
})
|
|
330
363
|
.filter_map(|entry| entry.ok())
|
|
@@ -332,7 +365,7 @@ pub(crate) fn resolve_files(pattern: &str) -> Vec<String> {
|
|
|
332
365
|
.collect();
|
|
333
366
|
|
|
334
367
|
if paths.is_empty() {
|
|
335
|
-
eprintln!("{
|
|
368
|
+
eprintln!("{} no files matched pattern: {}", ui::failure("Error:"), pattern);
|
|
336
369
|
process::exit(1);
|
|
337
370
|
}
|
|
338
371
|
|
|
@@ -343,18 +376,16 @@ pub(crate) fn resolve_files(pattern: &str) -> Vec<String> {
|
|
|
343
376
|
}
|
|
344
377
|
|
|
345
378
|
pub(crate) fn parse_file(file: &str) -> yerba::Document {
|
|
346
|
-
use color::*;
|
|
347
|
-
|
|
348
379
|
yerba::parse_file(file).unwrap_or_else(|error| {
|
|
349
380
|
match &error {
|
|
350
381
|
yerba::YerbaError::IoError(io_error) => match io_error.kind() {
|
|
351
|
-
std::io::ErrorKind::NotFound => eprintln!("{
|
|
382
|
+
std::io::ErrorKind::NotFound => eprintln!("{} file not found: {}", ui::failure("Error:"), file),
|
|
352
383
|
std::io::ErrorKind::PermissionDenied => {
|
|
353
|
-
eprintln!("{
|
|
384
|
+
eprintln!("{} permission denied: {}", ui::failure("Error:"), file)
|
|
354
385
|
}
|
|
355
|
-
_ => eprintln!("{
|
|
386
|
+
_ => eprintln!("{} reading {}: {}", ui::failure("Error:"), file, io_error),
|
|
356
387
|
},
|
|
357
|
-
_ => eprintln!("{
|
|
388
|
+
_ => eprintln!("{} parsing {}: {}", ui::failure("Error:"), file, error),
|
|
358
389
|
}
|
|
359
390
|
|
|
360
391
|
process::exit(1);
|
|
@@ -366,21 +397,19 @@ pub(crate) fn run_op(display_file: &str, document: &yerba::Document, result: Res
|
|
|
366
397
|
}
|
|
367
398
|
|
|
368
399
|
pub(crate) fn run_op_with_hint(display_file: &str, document: &yerba::Document, result: Result<(), yerba::YerbaError>, hint: Option<&str>) {
|
|
369
|
-
use color::*;
|
|
370
|
-
|
|
371
400
|
if let Err(error) = result {
|
|
372
401
|
if let yerba::YerbaError::SelectorNotFound(selector) = &error {
|
|
373
|
-
eprintln!("{
|
|
402
|
+
eprintln!("{} selector \"{selector}\" not found in {display_file}", ui::failure("Error:"));
|
|
374
403
|
|
|
375
404
|
show_similar_selectors(display_file, document, selector);
|
|
376
405
|
} else {
|
|
377
|
-
eprintln!("{
|
|
406
|
+
eprintln!("{} {}", ui::failure("Error:"), error);
|
|
378
407
|
}
|
|
379
408
|
|
|
380
409
|
if let Some(hint) = hint {
|
|
381
410
|
if matches!(error, yerba::YerbaError::SelectorNotFound(_)) {
|
|
382
411
|
eprintln!();
|
|
383
|
-
eprintln!(" {
|
|
412
|
+
eprintln!(" {}", ui::subtle(format!("Hint: {}", hint)));
|
|
384
413
|
}
|
|
385
414
|
}
|
|
386
415
|
|
|
@@ -389,7 +418,6 @@ pub(crate) fn run_op_with_hint(display_file: &str, document: &yerba::Document, r
|
|
|
389
418
|
}
|
|
390
419
|
|
|
391
420
|
pub(crate) fn show_similar_selectors(file: &str, document: &yerba::Document, invalid_path: &str) {
|
|
392
|
-
use color::*;
|
|
393
421
|
use yerba::didyoumean::didyoumean_ranked;
|
|
394
422
|
|
|
395
423
|
let selectors = document.selectors();
|
|
@@ -405,19 +433,19 @@ pub(crate) fn show_similar_selectors(file: &str, document: &yerba::Document, inv
|
|
|
405
433
|
eprintln!();
|
|
406
434
|
|
|
407
435
|
if close.is_empty() {
|
|
408
|
-
eprintln!(" {
|
|
436
|
+
eprintln!(" {}", ui::strong(format!("Available selectors in {}:", file)));
|
|
409
437
|
|
|
410
438
|
for selector in selectors.iter().take(10) {
|
|
411
|
-
eprintln!(" {
|
|
439
|
+
eprintln!(" {}", ui::subtle(selector));
|
|
412
440
|
}
|
|
413
441
|
|
|
414
442
|
if selectors.len() > 10 {
|
|
415
|
-
eprintln!(" {
|
|
443
|
+
eprintln!(" {}", ui::subtle(format!("... and {} more", selectors.len() - 10)));
|
|
416
444
|
}
|
|
417
445
|
} else if close.len() == 1 {
|
|
418
|
-
eprintln!(" {
|
|
446
|
+
eprintln!(" {} {}", ui::strong("Did you mean this selector?"), close[0]);
|
|
419
447
|
} else {
|
|
420
|
-
eprintln!(" {
|
|
448
|
+
eprintln!(" {}", ui::strong("Did you mean one of these selectors?"));
|
|
421
449
|
|
|
422
450
|
for selector in close.iter().take(5) {
|
|
423
451
|
eprintln!(" {selector}");
|
|
@@ -425,8 +453,8 @@ pub(crate) fn show_similar_selectors(file: &str, document: &yerba::Document, inv
|
|
|
425
453
|
}
|
|
426
454
|
|
|
427
455
|
eprintln!();
|
|
428
|
-
eprintln!(" {
|
|
429
|
-
eprintln!(" yerba selectors \"{file}\"
|
|
456
|
+
eprintln!(" {}", ui::strong("To see all valid selectors, run:"));
|
|
457
|
+
eprintln!(" yerba selectors \"{file}\"");
|
|
430
458
|
}
|
|
431
459
|
|
|
432
460
|
pub(crate) fn output(file: &str, document: &yerba::Document, dry_run: bool) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use super::ui;
|
|
1
2
|
use std::process;
|
|
2
3
|
use std::sync::LazyLock;
|
|
3
4
|
|
|
@@ -43,10 +44,11 @@ impl Args {
|
|
|
43
44
|
let (target_parent, target_key) = target.rsplit_once('.').unwrap_or(("", &target));
|
|
44
45
|
|
|
45
46
|
if target_parent != parent_path {
|
|
46
|
-
use super::color::*;
|
|
47
47
|
eprintln!(
|
|
48
|
-
"{
|
|
49
|
-
|
|
48
|
+
"{} cannot move key across different maps ({} \u{2192} {})\n\n Use 'yerba rename' to relocate keys to a different path.",
|
|
49
|
+
ui::failure("Error:"),
|
|
50
|
+
self.selector,
|
|
51
|
+
target
|
|
50
52
|
);
|
|
51
53
|
|
|
52
54
|
process::exit(1);
|
|
@@ -59,10 +61,11 @@ impl Args {
|
|
|
59
61
|
let (target_parent, target_key) = target.rsplit_once('.').unwrap_or(("", &target));
|
|
60
62
|
|
|
61
63
|
if target_parent != parent_path {
|
|
62
|
-
use super::color::*;
|
|
63
64
|
eprintln!(
|
|
64
|
-
"{
|
|
65
|
-
|
|
65
|
+
"{} cannot move key across different maps ({} \u{2192} {})\n\n Use 'yerba rename' to relocate keys to a different path.",
|
|
66
|
+
ui::failure("Error:"),
|
|
67
|
+
self.selector,
|
|
68
|
+
target
|
|
66
69
|
);
|
|
67
70
|
|
|
68
71
|
process::exit(1);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
use super::ui;
|
|
1
2
|
use std::sync::LazyLock;
|
|
2
3
|
|
|
3
4
|
use indoc::indoc;
|
|
@@ -38,8 +39,8 @@ pub struct Args {
|
|
|
38
39
|
impl Args {
|
|
39
40
|
pub fn run(self) {
|
|
40
41
|
if self.values.is_none() && self.keys.is_none() {
|
|
41
|
-
use super::
|
|
42
|
-
eprintln!("{
|
|
42
|
+
use super::ui;
|
|
43
|
+
eprintln!("{} specify --values, --keys, or both", ui::failure("Error:"));
|
|
43
44
|
std::process::exit(1);
|
|
44
45
|
}
|
|
45
46
|
|
|
@@ -55,9 +56,7 @@ impl Args {
|
|
|
55
56
|
if let Some(style) = &self.values {
|
|
56
57
|
if let Ok(warnings) = document.enforce_quotes_at(style, selector) {
|
|
57
58
|
for warning in warnings {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
eprintln!("{YELLOW}Warning:{RESET} {} — {}", resolved_file, warning);
|
|
59
|
+
eprintln!("{} {} — {}", ui::pending("Warning:"), resolved_file, warning);
|
|
61
60
|
}
|
|
62
61
|
}
|
|
63
62
|
}
|
data/rust/src/commands/schema.rs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
use std::process;
|
|
2
2
|
|
|
3
|
-
use super::color::*;
|
|
4
3
|
use super::resolve_files;
|
|
4
|
+
use super::ui;
|
|
5
5
|
|
|
6
6
|
#[derive(clap::Args)]
|
|
7
7
|
#[command(
|
|
@@ -32,7 +32,7 @@ impl Args {
|
|
|
32
32
|
let schema = match yerba::schema::load_schema(&self.schema) {
|
|
33
33
|
Ok(schema) => schema,
|
|
34
34
|
Err(error) => {
|
|
35
|
-
eprintln!("{
|
|
35
|
+
eprintln!("{} {}", ui::failure("Error:"), error);
|
|
36
36
|
process::exit(1);
|
|
37
37
|
}
|
|
38
38
|
};
|
|
@@ -40,7 +40,7 @@ impl Args {
|
|
|
40
40
|
let files = resolve_files(&self.file);
|
|
41
41
|
|
|
42
42
|
if files.is_empty() {
|
|
43
|
-
eprintln!("{
|
|
43
|
+
eprintln!("{} no files matching: {}", ui::failure("Error:"), self.file);
|
|
44
44
|
process::exit(1);
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -51,7 +51,7 @@ impl Args {
|
|
|
51
51
|
let document = match yerba::Document::parse_file(file) {
|
|
52
52
|
Ok(document) => document,
|
|
53
53
|
Err(error) => {
|
|
54
|
-
eprintln!(" {
|
|
54
|
+
eprintln!(" {} {} {} {}", ui::failure("error:"), ui::subtle("—"), file, error);
|
|
55
55
|
has_errors = true;
|
|
56
56
|
continue;
|
|
57
57
|
}
|
|
@@ -66,7 +66,7 @@ impl Args {
|
|
|
66
66
|
has_errors = true;
|
|
67
67
|
|
|
68
68
|
let relative = file.strip_prefix("./").unwrap_or(file);
|
|
69
|
-
eprintln!(" {
|
|
69
|
+
eprintln!(" {} {relative}", ui::failure("error:"));
|
|
70
70
|
|
|
71
71
|
for error in &errors {
|
|
72
72
|
eprintln!(" {error}");
|
|
@@ -78,7 +78,7 @@ impl Args {
|
|
|
78
78
|
if has_errors {
|
|
79
79
|
process::exit(1);
|
|
80
80
|
} else {
|
|
81
|
-
eprintln!("{
|
|
81
|
+
eprintln!("{}", ui::success(format!("All {} files valid.", files.len())));
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -4,7 +4,7 @@ use std::sync::LazyLock;
|
|
|
4
4
|
use indoc::indoc;
|
|
5
5
|
|
|
6
6
|
use super::colorize_examples;
|
|
7
|
-
use super::{
|
|
7
|
+
use super::{parse_file, resolve_files, ui};
|
|
8
8
|
|
|
9
9
|
static EXAMPLES: LazyLock<String> = LazyLock::new(|| {
|
|
10
10
|
colorize_examples(indoc! {r#"
|
|
@@ -108,7 +108,7 @@ impl Args {
|
|
|
108
108
|
if let Some(label) = info.count_label() {
|
|
109
109
|
let padding = max_selector_len - selector.len() + 2;
|
|
110
110
|
|
|
111
|
-
println!("{}{}{}
|
|
111
|
+
println!("{}{}{}", selector, " ".repeat(padding), ui::subtle(label));
|
|
112
112
|
} else {
|
|
113
113
|
println!("{}", selector);
|
|
114
114
|
}
|