refactor stairs
[?]
Jul 15, 2025, 4:06 PM
AI3IMKC3HRPMTWQCU5HGWKUHGKTJ22QF7V4AAEI6IEBIZ4WYWCKQCDependencies
- [2]
L6KSEFQImove cursor related stuff into its module - [3]
BFN2VHZSrefactor file stuff into sub-mod - [4]
KWTBNTO3diffs selection and scrolling - [5]
5MUEECMJsmooth scrolling nav - [6]
3TLPJ57Balt scroll via context and couple fixes - [7]
YKHE3XMWrefactor diffs handling - [8]
4PNWU55Oreplace the circular hor navigation - [9]
BNHJU2DUclippy fixes - [10]
KQABQCCZupdate rust to 1.88 - [*]
WT3GA27Padd 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 stairif 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())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
let ix = 0;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())}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
let ix = ix + 1;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())}} 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
let ix = 0;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())}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
let ix = ix + 1;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();}} 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
let file_ix =if log_entry.file_paths.len().saturating_sub(1)== file_ix{0} else {file_ix + 1};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
let file = log_file_selection(log_entry, file_ix);let file = log_file_selection(log_entry, file_ix); - replacement in inflorescence/src/cursor.rs at line 314
(Selection::LogChange {ix: log_ix,hash,message,file: Some(file),},Task::none(),)}(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)}}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
let ix = log_ix + 1;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));}} else {let ix = log_ix + 1;log_selection(repo, ix)}; - replacement in inflorescence/src/cursor.rs at line 343
} 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()}}};(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 stairif 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())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
let ix = repo.untracked_files.len() - 1;let selection =untracked_file_selection(repo, ix, files);(selection, Task::none())}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
let ix = ix - 1;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)}} 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
let ix = repo.changed_files.len() - 1;changed_file_selection(repo, ix, files)};(selection, Task::none())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
let ix = ix - 1;let selection = changed_file_selection(repo, ix, files);(selection, Task::none())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(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
file_ix - 1};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)}let file_ix = if 0 == file_ix {log_entry.file_paths.len() - 1 - replacement in inflorescence/src/cursor.rs at line 506
let ix = log_ix - 1;log_selection(repo, ix)file_ix - 1 - replacement in inflorescence/src/cursor.rs at line 508
(selection, Task::none())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
};(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)}};}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
state.selection = selection;task} else {Task::none()}state.selection = selection;task - replacement in inflorescence/src/cursor.rs at line 699
if let Some(_repo) = repo.as_ref() {let selection: Option<Selection> = match state.selection.take() {Some(Selection::LogChange {ix,hash,message,file:Some(LogChangeFileSelection {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
diff_selected,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,})}})} else {Some(Selection::LogChange {ix,hash,message,file: None,}) - replacement in inflorescence/src/cursor.rs at line 733
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;}}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
if let Some(repo) = repo.as_ref() {let (selection, task): (Option<Selection>, Task<M>) = match state.selection.take(){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
state.selection = selection;task} else {Task::none()}state.selection = selection;task