Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
lib: Add line merge utils
Erik Kundt committed 1 year ago
commit 379cb086445c51ca481a0113ff50435107e90c71
parent 6fbea8d
4 files changed +152 -4
modified Cargo.lock
@@ -1587,9 +1587,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"

[[package]]
name = "pretty_assertions"
-
version = "1.4.0"
+
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
+
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
 "diff",
 "yansi",
@@ -1894,6 +1894,7 @@ dependencies = [
 "libc",
 "log",
 "nom",
+
 "pretty_assertions",
 "radicle",
 "radicle-cli",
 "radicle-signals 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3275,9 +3276,9 @@ dependencies = [

[[package]]
name = "yansi"
-
version = "0.5.1"
+
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"

[[package]]
name = "zerocopy"
modified Cargo.toml
@@ -54,3 +54,6 @@ tokio = { version = "1.32.0", features = ["full"] }
tokio-stream = { version = "0.1.14" }
tui-textarea = { version = "0.5.1", default-features = false, features = ["termion"] }
tui-tree-widget = { version = "0.21.0" }
+

+
[dev-dependencies]
+
pretty_assertions = "^1.4.1"

\ No newline at end of file
modified src/ui.rs
@@ -4,6 +4,7 @@ pub mod layout;
pub mod rm;
pub mod span;
pub mod theme;
+
pub mod utils;

use ratatui::layout::Constraint;
use ratatui::text::Text;
added src/ui/utils.rs
@@ -0,0 +1,143 @@
+
use std::collections::HashMap;
+

+
pub struct LineMerger;
+

+
impl LineMerger {
+
    pub fn merge<T: Clone>(
+
        lines: Vec<T>,
+
        mixins: HashMap<usize, Vec<Vec<T>>>,
+
        start: usize,
+
    ) -> Vec<T> {
+
        let mut merged = vec![];
+
        for (idx, line) in lines.iter().enumerate() {
+
            merged.push(line.clone());
+

+
            let actual_idx = idx.saturating_add(start);
+
            if let Some(mixins) = mixins.get(&actual_idx) {
+
                for mixin in mixins {
+
                    for mixin_line in mixin {
+
                        merged.push(mixin_line.clone());
+
                    }
+
                }
+
            }
+
        }
+

+
        merged
+
    }
+
}
+

+
#[cfg(test)]
+
mod test {
+
    use std::collections::HashMap;
+

+
    use pretty_assertions::assert_eq;
+

+
    use crate::ui::utils::LineMerger;
+

+
    #[test]
+
    fn lines_should_be_merged_correctly() -> anyhow::Result<()> {
+
        let diff = r#"
+
fn main() {
+
    println!("Hello, world!");
+

+
    another_function();
+
}
+

+
fn another_function() {
+
    println!("Another function.");
+
}"#;
+

+
        let comment = r#"──────────────────────────────────────
+
Is this needed?
+
──────────────────────────────────────"#
+
            .to_string();
+
        let comment = comment.lines().into_iter().collect::<Vec<_>>();
+

+
        let merged = LineMerger::merge(
+
            diff.lines().into_iter().collect(),
+
            HashMap::from([(3_usize, vec![comment])]),
+
            1,
+
        );
+
        let actual = build_string(merged);
+

+
        let expected = r#"
+
fn main() {
+
    println!("Hello, world!");
+
──────────────────────────────────────
+
Is this needed?
+
──────────────────────────────────────
+

+
    another_function();
+
}
+

+
fn another_function() {
+
    println!("Another function.");
+
}"#;
+

+
        let expected = expected.to_string();
+

+
        assert_eq!(expected, actual);
+

+
        Ok(())
+
    }
+

+
    #[test]
+
    fn lines_with_start_should_be_merged_correctly() -> anyhow::Result<()> {
+
        let diff = r#"
+
fn main() {
+
    println!("Hello, world!");
+

+
    another_function();
+
}
+

+
fn another_function() {
+
    println!("Another function.");
+
}"#;
+

+
        let comment = r#"──────────────────────────────────────
+
Is this needed?
+
──────────────────────────────────────"#
+
            .to_string();
+
        let comment = comment.lines().into_iter().collect::<Vec<_>>();
+

+
        let merged = LineMerger::merge(
+
            diff.lines().into_iter().collect(),
+
            HashMap::from([(104_usize, vec![comment])]),
+
            100,
+
        );
+
        let actual = build_string(merged);
+

+
        let expected = r#"
+
fn main() {
+
    println!("Hello, world!");
+

+
    another_function();
+
──────────────────────────────────────
+
Is this needed?
+
──────────────────────────────────────
+
}
+

+
fn another_function() {
+
    println!("Another function.");
+
}"#;
+

+
        let expected = expected.to_string();
+

+
        assert_eq!(expected, actual);
+

+
        Ok(())
+
    }
+

+
    fn build_string(lines: Vec<&str>) -> String {
+
        let mut actual = String::new();
+
        for (idx, line) in lines.iter().enumerate() {
+
            if idx == lines.len() - 1 {
+
                actual.push_str(&format!("{}", line));
+
            } else {
+
                actual.push_str(&format!("{}\n", line));
+
            }
+
        }
+

+
        actual
+
    }
+
}