diff options
author | Canop <cano.petrole@gmail.com> | 2021-06-01 13:01:54 +0200 |
---|---|---|
committer | Canop <cano.petrole@gmail.com> | 2021-06-01 13:03:44 +0200 |
commit | f66974936561b95285aabfce0d194d1d574e9f5e (patch) | |
tree | 16fced838dc5c5eb25d6d291306d0a750c6999d1 /src | |
parent | de1bbcac35ac7c6ca736c7917c87f40e824e1a4a (diff) |
compute total staging area size
when show_size has been set to true (for example with :toggle_sizes)
The computation is done in background
Diffstat (limited to 'src')
-rw-r--r-- | src/app/app.rs | 7 | ||||
-rw-r--r-- | src/app/panel.rs | 4 | ||||
-rw-r--r-- | src/app/panel_state.rs | 7 | ||||
-rw-r--r-- | src/browser/browser_state.rs | 2 | ||||
-rw-r--r-- | src/preview/preview_state.rs | 2 | ||||
-rw-r--r-- | src/stage/mod.rs | 2 | ||||
-rw-r--r-- | src/stage/stage.rs | 23 | ||||
-rw-r--r-- | src/stage/stage_state.rs | 78 | ||||
-rw-r--r-- | src/stage/stage_sum.rs | 44 |
9 files changed, 155 insertions, 14 deletions
diff --git a/src/app/app.rs b/src/app/app.rs index fd21e35..c99b71c 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -604,7 +604,7 @@ impl App { con: &AppContext, ) -> Result<(), ProgramError> { while self.has_pending_task() && !dam.has_event() { - if self.do_pending_task(con, dam) { + if self.do_pending_task(app_state, con, dam) { self.update_preview(con); // the selection may have changed let app_cmd_context = AppCmdContext { other_path: self.get_other_panel_path(), @@ -627,13 +627,14 @@ impl App { /// do the next pending task fn do_pending_task( &mut self, + app_state: &AppState, con: &AppContext, dam: &mut Dam, ) -> bool { let screen = self.screen; // we start with the focused panel if self.panel().has_pending_task() { - self.mut_panel().do_pending_task(screen, con, dam); + self.mut_panel().do_pending_task(&app_state.stage, screen, con, dam); return true; } // then the other ones @@ -641,7 +642,7 @@ impl App { if idx != self.active_panel_idx { let panel = &mut self.panels[idx]; if panel.has_pending_task() { - panel.do_pending_task(screen, con, dam); + panel.do_pending_task(&app_state.stage, screen, con, dam); return true; } } diff --git a/src/app/panel.rs b/src/app/panel.rs index 1c9daa5..61cea36 100644 --- a/src/app/panel.rs +++ b/src/app/panel.rs @@ -13,6 +13,7 @@ use { errors::ProgramError, keys, skin::PanelSkin, + stage::*, task_sync::Dam, verb::*, }, @@ -106,11 +107,12 @@ impl Panel { /// in the dam pub fn do_pending_task( &mut self, + stage: &Stage, screen: Screen, con: &AppContext, dam: &mut Dam, ) { - self.mut_state().do_pending_task(screen, con, dam) + self.mut_state().do_pending_task(stage, screen, con, dam) } pub fn has_pending_task(&self) -> bool { diff --git a/src/app/panel_state.rs b/src/app/panel_state.rs index 14acbe1..ff4bee3 100644 --- a/src/app/panel_state.rs +++ b/src/app/panel_state.rs @@ -9,7 +9,7 @@ use { pattern::*, preview::{PreviewMode, PreviewState}, print, - stage::StageState, + stage::*, task_sync::Dam, tree::*, verb::*, @@ -650,6 +650,7 @@ pub trait PanelState { fn do_pending_task( &mut self, + _stage: &Stage, _screen: Screen, _con: &AppContext, _dam: &mut Dam, @@ -658,7 +659,9 @@ pub trait PanelState { unreachable!(); } - fn get_pending_task(&self) -> Option<&'static str> { + fn get_pending_task( + &self, + ) -> Option<&'static str> { None } diff --git a/src/browser/browser_state.rs b/src/browser/browser_state.rs index c40de5e..772ad3c 100644 --- a/src/browser/browser_state.rs +++ b/src/browser/browser_state.rs @@ -9,6 +9,7 @@ use { pattern::*, path::{self, PathAnchor}, print, + stage::*, task_sync::Dam, tree::*, tree_build::TreeBuilder, @@ -488,6 +489,7 @@ impl PanelState for BrowserState { /// Stop as soon as the dam asks for interruption fn do_pending_task( &mut self, + _stage: &Stage, screen: Screen, con: &AppContext, dam: &mut Dam, diff --git a/src/preview/preview_state.rs b/src/preview/preview_state.rs index cb03269..92295a8 100644 --- a/src/preview/preview_state.rs +++ b/src/preview/preview_state.rs @@ -7,6 +7,7 @@ use { errors::ProgramError, flag::Flag, pattern::InputPattern, + stage::*, task_sync::Dam, tree::TreeOptions, verb::*, @@ -143,6 +144,7 @@ impl PanelState for PreviewState { /// do the preview filtering if required and not yet done fn do_pending_task( &mut self, + _stage: &Stage, _screen: Screen, con: &AppContext, dam: &mut Dam, diff --git a/src/stage/mod.rs b/src/stage/mod.rs index e41a4e1..98bcbae 100644 --- a/src/stage/mod.rs +++ b/src/stage/mod.rs @@ -1,9 +1,11 @@ mod filtered_stage; mod stage; mod stage_state; +mod stage_sum; pub use { filtered_stage::*, stage::*, stage_state::*, + stage_sum::*, }; diff --git a/src/stage/stage.rs b/src/stage/stage.rs index be04397..47f1d66 100644 --- a/src/stage/stage.rs +++ b/src/stage/stage.rs @@ -1,4 +1,9 @@ use { + crate::{ + app::AppContext, + file_sum::FileSum, + task_sync::Dam, + }, std::{ path::{Path, PathBuf}, }, @@ -54,7 +59,7 @@ impl Stage { } pub fn clear(&mut self) { self.version += 1; - self.paths.clear() + self.paths.clear(); } pub fn paths(&self) -> &[PathBuf] { &self.paths @@ -73,4 +78,20 @@ impl Stage { pub fn version(&self) -> usize { self.version } + pub fn compute_sum(&self, dam: &Dam, con: &AppContext) -> Option<FileSum> { + let mut sum = FileSum::zero(); + for path in &self.paths { + if path.is_dir() { + let dir_sum = FileSum::from_dir(path, dam, con); + if let Some(dir_sum) = dir_sum { + sum += dir_sum; + } else { + return None; // computation was interrupted + } + } else { + sum += FileSum::from_file(path); + } + } + Some(sum) + } } diff --git a/src/stage/stage_state.rs b/src/stage/stage_state.rs index 4fac8c8..4dc5ed4 100644 --- a/src/stage/stage_state.rs +++ b/src/stage/stage_state.rs @@ -7,6 +7,7 @@ use { errors::ProgramError, pattern::*, skin::*, + task_sync::Dam, tree::*, verb::*, }, @@ -20,6 +21,8 @@ use { }; static TITLE: &str = "Staging Area"; // no wide char allowed here +static COUNT_LABEL: &str = " count: "; +static SIZE_LABEL: &str = " size: "; static ELLIPSIS: char = '…'; pub struct StageState { @@ -28,14 +31,15 @@ pub struct StageState { scroll: usize, - /// those options are only kept for transmission to child state - /// (if they become possible) tree_options: TreeOptions, /// the 'modal' mode mode: Mode, page_height: usize, + + stage_sum: StageSum, + } impl StageState { @@ -55,9 +59,15 @@ impl StageState { tree_options, mode: initial_mode(con), page_height: 0, + stage_sum: StageSum::default(), } } + fn need_sum_computation(&self) -> bool { + self.tree_options.show_sizes && !self.stage_sum.is_up_to_date() + } + + pub fn try_scroll( &mut self, cmd: ScrollCommand, @@ -98,7 +108,40 @@ impl StageState { TITLE, )?; } - cw.repeat(&styles.staging_area_title, &SPACE_FILLING, cw.allowed - count_len)?; + let mut show_count_label = false; + let mut rem = cw.allowed - count_len; + if COUNT_LABEL.len() < rem { + rem -= COUNT_LABEL.len(); + show_count_label = true; + if self.tree_options.show_sizes { + if let Some(sum) = self.stage_sum.computed() { + let size = file_size::fit_4(sum.to_size()); + let size_len = SIZE_LABEL.len() + size.len(); + if size_len < rem { + rem -= size_len; + // we display the size in the middle, so we cut rem in two + let left_rem = rem / 2; + rem -= left_rem; + cw.repeat(&styles.staging_area_title, &SPACE_FILLING, left_rem)?; + cw.queue_g_string( + &styles.staging_area_title, + SIZE_LABEL.to_string(), + )?; + cw.queue_g_string( + &styles.staging_area_title, + size, + )?; + } + } + } + } + cw.repeat(&styles.staging_area_title, &SPACE_FILLING, rem)?; + if show_count_label { + cw.queue_g_string( + &styles.staging_area_title, + COUNT_LABEL.to_string(), + )?; + } if self.filtered_stage.pattern().is_some() { cw.queue_g_string( &styles.char_match, @@ -138,10 +181,6 @@ impl PanelState for StageState { PanelStateType::Stage } - fn get_pending_task(&self) -> Option<&'static str> { - None - } - fn selected_path(&self) -> Option<&Path> { None } @@ -150,6 +189,29 @@ impl PanelState for StageState { None } + fn clear_pending(&mut self) { + self.stage_sum.clear(); + } + fn do_pending_task( + &mut self, + stage: &Stage, + _screen: Screen, + con: &AppContext, + dam: &mut Dam, + // need the stage here + ) { + if self.need_sum_computation() { + self.stage_sum.compute(stage, dam, con); + } + } + fn get_pending_task(&self) -> Option<&'static str> { + if self.need_sum_computation() { + Some("stage size summing") + } else { + None + } + } + fn sel_info<'c>(&'c self, app_state: &'c AppState) -> SelInfo<'c> { match app_state.stage.len() { 0 => SelInfo::None, @@ -192,6 +254,7 @@ impl PanelState for StageState { mode: initial_mode(con), tree_options: new_options, page_height: self.page_height, + stage_sum: self.stage_sum, })) } } @@ -227,6 +290,7 @@ impl PanelState for StageState { disc: &DisplayContext, ) -> Result<(), ProgramError> { let stage = &disc.app_state.stage; + self.stage_sum.see_stage(stage); // this may invalidate the sum if self.filtered_stage.update(stage) { self.fix_scroll(); } diff --git a/src/stage/stage_sum.rs b/src/stage/stage_sum.rs new file mode 100644 index 0000000..da57628 --- /dev/null +++ b/src/stage/stage_sum.rs @@ -0,0 +1,44 @@ +use { + super::*, + crate::{ + app::AppContext, + file_sum::FileSum, + task_sync::Dam, + }, +}; + +#[derive(Clone, Copy, Default)] +pub struct StageSum { + stage_version: usize, + sum: Option<FileSum>, +} + +impl StageSum { + /// invalidates the computed sum if the version at compilation + /// time is older than the current one + pub fn see_stage(&mut self, stage: &Stage) { + if stage.version() != self.stage_version { + self.sum = None; + } + } + pub fn is_up_to_date(&self) -> bool { + self.sum.is_some() + } + pub fn clear(&mut self) { + self.sum = None; + } + pub fn compute(&mut self, stage: &Stage, dam: &Dam, con: &AppContext) -> Option<FileSum> { + if self.stage_version != stage.version() { + self.sum = None; + } + self.stage_version = stage.version(); + if self.sum.is_none() { + // produces None in case of interruption + self.sum = stage.compute_sum(dam, con); + } + self.sum + } + pub fn computed(&self) -> Option<FileSum> { + self.sum + } +} |