Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): Dry run #156

Merged
merged 8 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,13 @@ Options (global):
Processing no files is not an error condition in itself, but might be an
unexpected outcome in some contexts. This flag makes the condition explicit.

--dry-run
Do not destructively overwrite files, instead print rich diff only.

The diff details the names of files which would be modified, alongside all
changes inside those files which would be performed outside of dry running.
It is similar to git diff with word diffing enabled.

-i, --invert
Undo the effects of passed actions, where applicable.

Expand Down
22 changes: 22 additions & 0 deletions src/actions/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,28 @@ pub struct Style {
pub styles: Vec<Styles>,
}

impl Style {
/// Creates a style with red foreground color and bold font weight.
#[must_use]
pub fn red_bold() -> Self {
Self {
fg: Some(Color::Red),
bg: None,
styles: vec![Styles::Bold],
}
}

/// Creates a style with green foreground color and bold font weight.
#[must_use]
pub fn green_bold() -> Self {
Self {
fg: Some(Color::Green),
bg: None,
styles: vec![Styles::Bold],
}
}
}

impl Action for Style {
fn act(&self, input: &str) -> String {
const NEWLINE: char = '\n';
Expand Down
105 changes: 105 additions & 0 deletions src/iterext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/// Extension trait that adds parallel zipping functionality to iterators over iterators.
pub trait ParallelZipExt: Iterator {
/// Zips multiple iterators in parallel, such that the nth invocation yields a
/// [`Vec`] of all nth items of the subiterators.
fn parallel_zip(self) -> ParallelZip<Self::Item>
where
Self: Sized,
Self::Item: Iterator;
}

/// An iterator similar to [`std::iter::zip`], but instead it zips over *multiple
/// iterators* in parallel, such that the nth invocation yields a [`Vec`] of all
/// nth items of its subiterators.
#[derive(Debug)]
pub struct ParallelZip<I>(Vec<I>);

impl<I: Iterator> Iterator for ParallelZip<I> {
type Item = Vec<I::Item>;

fn next(&mut self) -> Option<Self::Item> {
if self.0.is_empty() {
return None;
}

self.0.iter_mut().map(Iterator::next).collect()
}
}

// Implement the extension trait for any iterator whose items are themselves iterators
impl<T> ParallelZipExt for T
where
T: Iterator,
T::Item: Iterator,
{
fn parallel_zip(self) -> ParallelZip<T::Item> {
ParallelZip(self.collect())
}
}

#[cfg(test)]
mod tests {
use itertools::Itertools;
use rstest::rstest;

use super::*;

#[rstest]
#[case::empty_once(
Vec::<Vec<i32>>::new(),
Vec::new(),
)]
#[case::empty_twice(
vec![
vec![],
vec![],
],
vec![],
)]
#[case::zips_to_shortest(
vec![
vec![0, 1, 2],
vec![3, 4],
],
vec![
vec![0, 3],
vec![1, 4],
]
)]
#[case::base_case(
vec![
vec![1, 2],
vec![3, 4],
vec![5, 6]
],
vec![
vec![1, 3, 5],
vec![2, 4, 6]
]
)]
#[case::transpose_horizontal(
vec![
vec![1, 2, 3],
],
vec![
vec![1],
vec![2],
vec![3],
]
)]
#[case::transpose_vertical(
vec![
vec![1],
vec![2],
vec![3]
],
vec![
vec![1, 2, 3]
]
)]
fn test_parallel_zip(#[case] input: Vec<Vec<i32>>, #[case] expected: Vec<Vec<i32>>) {
let iters = input.into_iter().map(IntoIterator::into_iter).collect_vec();
let res = iters.into_iter().parallel_zip().collect_vec();
assert_eq!(res, expected);
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,6 @@ pub const GLOBAL_SCOPE: &str = r".*";
/// The type of regular expression used throughout the crate. Abstracts away the
/// underlying implementation.
pub use fancy_regex::Regex as RegexPattern;

/// Custom iterator extensions.
pub mod iterext;
Loading