Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
bin: Improve hunk items
Erik Kundt committed 1 year ago
commit baaca35fc5dfc9d4997f94cddcde245f00a545f6
parent 76f55f0
2 files changed +142 -145
modified bin/cob.rs
@@ -1,28 +1,24 @@
+
pub mod inbox;
+
pub mod issue;
+
pub mod patch;
+

+
use std::path::{Path, PathBuf};
use std::str::FromStr;

use anyhow::Result;

use radicle::cob::Label;
-
use radicle::prelude::Did;
-
use radicle_cli::git::unified_diff::FileHeader;
-

-
use std::path::{Path, PathBuf};
-

use radicle::git::Oid;
-

+
use radicle::prelude::Did;
use radicle_surf::diff::*;

+
use radicle_cli::git::unified_diff::FileHeader;
use radicle_cli::git::unified_diff::HunkHeader;

use crate::git::Blob;
use crate::git::Repo;
use crate::ui::items::Blobs;

-
pub mod inbox;
-
pub mod issue;
-
pub mod patch;
-

-
pub type IndexedHunkItem = (usize, crate::cob::HunkItem, HunkState);
pub type FilePaths<'a> = (Option<(&'a Path, Oid)>, Option<(&'a Path, Oid)>);

#[allow(dead_code)]
@@ -205,3 +201,26 @@ impl HunkItem {
        Blobs::from_paths(old, new, repo)
    }
}
+

+
#[derive(Clone, Debug)]
+
pub struct StatefulHunkItem(HunkItem, HunkState);
+

+
impl StatefulHunkItem {
+
    pub fn hunk(&self) -> &HunkItem {
+
        &self.0
+
    }
+

+
    pub fn state(&self) -> &HunkState {
+
        &self.1
+
    }
+

+
    pub fn state_mut(&mut self) -> &mut HunkState {
+
        &mut self.1
+
    }
+
}
+

+
impl From<(&HunkItem, &HunkState)> for StatefulHunkItem {
+
    fn from(value: (&HunkItem, &HunkState)) -> Self {
+
        Self(value.0.clone(), value.1.clone())
+
    }
+
}
modified bin/ui/items.rs
@@ -42,7 +42,7 @@ use tui::ui::utils::LineMerger;
use tui::ui::{span, Column};
use tui::ui::{ToRow, ToTree};

-
use crate::cob::{DiffStats, HunkStats, IndexedHunkItem};
+
use crate::cob::{DiffStats, HunkStats, StatefulHunkItem};
use crate::git::{Blob, Repo};
use crate::ui;

@@ -1094,8 +1094,8 @@ impl From<Vec<(EntryId, Comment<CodeLocation>)>> for HunkComments {
/// provide access to the underlying hunk type.
#[derive(Clone, Debug)]
pub struct HunkItem<'a> {
-
    /// The indexed, underlying hunk type.
-
    pub inner: IndexedHunkItem,
+
    /// The underlying hunk type and its current state (accepted / rejected).
+
    pub inner: StatefulHunkItem,
    /// Raw or highlighted hunk lines. Highlighting is expensive and needs to be asynchronously.
    /// Therefor, a hunks' lines need to stored separately.
    pub lines: Blobs<Vec<Line<'a>>>,
@@ -1103,12 +1103,13 @@ pub struct HunkItem<'a> {
    pub comments: HunkComments,
}

-
impl<'a> From<(&Repository, &Review, &IndexedHunkItem)> for HunkItem<'a> {
-
    fn from(value: (&Repository, &Review, &IndexedHunkItem)) -> Self {
+
impl<'a> From<(&Repository, &Review, StatefulHunkItem)> for HunkItem<'a> {
+
    fn from(value: (&Repository, &Review, StatefulHunkItem)) -> Self {
        let (repo, review, item) = value;
        let hi = Highlighter::default();
+
        let hunk = item.hunk();

-
        let path = match &item.1 {
+
        let path = match &hunk {
            crate::cob::HunkItem::Added { path, .. } => path,
            crate::cob::HunkItem::Modified { path, .. } => path,
            crate::cob::HunkItem::Deleted { path, .. } => path,
@@ -1121,7 +1122,7 @@ impl<'a> From<(&Repository, &Review, &IndexedHunkItem)> for HunkItem<'a> {
        // TODO(erikli): Start with raw, non-highlighted lines and
        // move highlighting to separate task / thread, e.g. here:
        // `let lines = blobs.raw()`
-
        let blobs = item.1.clone().blobs(repo.raw());
+
        let blobs = hunk.clone().blobs(repo.raw());
        let lines = blobs.highlight(hi);
        let comments = review
            .comments()
@@ -1174,18 +1175,14 @@ impl<'a> ToRow<3> for HunkItem<'a> {
            cell
        };

-
        match &self.inner {
-
            (
-
                _,
-
                Item::Added {
-
                    path,
-
                    header: _,
-
                    new: _,
-
                    hunk,
-
                    _stats: _,
-
                },
-
                state,
-
            ) => {
+
        match &self.inner.hunk() {
+
            Item::Added {
+
                path,
+
                header: _,
+
                new: _,
+
                hunk,
+
                _stats: _,
+
            } => {
                let stats = hunk.as_ref().map(HunkStats::from).unwrap_or_default();
                let stats_cell = [
                    build_stats_spans(&DiffStats::Hunk(stats)),
@@ -1194,23 +1191,21 @@ impl<'a> ToRow<3> for HunkItem<'a> {
                .concat();

                [
-
                    ui::span::hunk_state(state).into_right_aligned_line().into(),
+
                    ui::span::hunk_state(self.inner.state())
+
                        .into_right_aligned_line()
+
                        .into(),
                    HunkItem::pretty_path(path, false).into(),
                    Line::from(stats_cell).right_aligned().into(),
                ]
            }
-
            (
-
                _,
-
                Item::Modified {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                    hunk,
-
                    _stats: _,
-
                },
-
                state,
-
            ) => {
+
            Item::Modified {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
                hunk,
+
                _stats: _,
+
            } => {
                let stats = hunk.as_ref().map(HunkStats::from).unwrap_or_default();
                let stats_cell = [
                    build_stats_spans(&DiffStats::Hunk(stats)),
@@ -1219,22 +1214,20 @@ impl<'a> ToRow<3> for HunkItem<'a> {
                .concat();

                [
-
                    ui::span::hunk_state(state).into_right_aligned_line().into(),
+
                    ui::span::hunk_state(self.inner.state())
+
                        .into_right_aligned_line()
+
                        .into(),
                    HunkItem::pretty_path(path, false).into(),
                    Line::from(stats_cell).right_aligned().into(),
                ]
            }
-
            (
-
                _,
-
                Item::Deleted {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    hunk,
-
                    _stats: _,
-
                },
-
                state,
-
            ) => {
+
            Item::Deleted {
+
                path,
+
                header: _,
+
                old: _,
+
                hunk,
+
                _stats: _,
+
            } => {
                let stats = hunk.as_ref().map(HunkStats::from).unwrap_or_default();
                let stats_cell = [
                    build_stats_spans(&DiffStats::Hunk(stats)),
@@ -1243,12 +1236,14 @@ impl<'a> ToRow<3> for HunkItem<'a> {
                .concat();

                [
-
                    ui::span::hunk_state(state).into_right_aligned_line().into(),
+
                    ui::span::hunk_state(self.inner.state())
+
                        .into_right_aligned_line()
+
                        .into(),
                    HunkItem::pretty_path(path, true).into(),
                    Line::from(stats_cell).right_aligned().into(),
                ]
            }
-
            (_, Item::Copied { copied }, state) => {
+
            Item::Copied { copied } => {
                let stats = copied.diff.stats().copied().unwrap_or_default();
                let stats_cell = [
                    build_stats_spans(&DiffStats::File(stats)),
@@ -1257,12 +1252,14 @@ impl<'a> ToRow<3> for HunkItem<'a> {
                .concat();

                [
-
                    ui::span::hunk_state(state).into_right_aligned_line().into(),
+
                    ui::span::hunk_state(self.inner.state())
+
                        .into_right_aligned_line()
+
                        .into(),
                    HunkItem::pretty_path(&copied.new_path, false).into(),
                    Line::from(stats_cell).right_aligned().into(),
                ]
            }
-
            (_, Item::Moved { moved }, state) => {
+
            Item::Moved { moved } => {
                let stats = moved.diff.stats().copied().unwrap_or_default();
                let stats_cell = [
                    build_stats_spans(&DiffStats::File(stats)),
@@ -1271,40 +1268,38 @@ impl<'a> ToRow<3> for HunkItem<'a> {
                .concat();

                [
-
                    ui::span::hunk_state(state).into_right_aligned_line().into(),
+
                    ui::span::hunk_state(self.inner.state())
+
                        .into_right_aligned_line()
+
                        .into(),
                    HunkItem::pretty_path(&moved.new_path, false).into(),
                    Line::from(stats_cell).right_aligned().into(),
                ]
            }
-
            (
-
                _,
-
                Item::EofChanged {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                    _eof: _,
-
                },
-
                state,
-
            ) => [
-
                ui::span::hunk_state(state).into_right_aligned_line().into(),
+
            Item::EofChanged {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
                _eof: _,
+
            } => [
+
                ui::span::hunk_state(self.inner.state())
+
                    .into_right_aligned_line()
+
                    .into(),
                HunkItem::pretty_path(path, false).into(),
                span::default("EOF ")
                    .light_blue()
                    .into_right_aligned_line()
                    .into(),
            ],
-
            (
-
                _,
-
                Item::ModeChanged {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                },
-
                state,
-
            ) => [
-
                ui::span::hunk_state(state).into_right_aligned_line().into(),
+
            Item::ModeChanged {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
            } => [
+
                ui::span::hunk_state(self.inner.state())
+
                    .into_right_aligned_line()
+
                    .into(),
                HunkItem::pretty_path(path, false).into(),
                span::default("FM ")
                    .light_blue()
@@ -1358,18 +1353,14 @@ impl<'a> HunkItem<'a> {
            span::blank()
        };

-
        match &self.inner {
-
            (
-
                _,
-
                crate::cob::HunkItem::Added {
-
                    path,
-
                    header: _,
-
                    new: _,
-
                    hunk: _,
-
                    _stats: _,
-
                },
-
                _,
-
            ) => {
+
        match &self.inner.hunk() {
+
            crate::cob::HunkItem::Added {
+
                path,
+
                header: _,
+
                new: _,
+
                hunk: _,
+
                _stats: _,
+
            } => {
                let path = HunkItem::pretty_path(path, false);
                let header = [
                    Column::new("", Constraint::Length(0)),
@@ -1390,18 +1381,15 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (
-
                _,
-
                crate::cob::HunkItem::Modified {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                    hunk: _,
-
                    _stats: _,
-
                },
-
                _,
-
            ) => {
+

+
            crate::cob::HunkItem::Modified {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
                hunk: _,
+
                _stats: _,
+
            } => {
                let path = HunkItem::pretty_path(path, false);
                let header = [
                    Column::new("", Constraint::Length(0)),
@@ -1422,17 +1410,14 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (
-
                _,
-
                crate::cob::HunkItem::Deleted {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    hunk: _,
-
                    _stats: _,
-
                },
-
                _,
-
            ) => {
+

+
            crate::cob::HunkItem::Deleted {
+
                path,
+
                header: _,
+
                old: _,
+
                hunk: _,
+
                _stats: _,
+
            } => {
                let path = HunkItem::pretty_path(path, true);
                let header = [
                    Column::new("", Constraint::Length(0)),
@@ -1453,7 +1438,7 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (_, crate::cob::HunkItem::Copied { copied }, _) => {
+
            crate::cob::HunkItem::Copied { copied } => {
                let path = Line::from(
                    [
                        HunkItem::pretty_path(&copied.old_path, false).spans,
@@ -1478,7 +1463,7 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (_, crate::cob::HunkItem::Moved { moved }, _) => {
+
            crate::cob::HunkItem::Moved { moved } => {
                let path = Line::from(
                    [
                        HunkItem::pretty_path(&moved.old_path, false).spans,
@@ -1503,17 +1488,14 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (
-
                _,
-
                crate::cob::HunkItem::EofChanged {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                    _eof: _,
-
                },
-
                _,
-
            ) => {
+

+
            crate::cob::HunkItem::EofChanged {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
                _eof: _,
+
            } => {
                let path = HunkItem::pretty_path(path, false);
                let header = [
                    Column::new("", Constraint::Length(0)),
@@ -1529,16 +1511,12 @@ impl<'a> HunkItem<'a> {

                header.to_vec()
            }
-
            (
-
                _,
-
                crate::cob::HunkItem::ModeChanged {
-
                    path,
-
                    header: _,
-
                    old: _,
-
                    new: _,
-
                },
-
                _,
-
            ) => {
+
            crate::cob::HunkItem::ModeChanged {
+
                path,
+
                header: _,
+
                old: _,
+
                new: _,
+
            } => {
                let path = HunkItem::pretty_path(path, false);
                let header = [
                    Column::new("", Constraint::Length(0)),
@@ -1560,10 +1538,10 @@ impl<'a> HunkItem<'a> {
    pub fn hunk_text(&'a self) -> Option<Text<'a>> {
        use crate::cob::HunkItem;

-
        match &self.inner {
-
            (_, HunkItem::Added { hunk, .. }, _)
-
            | (_, HunkItem::Modified { hunk, .. }, _)
-
            | (_, HunkItem::Deleted { hunk, .. }, _) => {
+
        match &self.inner.hunk() {
+
            HunkItem::Added { hunk, .. }
+
            | HunkItem::Modified { hunk, .. }
+
            | HunkItem::Deleted { hunk, .. } => {
                let mut lines = hunk
                    .as_ref()
                    .map(|hunk| Text::from(hunk.to_text(&self.lines)));