Refactoring.

This commit is contained in:
ClementTsang 2020-02-29 17:05:01 -05:00
parent ff43799037
commit eb2622467f
21 changed files with 4958 additions and 4939 deletions

View File

@ -300,7 +300,7 @@ impl App {
left_legend,
use_current_cpu_total,
show_disabled_data,
use_basic_mode
use_basic_mode,
},
is_expanded: false,
is_resized: false,
@ -712,8 +712,7 @@ impl App {
pub fn on_up_key(&mut self) {
if !self.is_in_dialog() {
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
} else {
if let WidgetPosition::ProcessSearch = self.current_widget_selected {} else {
self.decrement_position_count();
}
}
@ -721,8 +720,7 @@ impl App {
pub fn on_down_key(&mut self) {
if !self.is_in_dialog() {
if let WidgetPosition::ProcessSearch = self.current_widget_selected {
} else {
if let WidgetPosition::ProcessSearch = self.current_widget_selected {} else {
self.increment_position_count();
}
}

View File

@ -37,15 +37,13 @@ pub async fn get_temperature_data(
temperature: match temp_type {
TemperatureType::Celsius => sensor
.current()
.get::<thermodynamic_temperature::degree_celsius>(
),
.get::<thermodynamic_temperature::degree_celsius>(),
TemperatureType::Kelvin => {
sensor.current().get::<thermodynamic_temperature::kelvin>()
}
TemperatureType::Fahrenheit => sensor
.current()
.get::<thermodynamic_temperature::degree_fahrenheit>(
),
.get::<thermodynamic_temperature::degree_fahrenheit>(),
},
});
}

View File

@ -73,9 +73,12 @@ pub struct DisplayableData {
pub network_data_tx: Vec<(f64, f64)>,
pub disk_data: Vec<Vec<String>>,
pub temp_sensor_data: Vec<Vec<String>>,
pub process_data: HashMap<u32, ProcessHarvest>, // Not the final value
pub grouped_process_data: Vec<ConvertedProcessData>, // Not the final value
pub finalized_process_data: Vec<ConvertedProcessData>, // What's actually displayed
pub process_data: HashMap<u32, ProcessHarvest>,
// Not the final value
pub grouped_process_data: Vec<ConvertedProcessData>,
// Not the final value
pub finalized_process_data: Vec<ConvertedProcessData>,
// What's actually displayed
pub mem_label: String,
pub swap_label: String,
pub mem_data: Vec<(f64, f64)>,

View File

@ -4,7 +4,8 @@ use tui::style::{Color, Style};
use crate::utils::{error, gen_util::*};
const GOLDEN_RATIO: f32 = 0.618_034; // Approx, good enough for use (also Clippy gets mad if it's too long)
const GOLDEN_RATIO: f32 = 0.618_034;
// Approx, good enough for use (also Clippy gets mad if it's too long)
pub const STANDARD_FIRST_COLOUR: Color = Color::LightMagenta;
pub const STANDARD_SECOND_COLOUR: Color = Color::LightYellow;
pub const STANDARD_THIRD_COLOUR: Color = Color::LightCyan;

View File

@ -1,6 +1,8 @@
pub const STALE_MAX_MILLISECONDS: u128 = 60 * 1000; // How long to store data.
pub const STALE_MAX_MILLISECONDS: u128 = 60 * 1000;
// How long to store data.
pub const TIME_STARTS_FROM: u64 = 60 * 1000;
pub const TICK_RATE_IN_MILLISECONDS: u64 = 200; // How fast the screen refreshes
pub const TICK_RATE_IN_MILLISECONDS: u64 = 200;
// How fast the screen refreshes
pub const DEFAULT_REFRESH_RATE_IN_MILLISECONDS: u128 = 1000;
pub const MAX_KEY_TIMEOUT_IN_MILLISECONDS: u128 = 1000;
pub const NUM_COLOURS: i32 = 256;

View File

@ -20,35 +20,39 @@ use std::{
use crossterm::{
event::{
poll, read, DisableMouseCapture, EnableMouseCapture, Event as CEvent, KeyCode, KeyEvent,
KeyModifiers, MouseEvent,
DisableMouseCapture, EnableMouseCapture, Event as CEvent, KeyCode, KeyEvent, KeyModifiers, MouseEvent,
poll, read,
},
execute,
style::Print,
terminal::LeaveAlternateScreen,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen},
terminal::LeaveAlternateScreen,
};
use serde::Deserialize;
use tui::{backend::CrosstermBackend, Terminal};
use app::{
data_harvester::{self, processes::ProcessSorting},
App,
data_harvester::{self, processes::ProcessSorting},
};
use constants::*;
use data_conversion::*;
use utils::error::{self, BottomError};
use options::*;
use utils::error::{self};
pub mod app;
mod utils {
pub mod error;
pub mod gen_util;
pub mod logging;
}
mod canvas;
mod constants;
mod data_conversion;
pub mod options;
enum Event<I, J> {
KeyInput(I),
MouseInput(J),
@ -60,50 +64,6 @@ enum ResetEvent {
Reset,
}
#[derive(Default, Deserialize)]
struct Config {
flags: Option<ConfigFlags>,
colors: Option<ConfigColours>,
}
#[derive(Default, Deserialize)]
struct ConfigFlags {
avg_cpu: Option<bool>,
dot_marker: Option<bool>,
temperature_type: Option<String>,
rate: Option<u64>,
left_legend: Option<bool>,
current_usage: Option<bool>,
group_processes: Option<bool>,
case_sensitive: Option<bool>,
whole_word: Option<bool>,
regex: Option<bool>,
default_widget: Option<String>,
show_disabled_data: Option<bool>,
basic_mode: Option<bool>,
//disabled_cpu_cores: Option<Vec<u64>>, // TODO: [FEATURE] Enable disabling cores in config/flags
}
#[derive(Default, Deserialize)]
struct ConfigColours {
table_header_color: Option<String>,
avg_cpu_color: Option<String>,
cpu_core_colors: Option<Vec<String>>,
ram_color: Option<String>,
swap_color: Option<String>,
rx_color: Option<String>,
tx_color: Option<String>,
rx_total_color: Option<String>,
tx_total_color: Option<String>,
border_color: Option<String>,
highlighted_border_color: Option<String>,
text_color: Option<String>,
selected_text_color: Option<String>,
selected_bg_color: Option<String>,
widget_title_color: Option<String>,
graph_color: Option<String>,
}
fn get_matches() -> clap::ArgMatches<'static> {
clap_app!(app =>
(name: crate_name!())
@ -457,230 +417,6 @@ fn create_config(flag_config_location: Option<&str>) -> error::Result<Config> {
}
}
fn get_update_rate_in_milliseconds(
update_rate: &Option<&str>, config: &Config,
) -> error::Result<u128> {
let update_rate_in_milliseconds = if let Some(update_rate) = update_rate {
update_rate.parse::<u128>()?
} else if let Some(flags) = &config.flags {
if let Some(rate) = flags.rate {
rate as u128
} else {
constants::DEFAULT_REFRESH_RATE_IN_MILLISECONDS
}
} else {
constants::DEFAULT_REFRESH_RATE_IN_MILLISECONDS
};
if update_rate_in_milliseconds < 250 {
return Err(BottomError::InvalidArg(
"Please set your update rate to be greater than 250 milliseconds.".to_string(),
));
} else if update_rate_in_milliseconds > u128::from(std::u64::MAX) {
return Err(BottomError::InvalidArg(
"Please set your update rate to be less than unsigned INT_MAX.".to_string(),
));
}
Ok(update_rate_in_milliseconds)
}
fn get_temperature_option(
matches: &clap::ArgMatches<'static>, config: &Config,
) -> error::Result<data_harvester::temperature::TemperatureType> {
if matches.is_present("FAHRENHEIT") {
return Ok(data_harvester::temperature::TemperatureType::Fahrenheit);
} else if matches.is_present("KELVIN") {
return Ok(data_harvester::temperature::TemperatureType::Kelvin);
} else if matches.is_present("CELSIUS") {
return Ok(data_harvester::temperature::TemperatureType::Celsius);
} else if let Some(flags) = &config.flags {
if let Some(temp_type) = &flags.temperature_type {
// Give lowest priority to config.
return match temp_type.as_str() {
"fahrenheit" | "f" => {
Ok(data_harvester::temperature::TemperatureType::Fahrenheit)
}
"kelvin" | "k" => {
Ok(data_harvester::temperature::TemperatureType::Kelvin)
}
"celsius" | "c" => {
Ok(data_harvester::temperature::TemperatureType::Celsius)
}
_ => {
Err(BottomError::ConfigError(
"Invalid temperature type. Please have the value be of the form <kelvin|k|celsius|c|fahrenheit|f>".to_string()
))
}
};
}
}
Ok(data_harvester::temperature::TemperatureType::Celsius)
}
fn get_avg_cpu_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("AVG_CPU") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(avg_cpu) = flags.avg_cpu {
return avg_cpu;
}
}
false
}
fn get_use_dot_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("DOT_MARKER") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(dot_marker) = flags.dot_marker {
return dot_marker;
}
}
false
}
fn get_use_left_legend_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("LEFT_LEGEND") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(left_legend) = flags.left_legend {
return left_legend;
}
}
false
}
fn get_use_current_cpu_total_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("USE_CURR_USAGE") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(current_usage) = flags.current_usage {
return current_usage;
}
}
false
}
fn get_show_disabled_data_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("SHOW_DISABLED_DATA") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(show_disabled_data) = flags.show_disabled_data {
return show_disabled_data;
}
}
false
}
fn get_use_basic_mode_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("BASIC_MODE") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(basic_mode) = flags.basic_mode {
return basic_mode;
}
}
false
}
fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("GROUP_PROCESSES") {
app.toggle_grouping();
} else if let Some(flags) = &config.flags {
if let Some(grouping) = flags.group_processes {
if grouping {
app.toggle_grouping();
}
}
}
}
fn enable_app_case_sensitive(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("CASE_SENSITIVE") {
app.process_search_state.search_toggle_ignore_case();
} 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();
}
}
}
}
fn enable_app_match_whole_word(
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
) {
if matches.is_present("WHOLE_WORD") {
app.process_search_state.search_toggle_whole_word();
} 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();
}
}
}
}
fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("REGEX_DEFAULT") {
app.process_search_state.search_toggle_regex();
} else if let Some(flags) = &config.flags {
if let Some(regex) = flags.regex {
if regex {
app.process_search_state.search_toggle_regex();
}
}
}
}
fn get_default_widget(matches: &clap::ArgMatches<'static>, config: &Config) -> app::WidgetPosition {
if matches.is_present("CPU_WIDGET") {
return app::WidgetPosition::Cpu;
} else if matches.is_present("MEM_WIDGET") {
return app::WidgetPosition::Mem;
} else if matches.is_present("DISK_WIDGET") {
return app::WidgetPosition::Disk;
} else if matches.is_present("TEMP_WIDGET") {
return app::WidgetPosition::Temp;
} else if matches.is_present("NET_WIDGET") {
return app::WidgetPosition::Network;
} else if matches.is_present("PROC_WIDGET") {
return app::WidgetPosition::Process;
} else if let Some(flags) = &config.flags {
if let Some(default_widget) = &flags.default_widget {
match default_widget.as_str() {
"cpu_default" => {
return app::WidgetPosition::Cpu;
}
"memory_default" => {
return app::WidgetPosition::Mem;
}
"processes_default" => {
return app::WidgetPosition::Process;
}
"network_default" => {
return app::WidgetPosition::Network;
}
"temperature_default" => {
return app::WidgetPosition::Temp;
}
"disk_default" => {
return app::WidgetPosition::Disk;
}
_ => {}
}
}
}
app::WidgetPosition::Process
}
fn try_drawing(
terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>,
app: &mut App, painter: &mut canvas::Painter,

281
src/options.rs Normal file
View File

@ -0,0 +1,281 @@
use serde::Deserialize;
use crate::{
app::{self, App, data_harvester},
constants::*,
utils::error::{self, BottomError},
};
#[derive(Default, Deserialize)]
pub struct Config {
pub flags: Option<ConfigFlags>,
pub colors: Option<ConfigColours>,
}
#[derive(Default, Deserialize)]
pub struct ConfigFlags {
pub avg_cpu: Option<bool>,
pub dot_marker: Option<bool>,
pub temperature_type: Option<String>,
pub rate: Option<u64>,
pub left_legend: Option<bool>,
pub current_usage: Option<bool>,
pub group_processes: Option<bool>,
pub case_sensitive: Option<bool>,
pub whole_word: Option<bool>,
pub regex: Option<bool>,
pub default_widget: Option<String>,
pub show_disabled_data: Option<bool>,
pub basic_mode: Option<bool>,
//disabled_cpu_cores: Option<Vec<u64>>, // TODO: [FEATURE] Enable disabling cores in config/flags
}
#[derive(Default, Deserialize)]
pub struct ConfigColours {
pub table_header_color: Option<String>,
pub avg_cpu_color: Option<String>,
pub cpu_core_colors: Option<Vec<String>>,
pub ram_color: Option<String>,
pub swap_color: Option<String>,
pub rx_color: Option<String>,
pub tx_color: Option<String>,
pub rx_total_color: Option<String>,
pub tx_total_color: Option<String>,
pub border_color: Option<String>,
pub highlighted_border_color: Option<String>,
pub text_color: Option<String>,
pub selected_text_color: Option<String>,
pub selected_bg_color: Option<String>,
pub widget_title_color: Option<String>,
pub graph_color: Option<String>,
}
pub fn get_update_rate_in_milliseconds(
update_rate: &Option<&str>, config: &Config,
) -> error::Result<u128> {
let update_rate_in_milliseconds = if let Some(update_rate) = update_rate {
update_rate.parse::<u128>()?
} else if let Some(flags) = &config.flags {
if let Some(rate) = flags.rate {
rate as u128
} else {
DEFAULT_REFRESH_RATE_IN_MILLISECONDS
}
} else {
DEFAULT_REFRESH_RATE_IN_MILLISECONDS
};
if update_rate_in_milliseconds < 250 {
return Err(BottomError::InvalidArg(
"Please set your update rate to be greater than 250 milliseconds.".to_string(),
));
} else if update_rate_in_milliseconds > u128::from(std::u64::MAX) {
return Err(BottomError::InvalidArg(
"Please set your update rate to be less than unsigned INT_MAX.".to_string(),
));
}
Ok(update_rate_in_milliseconds)
}
pub fn get_temperature_option(
matches: &clap::ArgMatches<'static>, config: &Config,
) -> error::Result<data_harvester::temperature::TemperatureType> {
if matches.is_present("FAHRENHEIT") {
return Ok(data_harvester::temperature::TemperatureType::Fahrenheit);
} else if matches.is_present("KELVIN") {
return Ok(data_harvester::temperature::TemperatureType::Kelvin);
} else if matches.is_present("CELSIUS") {
return Ok(data_harvester::temperature::TemperatureType::Celsius);
} else if let Some(flags) = &config.flags {
if let Some(temp_type) = &flags.temperature_type {
// Give lowest priority to config.
return match temp_type.as_str() {
"fahrenheit" | "f" => {
Ok(data_harvester::temperature::TemperatureType::Fahrenheit)
}
"kelvin" | "k" => {
Ok(data_harvester::temperature::TemperatureType::Kelvin)
}
"celsius" | "c" => {
Ok(data_harvester::temperature::TemperatureType::Celsius)
}
_ => {
Err(BottomError::ConfigError(
"Invalid temperature type. Please have the value be of the form <kelvin|k|celsius|c|fahrenheit|f>".to_string()
))
}
};
}
}
Ok(data_harvester::temperature::TemperatureType::Celsius)
}
pub fn get_avg_cpu_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("AVG_CPU") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(avg_cpu) = flags.avg_cpu {
return avg_cpu;
}
}
false
}
pub fn get_use_dot_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("DOT_MARKER") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(dot_marker) = flags.dot_marker {
return dot_marker;
}
}
false
}
pub fn get_use_left_legend_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("LEFT_LEGEND") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(left_legend) = flags.left_legend {
return left_legend;
}
}
false
}
pub fn get_use_current_cpu_total_option(
matches: &clap::ArgMatches<'static>, config: &Config,
) -> bool {
if matches.is_present("USE_CURR_USAGE") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(current_usage) = flags.current_usage {
return current_usage;
}
}
false
}
pub fn get_show_disabled_data_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("SHOW_DISABLED_DATA") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(show_disabled_data) = flags.show_disabled_data {
return show_disabled_data;
}
}
false
}
pub fn get_use_basic_mode_option(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
if matches.is_present("BASIC_MODE") {
return true;
} else if let Some(flags) = &config.flags {
if let Some(basic_mode) = flags.basic_mode {
return basic_mode;
}
}
false
}
pub fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("GROUP_PROCESSES") {
app.toggle_grouping();
} else if let Some(flags) = &config.flags {
if let Some(grouping) = flags.group_processes {
if grouping {
app.toggle_grouping();
}
}
}
}
pub fn enable_app_case_sensitive(
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
) {
if matches.is_present("CASE_SENSITIVE") {
app.process_search_state.search_toggle_ignore_case();
} 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();
}
}
}
}
pub fn enable_app_match_whole_word(
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
) {
if matches.is_present("WHOLE_WORD") {
app.process_search_state.search_toggle_whole_word();
} 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();
}
}
}
}
pub fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("REGEX_DEFAULT") {
app.process_search_state.search_toggle_regex();
} else if let Some(flags) = &config.flags {
if let Some(regex) = flags.regex {
if regex {
app.process_search_state.search_toggle_regex();
}
}
}
}
pub fn get_default_widget(
matches: &clap::ArgMatches<'static>, config: &Config,
) -> app::WidgetPosition {
if matches.is_present("CPU_WIDGET") {
return app::WidgetPosition::Cpu;
} else if matches.is_present("MEM_WIDGET") {
return app::WidgetPosition::Mem;
} else if matches.is_present("DISK_WIDGET") {
return app::WidgetPosition::Disk;
} else if matches.is_present("TEMP_WIDGET") {
return app::WidgetPosition::Temp;
} else if matches.is_present("NET_WIDGET") {
return app::WidgetPosition::Network;
} else if matches.is_present("PROC_WIDGET") {
return app::WidgetPosition::Process;
} else if let Some(flags) = &config.flags {
if let Some(default_widget) = &flags.default_widget {
match default_widget.as_str() {
"cpu_default" => {
return app::WidgetPosition::Cpu;
}
"memory_default" => {
return app::WidgetPosition::Mem;
}
"processes_default" => {
return app::WidgetPosition::Process;
}
"network_default" => {
return app::WidgetPosition::Network;
}
"temperature_default" => {
return app::WidgetPosition::Temp;
}
"disk_default" => {
return app::WidgetPosition::Disk;
}
_ => {}
}
}
}
app::WidgetPosition::Process
}