summaryrefslogtreecommitdiffstats
path: root/src/options.rs
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2020-04-01 20:31:43 -0400
committerGitHub <noreply@github.com>2020-04-01 20:31:43 -0400
commit0b1d84fdf590bf8cacc5d0f94b67f63daa9b768a (patch)
treed2ff261148f9ef21f2e860af43f795df911c5c79 /src/options.rs
parentc1a19f960fc1b348dd4465fe9a4d698bed229c77 (diff)
Add modularity to widget placement and inclusion (#95)
Diffstat (limited to 'src/options.rs')
-rw-r--r--src/options.rs313
1 files changed, 244 insertions, 69 deletions
diff --git a/src/options.rs b/src/options.rs
index b631f903..96e1e80a 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -1,21 +1,26 @@
use serde::Deserialize;
-
+use std::collections::HashMap;
use std::time::Instant;
use crate::{
- app::{data_harvester, App, AppConfigFields, CpuState, MemState, NetState, WidgetPosition},
+ app::{
+ data_harvester, layout_manager::*, App, AppConfigFields, BasicTableWidgetState, CpuState,
+ CpuWidgetState, DiskState, DiskWidgetState, MemState, MemWidgetState, NetState,
+ NetWidgetState, ProcState, ProcWidgetState, TempState, TempWidgetState,
+ },
constants::*,
utils::error::{self, BottomError},
};
-// use layout_manager::*;
+use layout_options::*;
-// mod layout_manager;
+mod layout_options;
#[derive(Default, Deserialize)]
pub struct Config {
pub flags: Option<ConfigFlags>,
pub colors: Option<ConfigColours>,
+ pub row: Option<Vec<Row>>,
}
#[derive(Default, Deserialize)]
@@ -37,6 +42,8 @@ pub struct ConfigFlags {
pub time_delta: Option<u64>,
pub autohide_time: Option<bool>,
pub hide_time: Option<bool>,
+ pub default_widget_type: Option<String>,
+ pub default_widget_count: Option<u64>,
//disabled_cpu_cores: Option<Vec<u64>>, // TODO: [FEATURE] Enable disabling cores in config/flags
}
@@ -60,27 +67,135 @@ pub struct ConfigColours {
pub graph_color: Option<String>,
}
-pub fn build_app(matches: &clap::ArgMatches<'static>, config: &Config) -> error::Result<App> {
+pub fn build_app(
+ matches: &clap::ArgMatches<'static>, config: &Config, widget_layout: &BottomLayout,
+ default_widget_id: u64,
+) -> error::Result<App> {
let autohide_time = get_autohide_time(&matches, &config);
let default_time_value = get_default_time_value(&matches, &config)?;
- let default_widget = get_default_widget(&matches, &config);
let use_basic_mode = get_use_basic_mode(&matches, &config);
- let current_widget_selected = if use_basic_mode {
- match default_widget {
- WidgetPosition::Cpu => WidgetPosition::BasicCpu,
- WidgetPosition::Network => WidgetPosition::BasicNet,
- WidgetPosition::Mem => WidgetPosition::BasicMem,
- _ => default_widget,
- }
+ // For processes
+ let is_grouped = get_app_grouping(matches, config);
+ let is_case_sensitive = get_app_case_sensitive(matches, config);
+ let is_match_whole_word = get_app_match_whole_word(matches, config);
+ let is_use_regex = get_app_use_regex(matches, config);
+
+ let mut widget_map = HashMap::new();
+ let mut cpu_state_map: HashMap<u64, CpuWidgetState> = HashMap::new();
+ let mut mem_state_map: HashMap<u64, MemWidgetState> = HashMap::new();
+ let mut net_state_map: HashMap<u64, NetWidgetState> = HashMap::new();
+ let mut proc_state_map: HashMap<u64, ProcWidgetState> = HashMap::new();
+ let mut temp_state_map: HashMap<u64, TempWidgetState> = HashMap::new();
+ let mut disk_state_map: HashMap<u64, DiskWidgetState> = HashMap::new();
+
+ let autohide_timer = if autohide_time {
+ Some(Instant::now())
} else {
- default_widget
+ None
};
- let previous_basic_table_selected = if default_widget.is_widget_table() {
- default_widget
+ let (default_widget_type_option, _) = get_default_widget_and_count(matches, config)?;
+ let mut initial_widget_id: u64 = default_widget_id;
+ let mut initial_widget_type = BottomWidgetType::Proc;
+ let is_custom_layout = config.row.is_some();
+
+ for row in &widget_layout.rows {
+ for col in &row.children {
+ for col_row in &col.children {
+ for widget in &col_row.children {
+ widget_map.insert(widget.widget_id, widget.clone());
+ if let Some(default_widget_type) = &default_widget_type_option {
+ if !is_custom_layout || use_basic_mode {
+ match widget.widget_type {
+ BottomWidgetType::BasicCpu => {
+ if let BottomWidgetType::Cpu = *default_widget_type {
+ initial_widget_id = widget.widget_id;
+ initial_widget_type = BottomWidgetType::Cpu;
+ }
+ }
+ BottomWidgetType::BasicMem => {
+ if let BottomWidgetType::Mem = *default_widget_type {
+ initial_widget_id = widget.widget_id;
+ initial_widget_type = BottomWidgetType::Cpu;
+ }
+ }
+ BottomWidgetType::BasicNet => {
+ if let BottomWidgetType::Net = *default_widget_type {
+ initial_widget_id = widget.widget_id;
+ initial_widget_type = BottomWidgetType::Cpu;
+ }
+ }
+ _ => {
+ if *default_widget_type == widget.widget_type {
+ initial_widget_id = widget.widget_id;
+ initial_widget_type = widget.widget_type.clone();
+ }
+ }
+ }
+ }
+ }
+ match widget.widget_type {
+ BottomWidgetType::Cpu => {
+ cpu_state_map.insert(
+ widget.widget_id,
+ CpuWidgetState::init(default_time_value, autohide_timer),
+ );
+ }
+ BottomWidgetType::Mem => {
+ mem_state_map.insert(
+ widget.widget_id,
+ MemWidgetState::init(default_time_value, autohide_timer),
+ );
+ }
+ BottomWidgetType::Net => {
+ net_state_map.insert(
+ widget.widget_id,
+ NetWidgetState::init(default_time_value, autohide_timer),
+ );
+ }
+ BottomWidgetType::Proc => {
+ proc_state_map.insert(
+ widget.widget_id,
+ ProcWidgetState::init(
+ is_case_sensitive,
+ is_match_whole_word,
+ is_use_regex,
+ is_grouped,
+ ),
+ );
+ }
+ BottomWidgetType::Disk => {
+ disk_state_map.insert(widget.widget_id, DiskWidgetState::init());
+ }
+ BottomWidgetType::Temp => {
+ temp_state_map.insert(widget.widget_id, TempWidgetState::init());
+ }
+ _ => {}
+ }
+ }
+ }
+ }
+ }
+
+ // FIXME: [MODULARITY] Don't collect if not added!
+ let basic_table_widget_state = if use_basic_mode {
+ Some(match initial_widget_type {
+ BottomWidgetType::Proc | BottomWidgetType::Disk | BottomWidgetType::Temp => {
+ BasicTableWidgetState {
+ currently_displayed_widget_type: initial_widget_type,
+ currently_displayed_widget_id: initial_widget_id,
+ widget_id: 100,
+ }
+ }
+ _ => BasicTableWidgetState {
+ currently_displayed_widget_type: BottomWidgetType::Proc,
+ currently_displayed_widget_id: DEFAULT_WIDGET_ID,
+ widget_id: 100,
+ },
+ })
} else {
- WidgetPosition::Process
+ None
};
let app_config_fields = AppConfigFields {
@@ -98,22 +213,62 @@ pub fn build_app(matches: &clap::ArgMatches<'static>, config: &Config) -> error:
autohide_time,
};
- let time_now = if autohide_time {
- Some(Instant::now())
- } else {
- None
- };
-
Ok(App::builder()
.app_config_fields(app_config_fields)
- .current_widget_selected(current_widget_selected)
- .previous_basic_table_selected(previous_basic_table_selected)
- .cpu_state(CpuState::init(default_time_value, time_now))
- .mem_state(MemState::init(default_time_value, time_now))
- .net_state(NetState::init(default_time_value, time_now))
+ .cpu_state(CpuState::init(cpu_state_map))
+ .mem_state(MemState::init(mem_state_map))
+ .net_state(NetState::init(net_state_map))
+ .proc_state(ProcState::init(proc_state_map))
+ .disk_state(DiskState::init(disk_state_map))
+ .temp_state(TempState::init(temp_state_map))
+ .basic_table_widget_state(basic_table_widget_state)
+ .current_widget(widget_map.get(&initial_widget_id).unwrap().clone()) // I think the unwrap is fine here
+ .widget_map(widget_map)
.build())
}
+pub fn get_widget_layout(
+ matches: &clap::ArgMatches<'static>, config: &Config,
+) -> error::Result<(BottomLayout, u64)> {
+ let left_legend = get_use_left_legend(matches, config);
+ let (default_widget_type, mut default_widget_count) =
+ get_default_widget_and_count(matches, config)?;
+ let mut default_widget_id = 1;
+
+ let bottom_layout = if get_use_basic_mode(matches, config) {
+ default_widget_id = DEFAULT_WIDGET_ID;
+ BottomLayout::init_basic_default()
+ } else if let Some(rows) = &config.row {
+ let mut iter_id = 0; // A lazy way of forcing unique IDs *shrugs*
+ let mut total_height_ratio = 0;
+
+ let mut ret_bottom_layout = BottomLayout {
+ rows: rows
+ .iter()
+ .map(|row| {
+ row.convert_row_to_bottom_row(
+ &mut iter_id,
+ &mut total_height_ratio,
+ &mut default_widget_id,
+ &default_widget_type,
+ &mut default_widget_count,
+ left_legend,
+ )
+ })
+ .collect::<error::Result<Vec<_>>>()?,
+ total_row_height_ratio: total_height_ratio,
+ };
+ ret_bottom_layout.get_movement_mappings();
+
+ ret_bottom_layout
+ } else {
+ default_widget_id = DEFAULT_WIDGET_ID;
+ BottomLayout::init_default(left_legend)
+ };
+
+ Ok((bottom_layout, default_widget_id))
+}
+
fn get_update_rate_in_milliseconds(
matches: &clap::ArgMatches<'static>, config: &Config,
) -> error::Result<u64> {
@@ -296,56 +451,56 @@ fn get_time_interval(matches: &clap::ArgMatches<'static>, config: &Config) -> er
Ok(time_interval as u64)
}
-pub fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
+pub fn get_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("GROUP_PROCESSES") {
- app.toggle_grouping();
+ return true;
} else if let Some(flags) = &config.flags {
if let Some(grouping) = flags.group_processes {
if grouping {
- app.toggle_grouping();
+ return true;
}
}
}
+ false
}
-pub fn enable_app_case_sensitive(
- matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
-) {
+pub fn get_app_case_sensitive(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("CASE_SENSITIVE") {
- app.process_search_state.search_toggle_ignore_case();
+ return true;
} else if let Some(flags) = &config.flags {
if let Some(case_sensitive) = flags.case_sensitive {
if case_sensitive {
- app.process_search_state.search_toggle_ignore_case();
+ return true;
}
}
}
+ false
}
-pub fn enable_app_match_whole_word(
- matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
-) {
+pub fn get_app_match_whole_word(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("WHOLE_WORD") {
- app.process_search_state.search_toggle_whole_word();
+ return true;
} else if let Some(flags) = &config.flags {
if let Some(whole_word) = flags.whole_word {
if whole_word {
- app.process_search_state.search_toggle_whole_word();
+ return true;
}
}
}
+ false
}
-pub fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
+pub fn get_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("REGEX_DEFAULT") {
- app.process_search_state.search_toggle_regex();
+ return true;
} else if let Some(flags) = &config.flags {
if let Some(regex) = flags.regex {
if regex {
- app.process_search_state.search_toggle_regex();
+ return true;
}
}
}
+ false
}
fn get_hide_time(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
@@ -375,32 +530,52 @@ fn get_autohide_time(matches: &clap::ArgMatches<'static>, config: &Config) -> bo
false
}
-fn get_default_widget(matches: &clap::ArgMatches<'static>, config: &Config) -> WidgetPosition {
- if matches.is_present("CPU_WIDGET") {
- return WidgetPosition::Cpu;
- } else if matches.is_present("MEM_WIDGET") {
- return WidgetPosition::Mem;
- } else if matches.is_present("DISK_WIDGET") {
- return WidgetPosition::Disk;
- } else if matches.is_present("TEMP_WIDGET") {
- return WidgetPosition::Temp;
- } else if matches.is_present("NET_WIDGET") {
- return WidgetPosition::Network;
- } else if matches.is_present("PROC_WIDGET") {
- return WidgetPosition::Process;
+fn get_default_widget_and_count(
+ matches: &clap::ArgMatches<'static>, config: &Config,
+) -> error::Result<(Option<BottomWidgetType>, u64)> {
+ let widget_type = if let Some(widget_type) = matches.value_of("DEFAULT_WIDGET_TYPE") {
+ let parsed_widget = widget_type.parse::<BottomWidgetType>()?;
+ if let BottomWidgetType::Empty = parsed_widget {
+ None
+ } else {
+ Some(parsed_widget)
+ }
} else if let Some(flags) = &config.flags {
- if let Some(default_widget) = &flags.default_widget {
- return match default_widget.as_str() {
- "cpu_default" => WidgetPosition::Cpu,
- "memory_default" => WidgetPosition::Mem,
- "processes_default" => WidgetPosition::Process,
- "network_default" => WidgetPosition::Network,
- "temperature_default" => WidgetPosition::Temp,
- "disk_default" => WidgetPosition::Disk,
- _ => WidgetPosition::Process,
- };
+ if let Some(widget_type) = &flags.default_widget_type {
+ let parsed_widget = widget_type.parse::<BottomWidgetType>()?;
+ if let BottomWidgetType::Empty = parsed_widget {
+ None
+ } else {
+ Some(parsed_widget)
+ }
+ } else {
+ None
}
- }
+ } else {
+ None
+ };
+
+ if widget_type.is_some() {
+ let widget_count = if let Some(widget_count) = matches.value_of("DEFAULT_WIDGET_COUNT") {
+ widget_count.parse::<u128>()?
+ } else if let Some(flags) = &config.flags {
+ if let Some(widget_count) = flags.default_widget_count {
+ widget_count as u128
+ } else {
+ 1 as u128
+ }
+ } else {
+ 1 as u128
+ };
- WidgetPosition::Process
+ if widget_count > std::u64::MAX as u128 {
+ Err(BottomError::InvalidArg(
+ "Please set your widget count to be at most unsigned INT_MAX.".to_string(),
+ ))
+ } else {
+ Ok((widget_type, widget_count as u64))
+ }
+ } else {
+ Ok((None, 1))
+ }
}