refactor stairs

[?]
Jul 15, 2025, 4:06 PM
AI3IMKC3HRPMTWQCU5HGWKUHGKTJ22QF7V4AAEI6IEBIZ4WYWCKQC

Dependencies

  • [2] L6KSEFQI move cursor related stuff into its module
  • [3] BFN2VHZS refactor file stuff into sub-mod
  • [4] KWTBNTO3 diffs selection and scrolling
  • [5] 5MUEECMJ smooth scrolling nav
  • [6] 3TLPJ57B alt scroll via context and couple fixes
  • [7] YKHE3XMW refactor diffs handling
  • [8] 4PNWU55O replace the circular hor navigation
  • [9] BNHJU2DU clippy fixes
  • [10] KQABQCCZ update rust to 1.88
  • [*] WT3GA27P add cursor with selection

Change contents

  • replacement in inflorescence/src/cursor.rs at line 177
    [4.22942][4.22942:23632](),[4.23632][5.5855:5968](),[5.5968][4.23741:23767](),[4.23741][4.23741:23767](),[4.23767][5.5969:6042](),[5.6042][4.23833:24411](),[4.23833][4.23833:24411]()
    // TODO stair
    if let Some(repo) = repo.as_ref() {
    let (selection, task) = match state.selection.take() {
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Untracked);
    (
    Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
    } else {
    Task::none()
    },
    )
    } else if repo.untracked_files.len().saturating_sub(1) == ix {
    if !repo.changed_files.is_empty() {
    let ix = 0;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    } else if !repo.log.is_empty() {
    let ix = 0;
    (log_selection(repo, ix), Task::none())
    [4.22942]
    [4.24411]
    let Some(repo) = repo.as_ref() else {
    return Task::none();
    };
    let (selection, task) = match state.selection.take() {
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);
    (
    Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
  • replacement in inflorescence/src/cursor.rs at line 200
    [4.24440][4.24440:24637](),[4.24637][2.4594:4616](),[2.4594][2.4594:4616]()
    let ix = 0;
    let selection =
    untracked_file_selection(repo, ix, files);
    (selection, Task::none())
    }
    [4.24440]
    [4.24638]
    Task::none()
    },
    )
    } else if repo.untracked_files.len().saturating_sub(1) == ix {
    if !repo.changed_files.is_empty() {
    let ix = 0;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    } else if !repo.log.is_empty() {
    let ix = 0;
    (log_selection(repo, ix), Task::none())
  • replacement in inflorescence/src/cursor.rs at line 212
    [4.24663][4.24663:24700]()
    let ix = ix + 1;
    [4.24663]
    [4.24700]
    let ix = 0;
  • replacement in inflorescence/src/cursor.rs at line 215
    [4.24825][4.24825:25461](),[4.25461][5.6043:6156](),[5.6156][4.25570:25596](),[4.25570][4.25570:25596](),[4.25596][5.6157:6230](),[5.6230][4.25662:26270](),[4.25662][4.25662:26270]()
    };
    (Some(selection), task)
    }
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Changed);
    (
    Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
    } else {
    Task::none()
    },
    )
    } else if repo.changed_files.len().saturating_sub(1) == ix {
    if !repo.log.is_empty() {
    let ix = 0;
    (log_selection(repo, ix), Task::none())
    } else if !repo.untracked_files.is_empty() {
    let ix = 0;
    let selection =
    untracked_file_selection(repo, ix, files);
    (selection, Task::none())
    [4.24825]
    [4.26270]
    }
    } else {
    let ix = ix + 1;
    let selection = untracked_file_selection(repo, ix, files);
    (selection, Task::none())
    };
    (Some(selection), task)
    }
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash = file::id_parts_hash(&path, file::Kind::Changed);
    (
    Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
  • replacement in inflorescence/src/cursor.rs at line 242
    [4.26299][4.26299:26466](),[4.26466][2.6531:6553](),[2.6531][2.6531:6553]()
    let ix = 0;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    }
    [4.26299]
    [4.26467]
    Task::none()
    },
    )
    } else if repo.changed_files.len().saturating_sub(1) == ix {
    if !repo.log.is_empty() {
    let ix = 0;
    (log_selection(repo, ix), Task::none())
    } else if !repo.untracked_files.is_empty() {
    let ix = 0;
    let selection = untracked_file_selection(repo, ix, files);
    (selection, Task::none())
  • replacement in inflorescence/src/cursor.rs at line 254
    [4.26492][4.26492:26529]()
    let ix = ix + 1;
    [4.26492]
    [4.26529]
    let ix = 0;
  • replacement in inflorescence/src/cursor.rs at line 257
    [4.26652][4.26652:27091](),[4.27091][2.6761:6789](),[2.6761][2.6761:6789](),[2.6789][4.27092:27835](),[4.27835][5.6231:6364](),[5.6364][4.27964:27998](),[4.27964][4.27964:27998](),[4.27998][5.6365:6446](),[5.6446][4.28072:28335](),[4.28072][4.28072:28335]()
    };
    (Some(selection), task)
    }
    Some(Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) => {
    let (selection, task) = match file {
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) => {
    if diff_selected {
    let id_hash = file::log_id_parts_hash(hash, &path);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    },
    if let Some(nav) = logs
    .diffs
    .get_mut(&id_hash)
    .and_then(|diff| diff.state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
    } else {
    Task::none()
    },
    )
    } else {
    let log_entry = repo.log.get(log_ix).unwrap();
    [4.26652]
    [2.7109]
    }
    } else {
    let ix = ix + 1;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    };
    (Some(selection), task)
    }
    Some(Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) => {
    let (selection, task) = match file {
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) => {
    if diff_selected {
    let id_hash = file::log_id_parts_hash(hash, &path);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    },
    if let Some(nav) = logs
    .diffs
    .get_mut(&id_hash)
    .and_then(|diff| diff.state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_down(nav, delta)
    } else {
    Task::none()
    },
    )
    } else {
    let log_entry = repo.log.get(log_ix).unwrap();
  • replacement in inflorescence/src/cursor.rs at line 303
    [2.7110][4.28336:28458](),[4.28458][2.7315:7558](),[2.7315][2.7315:7558]()
    let file_ix =
    if log_entry.file_paths.len().saturating_sub(1)
    == file_ix
    {
    0
    } else {
    file_ix + 1
    };
    [2.7110]
    [2.7558]
    let file_ix =
    if log_entry.file_paths.len().saturating_sub(1)
    == file_ix
    {
    0
    } else {
    file_ix + 1
    };
  • replacement in inflorescence/src/cursor.rs at line 312
    [2.7559][4.28459:28538]()
    let file = log_file_selection(log_entry, file_ix);
    [2.7559]
    [2.7678]
    let file = log_file_selection(log_entry, file_ix);
  • replacement in inflorescence/src/cursor.rs at line 314
    [2.7679][4.28539:28950]()
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    },
    Task::none(),
    )
    }
    [2.7679]
    [4.28950]
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    },
    Task::none(),
    )
  • replacement in inflorescence/src/cursor.rs at line 324
    [4.28972][4.28972:29513](),[4.29513][2.9832:9873](),[2.9832][2.9832:9873](),[2.9873][4.29514:29562](),[4.29562][2.9930:9990](),[2.9930][2.9930:9990](),[2.9990][4.29563:29597]()
    None => {
    let selection =
    if repo.log.len().saturating_sub(1) == log_ix {
    if !repo.untracked_files.is_empty() {
    let ix = 0;
    untracked_file_selection(repo, ix, files)
    } else if !repo.changed_files.is_empty() {
    let ix = 0;
    changed_file_selection(repo, ix, files)
    } else {
    let ix = 0;
    log_selection(repo, ix)
    }
    [4.28972]
    [4.29597]
    }
    None => {
    let selection =
    if repo.log.len().saturating_sub(1) == log_ix {
    if !repo.untracked_files.is_empty() {
    let ix = 0;
    untracked_file_selection(repo, ix, files)
    } else if !repo.changed_files.is_empty() {
    let ix = 0;
    changed_file_selection(repo, ix, files)
  • replacement in inflorescence/src/cursor.rs at line 335
    [4.29634][4.29634:29687]()
    let ix = log_ix + 1;
    [4.29634]
    [4.29687]
    let ix = 0;
  • replacement in inflorescence/src/cursor.rs at line 337
    [4.29743][4.29743:29824](),[4.29824][2.10180:10202](),[2.10180][2.10180:10202](),[2.10202][4.29825:30139]()
    };
    (selection, Task::none())
    }
    };
    (Some(selection), task)
    }
    None => {
    let (selection, task) = if !repo.untracked_files.is_empty() {
    let ix = 0;
    let selection =
    Some(untracked_file_selection(repo, ix, files));
    [4.29743]
    [4.30139]
    }
    } else {
    let ix = log_ix + 1;
    log_selection(repo, ix)
    };
  • replacement in inflorescence/src/cursor.rs at line 343
    [4.30185][4.30185:30874]()
    } else if !repo.changed_files.is_empty() {
    let ix = 0;
    let selection =
    Some(changed_file_selection(repo, ix, files));
    (selection, Task::none())
    } else if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    let selection = log_selection(repo, ix);
    (Some(selection), Task::none())
    } else {
    (None, Task::none())
    };
    (selection, task)
    }
    };
    state.selection = selection;
    task
    } else {
    Task::none()
    }
    [4.30185]
    [4.30874]
    }
    };
    (Some(selection), task)
    }
    None => {
    let (selection, task) = if !repo.untracked_files.is_empty() {
    let ix = 0;
    let selection = Some(untracked_file_selection(repo, ix, files));
    (selection, Task::none())
    } else if !repo.changed_files.is_empty() {
    let ix = 0;
    let selection = Some(changed_file_selection(repo, ix, files));
    (selection, Task::none())
    } else if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    let selection = log_selection(repo, ix);
    (Some(selection), Task::none())
    } else {
    (None, Task::none())
    };
    (selection, task)
    }
    };
    state.selection = selection;
    task
  • replacement in inflorescence/src/cursor.rs at line 378
    [4.31064][4.31064:31754](),[4.31754][5.6556:6669](),[5.6669][3.9517:9543](),[4.31863][3.9517:9543](),[3.9517][3.9517:9543](),[3.9543][5.6670:6741](),[5.6741][3.10289:10322](),[4.31928][3.10289:10322](),[3.10289][3.10289:10322](),[3.10322][4.31929:32475]()
    // TODO stair
    if let Some(repo) = repo.as_ref() {
    let (selection, task) = match state.selection.take() {
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Untracked);
    (
    Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
    } else {
    Task::none()
    },
    )
    } else if 0 == ix {
    if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    (log_selection(repo, ix), Task::none())
    } else if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    [4.31064]
    [4.32475]
    let Some(repo) = repo.as_ref() else {
    return Task::none();
    };
    let (selection, task) = match state.selection.take() {
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash = file::id_parts_hash(&path, file::Kind::Untracked);
    (
    Selection::UntrackedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
  • replacement in inflorescence/src/cursor.rs at line 401
    [4.32504][4.32504:32730](),[4.32730][2.11641:11663](),[2.11641][2.11641:11663]()
    let ix = repo.untracked_files.len() - 1;
    let selection =
    untracked_file_selection(repo, ix, files);
    (selection, Task::none())
    }
    [4.32504]
    [4.32731]
    Task::none()
    },
    )
    } else if 0 == ix {
    if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    (log_selection(repo, ix), Task::none())
    } else if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
  • replacement in inflorescence/src/cursor.rs at line 413
    [4.32756][4.32756:32793]()
    let ix = ix - 1;
    [4.32756]
    [4.32793]
    let ix = repo.untracked_files.len() - 1;
  • replacement in inflorescence/src/cursor.rs at line 416
    [4.32918][2.11663:11682](),[2.11663][2.11663:11682](),[2.11682][4.32919:33536](),[4.33536][5.6742:6855](),[5.6855][4.33645:33671](),[4.33645][4.33645:33671](),[4.33671][5.6856:6927](),[5.6927][4.33735:34253](),[4.33735][4.33735:34253]()
    };
    (Some(selection), task)
    }
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash =
    file::id_parts_hash(&path, file::Kind::Changed);
    (
    Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
    } else {
    Task::none()
    },
    )
    } else if 0 == ix {
    let selection = if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    untracked_file_selection(repo, ix, files)
    } else if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    log_selection(repo, ix)
    [4.32918]
    [4.34253]
    }
    } else {
    let ix = ix - 1;
    let selection = untracked_file_selection(repo, ix, files);
    (selection, Task::none())
    };
    (Some(selection), task)
    }
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    }) => {
    let (selection, task) = if diff_selected {
    let id_hash = file::id_parts_hash(&path, file::Kind::Changed);
    (
    Selection::ChangedFile {
    ix,
    path,
    diff_selected,
    },
    if let Some(nav) = files_diffs
    .get_mut(&id_hash)
    .and_then(|state| state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
  • replacement in inflorescence/src/cursor.rs at line 443
    [4.34282][4.34282:34478]()
    let ix = repo.changed_files.len() - 1;
    changed_file_selection(repo, ix, files)
    };
    (selection, Task::none())
    [4.34282]
    [4.34478]
    Task::none()
    },
    )
    } else if 0 == ix {
    let selection = if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    untracked_file_selection(repo, ix, files)
    } else if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    log_selection(repo, ix)
  • replacement in inflorescence/src/cursor.rs at line 454
    [4.34503][4.34503:34663]()
    let ix = ix - 1;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    [4.34503]
    [4.34663]
    let ix = repo.changed_files.len() - 1;
    changed_file_selection(repo, ix, files)
  • replacement in inflorescence/src/cursor.rs at line 457
    [4.34682][4.34682:34722](),[4.34722][2.11798:11812](),[2.11798][2.11798:11812](),[2.11812][4.34723:35860](),[4.35860][5.6928:7061](),[5.7061][4.35989:36023](),[4.35989][4.35989:36023](),[4.36023][5.7062:7141](),[5.7141][4.36095:36250](),[4.36095][4.36095:36250](),[4.36250][2.13256:13289](),[2.13256][2.13256:13289](),[2.13289][4.36251:36450]()
    (Some(selection), task)
    }
    Some(Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) => {
    let (selection, task) = match file {
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) => {
    if diff_selected {
    let id_hash = file::log_id_parts_hash(hash, &path);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    },
    if let Some(nav) = logs
    .diffs
    .get_mut(&id_hash)
    .and_then(|diff| diff.state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
    } else {
    Task::none()
    },
    )
    } else {
    let log_entry = repo.log.get(log_ix).unwrap();
    let file_ix = if 0 == file_ix {
    log_entry.file_paths.len() - 1
    [4.34682]
    [4.36450]
    (selection, Task::none())
    } else {
    let ix = ix - 1;
    let selection = changed_file_selection(repo, ix, files);
    (selection, Task::none())
    };
    (Some(selection), task)
    }
    Some(Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file,
    }) => {
    let (selection, task) = match file {
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }) => {
    if diff_selected {
    let id_hash = file::log_id_parts_hash(hash, &path);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    },
    if let Some(nav) = logs
    .diffs
    .get_mut(&id_hash)
    .and_then(|diff| diff.state.nav.as_mut())
    {
    iced_nav_scrollable::scroll_up(nav, delta)
  • replacement in inflorescence/src/cursor.rs at line 497
    [4.36487][4.36487:36562]()
    file_ix - 1
    };
    [4.36487]
    [4.36562]
    Task::none()
    },
    )
    } else {
    let log_entry = repo.log.get(log_ix).unwrap();
  • replacement in inflorescence/src/cursor.rs at line 503
    [4.36563][4.36563:37053](),[4.37053][2.13733:13755](),[2.13733][2.13733:13755](),[2.13755][4.37054:37421](),[4.37421][2.13952:14025](),[2.13952][2.13952:14025](),[2.14025][4.37422:37533](),[4.37533][2.14438:14555](),[2.14438][2.14438:14555](),[2.15013][2.15013:15043]()
    let file = log_file_selection(log_entry, file_ix);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    },
    Task::none(),
    )
    }
    }
    None => {
    let selection = if 0 == log_ix {
    if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    changed_file_selection(repo, ix, files)
    } else if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    untracked_file_selection(repo, ix, files)
    } else {
    let ix = repo.log.len() - 1;
    log_selection(repo, ix)
    }
    [4.36563]
    [2.15043]
    let file_ix = if 0 == file_ix {
    log_entry.file_paths.len() - 1
  • replacement in inflorescence/src/cursor.rs at line 506
    [2.15076][4.37534:37635]()
    let ix = log_ix - 1;
    log_selection(repo, ix)
    [2.15076]
    [2.15443]
    file_ix - 1
  • replacement in inflorescence/src/cursor.rs at line 508
    [2.15470][4.37636:37686]()
    (selection, Task::none())
    [2.15470]
    [2.15518]
    let file = log_file_selection(log_entry, file_ix);
    (
    Selection::LogChange {
    ix: log_ix,
    hash,
    message,
    file: Some(file),
    },
    Task::none(),
    )
  • replacement in inflorescence/src/cursor.rs at line 520
    [2.15540][4.37687:38654]()
    };
    (Some(selection), task)
    }
    None => {
    let (selection, task) = if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    let selection = log_selection(repo, ix);
    (Some(selection), Task::none())
    } else if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    let selection = changed_file_selection(repo, ix, files);
    (Some(selection), Task::none())
    } else if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    let selection = untracked_file_selection(repo, ix, files);
    (Some(selection), Task::none())
    } else {
    (None, Task::none())
    };
    (selection, task)
    }
    };
    [2.15540]
    [4.38654]
    }
    None => {
    let selection = if 0 == log_ix {
    if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    changed_file_selection(repo, ix, files)
    } else if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    untracked_file_selection(repo, ix, files)
    } else {
    let ix = repo.log.len() - 1;
    log_selection(repo, ix)
    }
    } else {
    let ix = log_ix - 1;
    log_selection(repo, ix)
    };
    (selection, Task::none())
    }
    };
    (Some(selection), task)
    }
    None => {
    let (selection, task) = if !repo.log.is_empty() {
    let ix = repo.log.len() - 1;
    let selection = log_selection(repo, ix);
    (Some(selection), Task::none())
    } else if !repo.changed_files.is_empty() {
    let ix = repo.changed_files.len() - 1;
    let selection = changed_file_selection(repo, ix, files);
    (Some(selection), Task::none())
    } else if !repo.untracked_files.is_empty() {
    let ix = repo.untracked_files.len() - 1;
    let selection = untracked_file_selection(repo, ix, files);
    (Some(selection), Task::none())
    } else {
    (None, Task::none())
    };
    (selection, task)
    }
    };
  • replacement in inflorescence/src/cursor.rs at line 562
    [4.38655][4.38655:38739](),[4.38739][6.4165:4171]()
    state.selection = selection;
    task
    } else {
    Task::none()
    }
    [4.38655]
    [6.4171]
    state.selection = selection;
    task
  • replacement in inflorescence/src/cursor.rs at line 699
    [4.38826][4.38826:39120]()
    if let Some(_repo) = repo.as_ref() {
    let selection: Option<Selection> = match state.selection.take() {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    [4.38826]
    [4.39120]
    let Some(_repo) = repo.as_ref() else {
    return Task::none();
    };
    let selection: Option<Selection> = match state.selection.take() {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file:
    Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected,
    }),
    }) => {
    if diff_selected {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
  • replacement in inflorescence/src/cursor.rs at line 722
    [4.39187][4.39187:39226]()
    diff_selected,
    [4.39187]
    [4.39226]
    diff_selected: false,
  • replacement in inflorescence/src/cursor.rs at line 724
    [4.39250][4.39250:39705](),[4.39705][2.15540:15588](),[2.15540][2.15540:15588](),[2.15588][4.39706:39734](),[4.39734][2.15624:15687](),[2.15624][2.15624:15687](),[2.15687][4.39735:39812]()
    }) => {
    if diff_selected {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file: Some(LogChangeFileSelection {
    ix: file_ix,
    path,
    diff_selected: false,
    }),
    })
    } else {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file: None,
    })
    }
    [4.39250]
    [4.39812]
    })
    } else {
    Some(Selection::LogChange {
    ix,
    hash,
    message,
    file: None,
    })
  • replacement in inflorescence/src/cursor.rs at line 733
    [4.39826][4.39826:40621]()
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected: true,
    }) => Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected: false,
    }),
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected: true,
    }) => Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected: false,
    }),
    selection @ (Some(Selection::UntrackedFile { .. })
    | Some(Selection::ChangedFile { .. })
    | Some(Selection::LogChange { file: None, .. })
    | None) => selection,
    };
    state.selection = selection;
    }
    [4.39826]
    [4.40621]
    }
    Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected: true,
    }) => Some(Selection::UntrackedFile {
    ix,
    path,
    diff_selected: false,
    }),
    Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected: true,
    }) => Some(Selection::ChangedFile {
    ix,
    path,
    diff_selected: false,
    }),
    selection @ (Some(Selection::UntrackedFile { .. })
    | Some(Selection::ChangedFile { .. })
    | Some(Selection::LogChange { file: None, .. })
    | None) => selection,
    };
    state.selection = selection;
  • replacement in inflorescence/src/cursor.rs at line 767
    [4.40802][4.40802:40969]()
    if let Some(repo) = repo.as_ref() {
    let (selection, task): (Option<Selection>, Task<M>) = match state
    .selection
    .take()
    {
    [4.40802]
    [4.40969]
    let Some(repo) = repo.as_ref() else {
    return Task::none();
    };
    let (selection, task): (Option<Selection>, Task<M>) =
    match state.selection.take() {
  • replacement in inflorescence/src/cursor.rs at line 900
    [4.45970][4.45970:46054](),[4.46054][5.7142:7148]()
    state.selection = selection;
    task
    } else {
    Task::none()
    }
    [4.45970]
    [5.7148]
    state.selection = selection;
    task