yerba 0.7.0 → 0.7.1
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/lib/yerba/version.rb +1 -1
- data/rust/Cargo.toml +1 -1
- data/rust/src/document/style.rs +102 -24
- data/rust/src/yerbafile.rs +23 -3
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c659373d09accba735b75efdae48ee3c22a801f95f9669403bbc96220c29e80b
|
|
4
|
+
data.tar.gz: 28625aeb5c6939da11d4dfc9fd6de3d17e5f7923c4c49d2bfcb97b5dcf9ba9f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ade24547cfc1b6b9423dac87eef5a979c10aa5a1d0755912273d9504d928587447d876e693beba7ab6bc5ab7185c534ebd956e3cf7172ef3d308b8a112dfb3ec
|
|
7
|
+
data.tar.gz: 898d28671752d146d0da2f695839af841b75462c3aec72192f277349778aec635df9c9775fb8015124dae6973011af1ce996115d3a9c7fa1303fb031c50217c1
|
data/lib/yerba/version.rb
CHANGED
data/rust/Cargo.toml
CHANGED
data/rust/src/document/style.rs
CHANGED
|
@@ -406,42 +406,120 @@ impl Document {
|
|
|
406
406
|
}
|
|
407
407
|
|
|
408
408
|
loop {
|
|
409
|
-
let
|
|
410
|
-
|
|
411
|
-
|
|
409
|
+
let source = self.root.text().to_string();
|
|
410
|
+
|
|
411
|
+
let scope_node = if scope_path.is_empty() {
|
|
412
|
+
self.root.clone()
|
|
413
|
+
} else {
|
|
414
|
+
match self.navigate(scope_path) {
|
|
415
|
+
Ok(node) => node,
|
|
416
|
+
Err(_) => return Ok(()),
|
|
417
|
+
}
|
|
412
418
|
};
|
|
413
419
|
|
|
414
|
-
let mut
|
|
420
|
+
let mut mismatch_ranges: Vec<TextRange> = Vec::new();
|
|
421
|
+
|
|
422
|
+
for descendant in scope_node.descendants() {
|
|
423
|
+
if !BlockSeq::can_cast(descendant.kind()) {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
let parent_entry = match descendant.ancestors().find(|ancestor| ancestor.kind() == SyntaxKind::BLOCK_MAP_ENTRY) {
|
|
428
|
+
Some(entry) => entry,
|
|
429
|
+
None => continue,
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
let first_entry = match BlockSeq::cast(descendant.clone()).and_then(|sequence| sequence.entries().next()) {
|
|
433
|
+
Some(entry) => entry,
|
|
434
|
+
None => continue,
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
let key_indent = preceding_whitespace_indent(&parent_entry).len();
|
|
438
|
+
let entry_indent = preceding_whitespace_indent(first_entry.syntax()).len();
|
|
439
|
+
let is_indented = entry_indent > key_indent;
|
|
415
440
|
|
|
416
|
-
|
|
417
|
-
|
|
441
|
+
if (style == "indented" && !is_indented) || (style == "compact" && is_indented) {
|
|
442
|
+
mismatch_ranges.push(descendant.text_range());
|
|
443
|
+
}
|
|
418
444
|
}
|
|
419
445
|
|
|
420
|
-
|
|
446
|
+
if mismatch_ranges.is_empty() {
|
|
447
|
+
return Ok(());
|
|
448
|
+
}
|
|
421
449
|
|
|
422
|
-
let
|
|
423
|
-
.into_iter()
|
|
424
|
-
.flat_map(|selector| {
|
|
425
|
-
if selector.contains("[]") {
|
|
426
|
-
self.resolve_selectors(&selector)
|
|
427
|
-
} else {
|
|
428
|
-
vec![selector]
|
|
429
|
-
}
|
|
430
|
-
})
|
|
431
|
-
.collect();
|
|
450
|
+
let mut edits: Vec<(TextRange, String)> = Vec::new();
|
|
432
451
|
|
|
433
|
-
|
|
434
|
-
.
|
|
435
|
-
|
|
436
|
-
|
|
452
|
+
for range in &mismatch_ranges {
|
|
453
|
+
if mismatch_ranges.iter().any(|other| other != range && range.contains_range(*other)) {
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
437
456
|
|
|
438
|
-
|
|
457
|
+
let node = match scope_node
|
|
458
|
+
.descendants()
|
|
459
|
+
.find(|descendant| BlockSeq::can_cast(descendant.kind()) && descendant.text_range() == *range)
|
|
460
|
+
{
|
|
461
|
+
Some(node) => node,
|
|
462
|
+
None => continue,
|
|
463
|
+
};
|
|
464
|
+
let parent_entry = match node.ancestors().find(|ancestor| ancestor.kind() == SyntaxKind::BLOCK_MAP_ENTRY) {
|
|
465
|
+
Some(entry) => entry,
|
|
466
|
+
None => continue,
|
|
467
|
+
};
|
|
468
|
+
let first_entry = match BlockSeq::cast(node).and_then(|seq| seq.entries().next()) {
|
|
469
|
+
Some(entry) => entry,
|
|
470
|
+
None => continue,
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
let key_indent = preceding_whitespace_indent(&parent_entry).len();
|
|
474
|
+
let entry_indent = preceding_whitespace_indent(first_entry.syntax()).len();
|
|
475
|
+
|
|
476
|
+
let indent_diff: i32 = match style {
|
|
477
|
+
"indented" => (key_indent as i32 + 2) - entry_indent as i32,
|
|
478
|
+
"compact" => key_indent as i32 - entry_indent as i32,
|
|
479
|
+
_ => continue,
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
if indent_diff == 0 {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
let seq_start: usize = range.start().into();
|
|
487
|
+
let line_start = source[..seq_start].rfind('\n').map(|pos| pos + 1).unwrap_or(0);
|
|
488
|
+
let full_text = &source[line_start..usize::from(range.end())];
|
|
489
|
+
|
|
490
|
+
let reindented: String = full_text
|
|
491
|
+
.lines()
|
|
492
|
+
.map(|line| {
|
|
493
|
+
if line.trim().is_empty() {
|
|
494
|
+
String::new()
|
|
495
|
+
} else {
|
|
496
|
+
let current_indent = line.len() - line.trim_start().len();
|
|
497
|
+
let new_indent = (current_indent as i32 + indent_diff).max(0) as usize;
|
|
498
|
+
format!("{}{}", " ".repeat(new_indent), line.trim_start())
|
|
499
|
+
}
|
|
500
|
+
})
|
|
501
|
+
.collect::<Vec<_>>()
|
|
502
|
+
.join("\n");
|
|
503
|
+
|
|
504
|
+
edits.push((TextRange::new(rowan::TextSize::from(line_start as u32), range.end()), reindented));
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
if edits.is_empty() {
|
|
439
508
|
return Ok(());
|
|
440
509
|
}
|
|
441
510
|
|
|
442
|
-
|
|
511
|
+
edits.sort_by_key(|edit| std::cmp::Reverse(edit.0.start()));
|
|
512
|
+
|
|
513
|
+
let mut new_source = source;
|
|
514
|
+
for (range, replacement) in edits {
|
|
515
|
+
let start: usize = range.start().into();
|
|
516
|
+
let end: usize = range.end().into();
|
|
517
|
+
new_source.replace_range(start..end, &replacement);
|
|
518
|
+
}
|
|
443
519
|
|
|
444
|
-
self.
|
|
520
|
+
let path = self.path.take();
|
|
521
|
+
*self = Self::parse(&new_source)?;
|
|
522
|
+
self.path = path;
|
|
445
523
|
}
|
|
446
524
|
}
|
|
447
525
|
|
data/rust/src/yerbafile.rs
CHANGED
|
@@ -439,6 +439,24 @@ impl Yerbafile {
|
|
|
439
439
|
results
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
fn relativize_path(&self, file_path: &str) -> Option<String> {
|
|
443
|
+
let path = Path::new(file_path);
|
|
444
|
+
|
|
445
|
+
if !path.is_absolute() {
|
|
446
|
+
return None;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if let Some(directory) = &self.directory {
|
|
450
|
+
if let Ok(relative) = path.strip_prefix(directory) {
|
|
451
|
+
return Some(relative.to_string_lossy().to_string());
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
std::env::current_dir()
|
|
456
|
+
.ok()
|
|
457
|
+
.and_then(|cwd| path.strip_prefix(&cwd).ok().map(|relative| relative.to_string_lossy().to_string()))
|
|
458
|
+
}
|
|
459
|
+
|
|
442
460
|
fn should_run_global_pipeline(&self, file_path: &str) -> bool {
|
|
443
461
|
if self.pipeline.is_empty() {
|
|
444
462
|
return false;
|
|
@@ -454,15 +472,17 @@ impl Yerbafile {
|
|
|
454
472
|
|
|
455
473
|
pub fn apply_to_document(&self, document: &mut Document, file_path: &str) -> Result<bool, YerbaError> {
|
|
456
474
|
let original = document.to_string();
|
|
475
|
+
let relative_path = self.relativize_path(file_path);
|
|
476
|
+
let match_path = relative_path.as_deref().unwrap_or(file_path);
|
|
457
477
|
|
|
458
|
-
if self.should_run_global_pipeline(
|
|
478
|
+
if self.should_run_global_pipeline(match_path) {
|
|
459
479
|
execute_pipeline(document, &self.pipeline, None, file_path, self)?;
|
|
460
480
|
}
|
|
461
481
|
|
|
462
482
|
for rule in &self.rules {
|
|
463
|
-
if !
|
|
483
|
+
if !match_path.is_empty() {
|
|
464
484
|
if let Ok(pattern) = glob::Pattern::new(&rule.files) {
|
|
465
|
-
if !pattern.matches(
|
|
485
|
+
if !pattern.matches(match_path) && !pattern.matches_path(Path::new(match_path)) {
|
|
466
486
|
continue;
|
|
467
487
|
}
|
|
468
488
|
} else {
|