refactor diff

[?]
May 1, 2025, 7:36 AM
QMAUTRB6R5R7ABWT2JIDEA7LMILZOS3PGPZIF3YUFKRVLW6HGKTQC

Dependencies

  • [2] 6YZAVBWU Initial commit
  • [3] WT3GA27P add cursor with selection
  • [4] 4WO3ZJM2 show untracked files' contents
  • [5] PTFDJ567 add untracked files encoding
  • [6] AMPZ2BXK show changed files diffs (only Edit atm)
  • [7] V55EAIWQ add src file LRU cache
  • [8] NRCUG4R2 load changed files src when selected
  • [9] Y5ATDI2H convert changed file diffs and load src only if any needs it
  • [10] HOJZI52Y rename flowers_ui to inflorescence
  • [11] MJDGPSHG WIP contents diff
  • [12] ZVI4AWER woot contents_diff
  • [13] EC3TVL4X add untracked files
  • [14] SWWE2R6M display basic repo stuff
  • [15] IQDCHWCP load a pijul repo
  • [16] YBJRDOTC make all repo actions async
  • [17] BJXUYQ2Y show untracked file contents in read-only text editor
  • [18] 3GZPRZXC s/-/_ in crate paths
  • [19] DVKSPF7R track selected file path together with an index

Change contents

  • edit in crates/inflorescence/src/main.rs at line 1
    [2.2763][11.1321:1340]()
    mod contents_diff;
  • edit in crates/inflorescence/src/main.rs at line 2
    [6.1219]
    [6.1219]
    mod diff;
  • replacement in crates/inflorescence/src/main.rs at line 154
    [12.1370][12.1370:1403]()
    Loaded(contents_diff::File),
    [12.1370]
    [7.1770]
    Loaded(diff::File),
  • replacement in crates/inflorescence/src/main.rs at line 172
    [12.1824][12.1824:1898]()
    contents_diff::File::Decoded(contents_diff::DecodedFile {
    [12.1824]
    [12.1898]
    diff::File::Decoded(diff::DecodedFile {
  • replacement in crates/inflorescence/src/main.rs at line 174
    [12.1928][12.1928:1978]()
    contents_diff::Combined {
    [12.1928]
    [12.1978]
    diff::Combined {
  • replacement in crates/inflorescence/src/main.rs at line 184
    [12.2338][12.2338:2580]()
    contents_diff::File::Undecodable(
    contents_diff::UndecodableFile {
    diffs_with_contents,
    diffs_without_contents,
    },
    ) => {
    [12.2338]
    [12.2580]
    diff::File::Undecodable(diff::UndecodableFile {
    diffs_with_contents,
    diffs_without_contents,
    }) => {
  • replacement in crates/inflorescence/src/main.rs at line 239
    [12.3084][12.3084:3120]()
    action: contents_diff::Msg,
    [12.3084]
    [6.1914]
    action: diff::Action,
  • replacement in crates/inflorescence/src/main.rs at line 261
    [12.3709][12.3709:3765]()
    diffs: contents_diff::State::default(),
    [12.3709]
    [12.3765]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 284
    [9.1086][12.4222:4278]()
    diffs: contents_diff::State::default(),
    [9.1086]
    [9.1086]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 523
    [12.9880][12.9880:9944]()
    diffs: contents_diff::State::default(),
    [12.9880]
    [12.9944]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 546
    [12.10850][12.10850:10914]()
    diffs: contents_diff::State::default(),
    [12.10850]
    [9.2006]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 737
    [12.11738][12.11738:11807]()
    contents_diff::FileContent::Decoded(decoded)
    [12.11738]
    [5.1411]
    diff::FileContent::Decoded(decoded)
  • replacement in crates/inflorescence/src/main.rs at line 739
    [5.1433][12.11808:11881]()
    None => contents_diff::FileContent::UnknownEncoding,
    [5.1433]
    [12.11881]
    None => diff::FileContent::UnknownEncoding,
  • replacement in crates/inflorescence/src/main.rs at line 743
    [12.11982][12.11982:12117]()
    let file_diff: contents_diff::File =
    contents_diff::init_file(file_content, None);
    [12.11982]
    [12.12117]
    let file_diff: diff::File =
    diff::init_file(file_content, None);
  • replacement in crates/inflorescence/src/main.rs at line 755
    [12.12539][12.12539:12797]()
    let file_diff: contents_diff::File =
    contents_diff::init_file(
    file_content,
    changed_file,
    );
    [12.12539]
    [12.12797]
    let file_diff: diff::File =
    diff::init_file(file_content, changed_file);
  • replacement in crates/inflorescence/src/main.rs at line 776
    [12.13454][12.13454:13516]()
    contents_diff::update(diffs, action);
    [12.13454]
    [12.13516]
    diff::update(diffs, action);
  • replacement in crates/inflorescence/src/main.rs at line 782
    [12.13729][12.13729:13791]()
    contents_diff::update(diffs, action);
    [12.13729]
    [12.13791]
    diff::update(diffs, action);
  • replacement in crates/inflorescence/src/main.rs at line 869
    [4.8055][12.14440:14516]()
    diffs: contents_diff::State::default(),
    [4.8055]
    [4.8055]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 901
    [8.4489][12.15292:15368]()
    diffs: contents_diff::State::default(),
    [8.4489]
    [8.4489]
    diffs: diff::State::default(),
  • replacement in crates/inflorescence/src/main.rs at line 998
    [12.16445][12.16445:16505]()
    contents_diff::diffs_from_repo_diffs(changed_file);
    [12.16445]
    [12.16505]
    diff::from_repo_changed_file(changed_file);
  • replacement in crates/inflorescence/src/main.rs at line 1079
    [12.17364][12.17364:17510]()
    contents_diff::view(selection_state, file).map(
    move |msg| Message::FileDiffsContentsAction {
    [12.17364]
    [12.17510]
    diff::view(selection_state, file).map(move |msg| {
    Message::FileDiffsContentsAction {
  • replacement in crates/inflorescence/src/main.rs at line 1083
    [12.17603][12.17603:17660]()
    },
    )
    [12.17603]
    [12.17660]
    }
    })
  • replacement in crates/inflorescence/src/main.rs at line 1104
    [12.18338][12.18338:18484]()
    contents_diff::view(selection_state, file).map(
    move |msg| Message::FileDiffsContentsAction {
    [12.18338]
    [12.18484]
    diff::view(selection_state, file).map(move |msg| {
    Message::FileDiffsContentsAction {
  • replacement in crates/inflorescence/src/main.rs at line 1108
    [12.18577][11.2931:2962](),[11.2931][11.2931:2962](),[11.2962][12.18578:18604]()
    },
    )
    [12.18577]
    [11.4823]
    }
    })
  • file move: contents_diff.rs (----------)diff.rs (----------)
    [10.120]
    [11.5018]
  • edit in crates/inflorescence/src/diff.rs at line 12
    [11.5154]
    [11.5154]
    #[allow(dead_code)] // TODO rm once `view_decoded` is fully implemented
    #[derive(Debug, Default)]
    pub struct State {
    pub selected_sections: Vec<usize>,
    pub expanded_unchanged_sections: Vec<usize>,
    pub collapsed_changed_sections: Vec<usize>,
    }
    #[derive(Debug, Clone)]
    pub enum Action {}
    pub fn update(_state: &mut State, _action: Action) {}
    pub fn view<'a>(state: &'a State, file: &'a File) -> Element<'a, Action> {
    match file {
    File::Decoded(decoded_file) => view_decoded(state, decoded_file),
    File::Undecodable(undecodable_file) => {
    view_undecodable(state, undecodable_file)
    }
    }
    }
    /// [`File`] is not part of [`State`] so it can be stored separately (i.e. in a
    /// cache, where it's immutable once set, unlike [`State`] which can change with [`Action`]s)
  • edit in crates/inflorescence/src/diff.rs at line 64
    [12.19687]
    [12.19687]
    UnknownEncoding,
    }
    #[derive(Debug)]
    pub enum DiffWithContents {
    Add,
    Edit {
    line: usize,
    deleted: bool,
    contents: String,
    },
    Replacement {
    line: usize,
    /// Deleted line
    change_contents: String,
    /// Added lines
    replacement_contents: String,
    },
    Del,
    Undel,
    }
    #[allow(dead_code)] // TODO rm once `view_undecodable` is implemented
    #[derive(Debug)]
    pub enum DiffWithoutContents {
    // _________________________________________________________________________
    // Cases that never have contents:
    Move,
    SolveNameConflict,
    UnsolveNameConflict,
    SolveOrderConflict,
    UnsolveOrderConflict,
    ResurrectZombines,
    AddRoot,
    DelRoot,
    // _________________________________________________________________________
    // Cases that normally have contents, but in these cases the contents are
    // not decodable:
    Edit {
    line: usize,
    deleted: bool,
    contents: UndecodableContents,
    },
    Replacement {
    line: usize,
    /// Deleted line
    change_contents: UndecodableContents,
    /// Added lines
    replacement_contents: UndecodableContents,
    },
    }
    #[allow(dead_code)] // TODO rm once `view_undecodable` is implemented
    #[derive(Debug)]
    pub enum UndecodableContents {
    /// Short byte sequence of unknown encoding encoded with base64 for
    /// display. Must be shorter than [`crate::repo::MAX_LEN_BASE64_DISPLAY`]
    ShortBase64(String),
  • edit in crates/inflorescence/src/diff.rs at line 123
    [12.19708]
    [12.19708]
    }
    #[derive(Debug)]
    pub enum Section {
    Unchanged(Lines),
    /// `deleted` and `added` are together because for
    /// `ChangedFileDiffWithContents::Replacement` they begin on the same line
    /// number
    Changed {
    deleted: Lines,
    added: Lines,
    },
  • edit in crates/inflorescence/src/diff.rs at line 136
    [12.19710]
    [12.19710]
    /// INVARIANT: There must be no new-lines in any of the strings, the source
    /// string must be split on those.
    pub type Lines = Vec<String>;
  • replacement in crates/inflorescence/src/diff.rs at line 146
    [12.19891][12.19891:19927]()
    .map(diffs_from_repo_diffs)
    [12.19891]
    [12.19927]
    .map(from_repo_changed_file)
  • replacement in crates/inflorescence/src/diff.rs at line 165
    [11.6147][12.20439:20472]()
    pub fn combine_decoded_contents(
    [11.6147]
    [12.20472]
    pub fn from_repo_changed_file(
    changed_file: &repo::ChangedFile,
    ) -> (Vec<DiffWithContents>, Vec<DiffWithoutContents>) {
    changed_file.iter().fold((vec![], vec![]), |(mut with, mut without), diff| {
    match diff {
    repo::ChangedFileDiff::Move => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::Del => {
    with.push(DiffWithContents::Del);
    },
    repo::ChangedFileDiff::Undel => {
    with.push(DiffWithContents::Undel);
    },
    repo::ChangedFileDiff::Add => {
    with.push(DiffWithContents::Add);
    },
    repo::ChangedFileDiff::SolveNameConflict => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::UnsolveNameConflict => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::Edit { line, deleted, contents } => match contents{
    repo::Contents::Decoded(lines) => {
    with.push(DiffWithContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: lines.clone(),
    });
    },
    repo::Contents::ShortBase64(short) => {
    without.push(DiffWithoutContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: UndecodableContents::ShortBase64(short.clone()),
    });
    },
    repo::Contents::UnknownEncoding(_bytes) => {
    without.push(DiffWithoutContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: UndecodableContents::UnknownEncoding,
    });
    },
    },
    repo::ChangedFileDiff::Replacement { line, change_contents, replacement_contents } => match (change_contents, replacement_contents) {
    (repo::Contents::Decoded(change), repo::Contents::Decoded(replacement)) => {
    with.push(DiffWithContents::Replacement {
    line: *line,
    change_contents: change.clone(),
    replacement_contents: replacement.clone(),
    });
    },
    (repo::Contents::ShortBase64(change), repo::Contents::ShortBase64(replacement)) => {
    without.push(DiffWithoutContents::Replacement {
    line: *line,
    change_contents: UndecodableContents::ShortBase64(change.clone()),
    replacement_contents: UndecodableContents::ShortBase64(replacement.clone()),
    });
    },
    (repo::Contents::UnknownEncoding(_change), repo::Contents::UnknownEncoding(_replacement)) => {
    without.push(DiffWithoutContents::Replacement {
    line: *line,
    change_contents: UndecodableContents::UnknownEncoding,
    replacement_contents: UndecodableContents::UnknownEncoding,
    });
    },
    _ => {
    unimplemented!("The change and replacement have different encoding!");
    }
    },
    repo::ChangedFileDiff::SolveOrderConflict => {
    without.push(DiffWithoutContents::SolveOrderConflict);
    },
    repo::ChangedFileDiff::UnsolveOrderConflict => {
    without.push(DiffWithoutContents::UnsolveOrderConflict);
    },
    repo::ChangedFileDiff::ResurrectZombines => {
    without.push(DiffWithoutContents::ResurrectZombines);
    },
    repo::ChangedFileDiff::AddRoot => {
    without.push(DiffWithoutContents::AddRoot);
    },
    repo::ChangedFileDiff::DelRoot => {
    without.push(DiffWithoutContents::DelRoot);
    },
    };
    (with, without)
    })
    }
    fn combine_decoded_contents(
  • edit in crates/inflorescence/src/diff.rs at line 364
    [11.9939][11.9939:9942](),[11.9942][12.21426:25625]()
    }
    pub fn diffs_from_repo_diffs(
    changed_file: &repo::ChangedFile,
    ) -> (Vec<DiffWithContents>, Vec<DiffWithoutContents>) {
    changed_file.iter().fold((vec![], vec![]), |(mut with, mut without), diff| {
    match diff {
    repo::ChangedFileDiff::Move => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::Del => {
    with.push(DiffWithContents::Del);
    },
    repo::ChangedFileDiff::Undel => {
    with.push(DiffWithContents::Undel);
    },
    repo::ChangedFileDiff::Add => {
    with.push(DiffWithContents::Add);
    },
    repo::ChangedFileDiff::SolveNameConflict => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::UnsolveNameConflict => {
    without.push(DiffWithoutContents::Move);
    },
    repo::ChangedFileDiff::Edit { line, deleted, contents } => match contents{
    repo::Contents::Decoded(lines) => {
    with.push(DiffWithContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: lines.clone(),
    });
    },
    repo::Contents::ShortBase64(short) => {
    without.push(DiffWithoutContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: UndecodableContents::ShortBase64(short.clone()),
    });
    },
    repo::Contents::UnknownEncoding(_bytes) => {
    without.push(DiffWithoutContents::Edit {
    line: *line,
    deleted: *deleted,
    contents: UndecodableContents::UnknownEncoding,
    });
    },
    },
    repo::ChangedFileDiff::Replacement { line, change_contents, replacement_contents } => match (change_contents, replacement_contents) {
    (repo::Contents::Decoded(change), repo::Contents::Decoded(replacement)) => {
    with.push(DiffWithContents::Replacement {
    line: *line,
    change_contents: change.clone(),
    replacement_contents: replacement.clone(),
    });
    },
    (repo::Contents::ShortBase64(change), repo::Contents::ShortBase64(replacement)) => {
    without.push(DiffWithoutContents::Replacement {
    line: *line,
    change_contents: UndecodableContents::ShortBase64(change.clone()),
    replacement_contents: UndecodableContents::ShortBase64(replacement.clone()),
    });
    },
    (repo::Contents::UnknownEncoding(_change), repo::Contents::UnknownEncoding(_replacement)) => {
    without.push(DiffWithoutContents::Replacement {
    line: *line,
    change_contents: UndecodableContents::UnknownEncoding,
    replacement_contents: UndecodableContents::UnknownEncoding,
    });
    },
    _ => {
    unimplemented!("The change and replacement have different encoding!");
    }
    },
    repo::ChangedFileDiff::SolveOrderConflict => {
    without.push(DiffWithoutContents::SolveOrderConflict);
    },
    repo::ChangedFileDiff::UnsolveOrderConflict => {
    without.push(DiffWithoutContents::UnsolveOrderConflict);
    },
    repo::ChangedFileDiff::ResurrectZombines => {
    without.push(DiffWithoutContents::ResurrectZombines);
    },
    repo::ChangedFileDiff::AddRoot => {
    without.push(DiffWithoutContents::AddRoot);
    },
    repo::ChangedFileDiff::DelRoot => {
    without.push(DiffWithoutContents::DelRoot);
    },
    };
    (with, without)
    })
  • edit in crates/inflorescence/src/diff.rs at line 366
    [12.25628][12.25628:27145](),[12.27145][11.10247:10250](),[11.10247][11.10247:10250](),[11.10250][12.27146:27679]()
    #[derive(Debug)]
    pub enum DiffWithContents {
    Add,
    Edit {
    line: usize,
    deleted: bool,
    contents: String,
    },
    Replacement {
    line: usize,
    /// Deleted line
    change_contents: String,
    /// Added lines
    replacement_contents: String,
    },
    Del,
    Undel,
    }
    #[allow(dead_code)] // TODO rm once `view_undecodable` is implemented
    #[derive(Debug)]
    pub enum DiffWithoutContents {
    // _________________________________________________________________________
    // Cases that never have contents:
    Move,
    SolveNameConflict,
    UnsolveNameConflict,
    SolveOrderConflict,
    UnsolveOrderConflict,
    ResurrectZombines,
    AddRoot,
    DelRoot,
    // _________________________________________________________________________
    // Cases that normally have contents, but in these cases the contents are
    // not decodable:
    Edit {
    line: usize,
    deleted: bool,
    contents: UndecodableContents,
    },
    Replacement {
    line: usize,
    /// Deleted line
    change_contents: UndecodableContents,
    /// Added lines
    replacement_contents: UndecodableContents,
    },
    }
    #[allow(dead_code)] // TODO rm once `view_undecodable` is implemented
    #[derive(Debug)]
    pub enum UndecodableContents {
    /// Short byte sequence of unknown encoding encoded with base64 for
    /// display. Must be shorter than [`crate::repo::MAX_LEN_BASE64_DISPLAY`]
    ShortBase64(String),
    UnknownEncoding,
    }
    #[allow(dead_code)] // TODO rm once `view_decoded` is fully implemented
    #[derive(Debug, Default)]
    pub struct State {
    pub selected_sections: Vec<usize>,
    pub expanded_unchanged_sections: Vec<usize>,
    pub collapsed_changed_sections: Vec<usize>,
    }
    #[derive(Debug)]
    pub enum Section {
    Unchanged(Lines),
    /// `deleted` and `added` are together because for
    /// `ChangedFileDiffWithContents::Replacement` they begin on the same line
    /// number
    Changed {
    deleted: Lines,
    added: Lines,
    },
    }
  • edit in crates/inflorescence/src/diff.rs at line 381
    [11.10601][11.10601:10752](),[11.10752][12.27786:27810](),[12.27810][11.10769:10786](),[11.10769][11.10769:10786](),[11.10786][12.27811:28136]()
    }
    }
    /// INVARIANT: There must be no new-lines in any of the strings, the source
    /// string must be split on those.
    pub type Lines = Vec<String>;
    #[derive(Debug, Clone)]
    pub enum Msg {}
    pub fn update(_state: &mut State, _msg: Msg) {}
    pub fn view<'a>(state: &'a State, file: &'a File) -> Element<'a, Msg> {
    match file {
    File::Decoded(decoded_file) => view_decoded(state, decoded_file),
    File::Undecodable(undecodable_file) => {
    view_undecodable(state, undecodable_file)
    }
  • replacement in crates/inflorescence/src/diff.rs at line 384
    [11.10833][12.28145:28170]()
    pub fn view_decoded<'a>(
    [11.10833]
    [12.28170]
    fn view_decoded<'a>(
  • replacement in crates/inflorescence/src/diff.rs at line 387
    [12.28220][12.28220:28244]()
    ) -> Element<'a, Msg> {
    [12.28220]
    [12.28244]
    ) -> Element<'a, Action> {
  • replacement in crates/inflorescence/src/diff.rs at line 452
    [12.28442][12.28442:28471]()
    pub fn view_undecodable<'a>(
    [12.28442]
    [12.28471]
    fn view_undecodable<'a>(
  • replacement in crates/inflorescence/src/diff.rs at line 455
    [12.28525][12.28525:28549]()
    ) -> Element<'a, Msg> {
    [12.28525]
    [12.28549]
    ) -> Element<'a, Action> {
  • replacement in crates/inflorescence/src/cursor.rs at line 1
    [3.26][12.18858:18884]()
    use crate::contents_diff;
    [3.26]
    [12.18884]
    use crate::diff;
  • replacement in crates/inflorescence/src/cursor.rs at line 13
    [12.18965][12.18965:19002]()
    diffs: contents_diff::State,
    [12.18965]
    [12.19002]
    diffs: diff::State,
  • replacement in crates/inflorescence/src/cursor.rs at line 18
    [12.19068][12.19068:19105]()
    diffs: contents_diff::State,
    [12.19068]
    [12.19105]
    diffs: diff::State,