summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorCanop <cano.petrole@gmail.com>2021-06-01 13:01:54 +0200
committerCanop <cano.petrole@gmail.com>2021-06-01 13:03:44 +0200
commitf66974936561b95285aabfce0d194d1d574e9f5e (patch)
tree16fced838dc5c5eb25d6d291306d0a750c6999d1 /src
parentde1bbcac35ac7c6ca736c7917c87f40e824e1a4a (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.rs7
-rw-r--r--src/app/panel.rs4
-rw-r--r--src/app/panel_state.rs7
-rw-r--r--src/browser/browser_state.rs2
-rw-r--r--src/preview/preview_state.rs2
-rw-r--r--src/stage/mod.rs2
-rw-r--r--src/stage/stage.rs23
-rw-r--r--src/stage/stage_state.rs78
-rw-r--r--src/stage/stage_sum.rs44
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
+ }
+}