summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorClementTsang <clementjhtsang@gmail.com>2020-02-10 00:16:11 -0500
committerClementTsang <clementjhtsang@gmail.com>2020-02-10 00:16:11 -0500
commit60b6a0911a109018c5825267a1a9905913c47b96 (patch)
tree77fd133ddc416ee346b699f423a94650f82ad1c4 /src
parent7ec52b722be8fbe0804ba9ce2bed9dfd40c73cde (diff)
Major refactoring to appease clippy; potential reintroduction of hjkl keys to navigate widgets...
Diffstat (limited to 'src')
-rw-r--r--src/app.rs26
-rw-r--r--src/app/data_harvester/processes.rs22
-rw-r--r--src/canvas.rs20
-rw-r--r--src/canvas/canvas_colours.rs9
-rw-r--r--src/constants.rs6
-rw-r--r--src/main.rs520
6 files changed, 338 insertions, 265 deletions
diff --git a/src/app.rs b/src/app.rs
index 538a5a81..270aa823 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -426,10 +426,8 @@ impl App {
self.search_state.current_cursor_position -= 1;
}
}
- } else {
- if self.delete_dialog_state.is_showing_dd && !self.delete_dialog_state.is_on_yes {
- self.delete_dialog_state.is_on_yes = true;
- }
+ } else if self.delete_dialog_state.is_showing_dd && !self.delete_dialog_state.is_on_yes {
+ self.delete_dialog_state.is_on_yes = true;
}
}
@@ -442,10 +440,8 @@ impl App {
self.search_state.current_cursor_position += 1;
}
}
- } else {
- if self.delete_dialog_state.is_showing_dd && self.delete_dialog_state.is_on_yes {
- self.delete_dialog_state.is_on_yes = false;
- }
+ } else if self.delete_dialog_state.is_showing_dd && self.delete_dialog_state.is_on_yes {
+ self.delete_dialog_state.is_on_yes = false;
}
}
@@ -615,14 +611,12 @@ impl App {
self.awaiting_second_char = false;
}
}
- } else {
- if self.help_dialog_state.is_showing_help {
- match caught_char {
- '1' => self.help_dialog_state.current_category = AppHelpCategory::General,
- '2' => self.help_dialog_state.current_category = AppHelpCategory::Process,
- '3' => self.help_dialog_state.current_category = AppHelpCategory::Search,
- _ => {}
- }
+ } else if self.help_dialog_state.is_showing_help {
+ match caught_char {
+ '1' => self.help_dialog_state.current_category = AppHelpCategory::General,
+ '2' => self.help_dialog_state.current_category = AppHelpCategory::Process,
+ '3' => self.help_dialog_state.current_category = AppHelpCategory::Search,
+ _ => {}
}
}
}
diff --git a/src/app/data_harvester/processes.rs b/src/app/data_harvester/processes.rs
index 80c81ba2..0092c768 100644
--- a/src/app/data_harvester/processes.rs
+++ b/src/app/data_harvester/processes.rs
@@ -1,5 +1,9 @@
use crate::utils::error;
-use std::{collections::HashMap, process::Command, time::Instant};
+use std::{
+ collections::{hash_map::RandomState, HashMap},
+ process::Command,
+ time::Instant,
+};
use sysinfo::{ProcessExt, System, SystemExt};
#[derive(Clone)]
@@ -111,10 +115,10 @@ fn get_process_cpu_stats(pid: u32) -> std::io::Result<f64> {
}
/// Note that cpu_percentage should be represented WITHOUT the \times 100 factor!
-fn linux_cpu_usage(
+fn linux_cpu_usage<S: core::hash::BuildHasher>(
pid: u32, cpu_usage: f64, cpu_percentage: f64,
- prev_pid_stats: &HashMap<String, (f64, Instant)>,
- new_pid_stats: &mut HashMap<String, (f64, Instant)>, use_current_cpu_total: bool,
+ prev_pid_stats: &HashMap<String, (f64, Instant), S>,
+ new_pid_stats: &mut HashMap<String, (f64, Instant), S>, use_current_cpu_total: bool,
curr_time: &Instant,
) -> std::io::Result<f64> {
// Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556
@@ -145,10 +149,10 @@ fn linux_cpu_usage(
}
}
-fn convert_ps(
+fn convert_ps<S: core::hash::BuildHasher>(
process: &str, cpu_usage: f64, cpu_percentage: f64,
- prev_pid_stats: &HashMap<String, (f64, Instant)>,
- new_pid_stats: &mut HashMap<String, (f64, Instant)>, use_current_cpu_total: bool,
+ prev_pid_stats: &HashMap<String, (f64, Instant), S>,
+ new_pid_stats: &mut HashMap<String, (f64, Instant), S>, use_current_cpu_total: bool,
curr_time: &Instant,
) -> std::io::Result<ProcessHarvest> {
if process.trim().to_string().is_empty() {
@@ -190,7 +194,7 @@ fn convert_ps(
pub fn get_sorted_processes_list(
sys: &System, prev_idle: &mut f64, prev_non_idle: &mut f64,
- prev_pid_stats: &mut HashMap<String, (f64, Instant)>, use_current_cpu_total: bool,
+ prev_pid_stats: &mut HashMap<String, (f64, Instant), RandomState>, use_current_cpu_total: bool,
mem_total_kb: u64, curr_time: &Instant,
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
let mut process_vector: Vec<ProcessHarvest> = Vec::new();
@@ -207,7 +211,7 @@ pub fn get_sorted_processes_list(
if let Ok((cpu_usage, cpu_percentage)) = cpu_calc {
let process_stream = split_string.collect::<Vec<&str>>();
- let mut new_pid_stats: HashMap<String, (f64, Instant)> = HashMap::new();
+ let mut new_pid_stats: HashMap<String, (f64, Instant), RandomState> = HashMap::new();
for process in process_stream {
if let Ok(process_object) = convert_ps(
diff --git a/src/canvas.rs b/src/canvas.rs
index 13fb63e2..c90c9829 100644
--- a/src/canvas.rs
+++ b/src/canvas.rs
@@ -588,7 +588,7 @@ impl Painter {
.header_style(self.colours.table_header_style)
.widths(
&(intrinsic_widths
- .into_iter()
+ .iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
)
@@ -678,7 +678,10 @@ impl Painter {
.y_axis(y_axis)
.datasets(&[
Dataset::default()
- .name("RX")
+ .name(&format!(
+ "RX: {:7}",
+ app_state.canvas_data.rx_display.clone()
+ ))
.marker(if app_state.use_dot {
Marker::Dot
} else {
@@ -687,7 +690,10 @@ impl Painter {
.style(self.colours.rx_style)
.data(&network_data_rx),
Dataset::default()
- .name("TX")
+ .name(&format!(
+ "TX: {:7}",
+ app_state.canvas_data.tx_display.clone()
+ ))
.marker(if app_state.use_dot {
Marker::Dot
} else {
@@ -742,7 +748,7 @@ impl Painter {
.style(self.colours.text_style)
.widths(
&(intrinsic_widths
- .into_iter()
+ .iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
)
@@ -809,7 +815,7 @@ impl Painter {
.header_style(self.colours.table_header_style)
.widths(
&(intrinsic_widths
- .into_iter()
+ .iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
)
@@ -876,7 +882,7 @@ impl Painter {
.header_style(self.colours.table_header_style)
.widths(
&(intrinsic_widths
- .into_iter()
+ .iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
)
@@ -1122,7 +1128,7 @@ impl Painter {
.header_style(self.colours.table_header_style)
.widths(
&(intrinsic_widths
- .into_iter()
+ .iter()
.map(|calculated_width| Constraint::Length(*calculated_width as u16))
.collect::<Vec<_>>()),
)
diff --git a/src/canvas/canvas_colours.rs b/src/canvas/canvas_colours.rs
index 27a4c4f4..4f40f7b4 100644
--- a/src/canvas/canvas_colours.rs
+++ b/src/canvas/canvas_colours.rs
@@ -78,11 +78,14 @@ impl CanvasColours {
self.tx_style = Style::default().fg(convert_hex_to_color(hex)?);
Ok(())
}
- pub fn set_cpu_colours(&mut self, hex_colours: &Vec<String>) -> error::Result<()> {
+ pub fn set_cpu_colours(&mut self, hex_colours: &[String]) -> error::Result<()> {
let max_amount = std::cmp::min(hex_colours.len(), NUM_COLOURS as usize);
- for i in 0..max_amount {
+ for (itx, hex_colour) in hex_colours.iter().enumerate() {
+ if itx >= max_amount {
+ break;
+ }
self.cpu_colour_styles
- .push(Style::default().fg(convert_hex_to_color(&hex_colours[i])?));
+ .push(Style::default().fg(convert_hex_to_color(hex_colour)?));
}
Ok(())
}
diff --git a/src/constants.rs b/src/constants.rs
index d01e63ff..791f3809 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -12,7 +12,7 @@ pub const DEFAULT_UNIX_CONFIG_FILE_PATH: &str = "~/.config/btm/btm.toml";
pub const DEFAULT_WINDOWS_CONFIG_FILE_PATH: &str = "";
// Help text
-pub const GENERAL_HELP_TEXT: [&'static str; 14] = [
+pub const GENERAL_HELP_TEXT: [&str; 14] = [
"General Keybindings\n\n",
"Esc Close dialog box\n",
"q, Ctrl-c Quit bottom\n",
@@ -29,7 +29,7 @@ pub const GENERAL_HELP_TEXT: [&'static str; 14] = [
"G Skip to the last entry of a list\n",
];
-pub const PROCESS_HELP_TEXT: [&'static str; 8] = [
+pub const PROCESS_HELP_TEXT: [&str; 8] = [
"Process Keybindings\n\n",
"dd Kill the highlighted process\n",
"c Sort by CPU usage\n",
@@ -40,7 +40,7 @@ pub const PROCESS_HELP_TEXT: [&'static str; 8] = [
"Ctrl-f, / Open up the search widget\n",
];
-pub const SEARCH_HELP_TEXT: [&'static str; 8] = [
+pub const SEARCH_HELP_TEXT: [&str; 8] = [
"Search Keybindings\n\n",
"Tab Toggle between searching for PID and name.\n",
"Esc Close search widget\n",
diff --git a/src/main.rs b/src/main.rs
index 1ef216d8..40689b38 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -53,13 +53,13 @@ enum ResetEvent {
Reset,
}
-#[derive(Deserialize)]
+#[derive(Default, Deserialize)]
struct Config {
flags: Option<ConfigFlags>,
colors: Option<ConfigColours>,
}
-#[derive(Deserialize)]
+#[derive(Default, Deserialize)]
struct ConfigFlags {
avg_cpu: Option<bool>,
dot_marker: Option<bool>,
@@ -73,7 +73,7 @@ struct ConfigFlags {
regex: Option<bool>,
}
-#[derive(Deserialize)]
+#[derive(Default, Deserialize)]
struct ConfigColours {
table_header_color: Option<String>,
cpu_core_colors: Option<Vec<String>>,
@@ -90,9 +90,8 @@ struct ConfigColours {
graph_color: Option<String>,
}
-fn main() -> error::Result<()> {
- //Parse command line options
- let matches = clap_app!(app =>
+fn get_matches() -> clap::ArgMatches<'static> {
+ clap_app!(app =>
(name: crate_name!())
(version: crate_version!())
(author: crate_authors!())
@@ -114,123 +113,24 @@ fn main() -> error::Result<()> {
(@arg WHOLE_WORD: -W --whole_word "Match whole word when searching by default.")
(@arg REGEX_DEFAULT: -R --regex "Use regex in searching by default.")
)
- .get_matches();
+ .get_matches()
+}
- if cfg!(debug_assertions) {
- utils::logging::init_logger()?;
- }
+fn main() -> error::Result<()> {
+ create_logger()?;
+ let matches = get_matches();
- let config_path = std::path::Path::new(matches.value_of("CONFIG_LOCATION").unwrap_or(
- if cfg!(target_os = "windows") {
- DEFAULT_WINDOWS_CONFIG_FILE_PATH
- } else {
- DEFAULT_UNIX_CONFIG_FILE_PATH
- },
- ));
+ let config: Config = create_config(matches.value_of("CONFIG_LOCATION"))?;
- let config_string = std::fs::read_to_string(config_path);
- let config_toml: Config = if let Ok(config_str) = config_string {
- toml::from_str(&config_str)?
- } else {
- toml::from_str("")?
- };
-
- let update_rate_in_milliseconds: u128 = if matches.is_present("RATE_MILLIS") {
- matches
- .value_of("RATE_MILLIS")
- .unwrap_or(&DEFAULT_REFRESH_RATE_IN_MILLISECONDS.to_string())
- .parse::<u128>()?
- } else if let Some(flags) = &config_toml.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(),
- ));
- }
+ let update_rate_in_milliseconds: u128 =
+ get_update_rate_in_milliseconds(&matches.value_of("RATE_MILLIS"), &config)?;
// Set other settings
- let temperature_type = if matches.is_present("FAHRENHEIT") {
- data_harvester::temperature::TemperatureType::Fahrenheit
- } else if matches.is_present("KELVIN") {
- data_harvester::temperature::TemperatureType::Kelvin
- } else if matches.is_present("CELSIUS") {
- data_harvester::temperature::TemperatureType::Celsius
- } else if let Some(flags) = &config_toml.flags {
- if let Some(temp_type) = &flags.temperature_type {
- // Give lowest priority to config.
- match temp_type.as_str() {
- "fahrenheit" | "f" => data_harvester::temperature::TemperatureType::Fahrenheit,
- "kelvin" | "k" => data_harvester::temperature::TemperatureType::Kelvin,
- "celsius" | "c" => data_harvester::temperature::TemperatureType::Celsius,
- _ => {
- return Err(BottomError::ConfigError(
- "Invalid temperature type. Please have the value be of the form <kelvin|k|celsius|c|fahrenheit|f>".to_string()
- ));
- }
- }
- } else {
- data_harvester::temperature::TemperatureType::Celsius
- }
- } else {
- data_harvester::temperature::TemperatureType::Celsius
- };
- let show_average_cpu = if matches.is_present("AVG_CPU") {
- true
- } else if let Some(flags) = &config_toml.flags {
- if let Some(avg_cpu) = flags.avg_cpu {
- avg_cpu
- } else {
- false
- }
- } else {
- false
- };
- let use_dot = if matches.is_present("DOT_MARKER") {
- true
- } else if let Some(flags) = &config_toml.flags {
- if let Some(dot_marker) = flags.dot_marker {
- dot_marker
- } else {
- false
- }
- } else {
- false
- };
- let left_legend = if matches.is_present("LEFT_LEGEND") {
- true
- } else if let Some(flags) = &config_toml.flags {
- if let Some(left_legend) = flags.left_legend {
- left_legend
- } else {
- false
- }
- } else {
- false
- };
-
- let use_current_cpu_total = if matches.is_present("USE_CURR_USAGE") {
- true
- } else if let Some(flags) = &config_toml.flags {
- if let Some(current_usage) = flags.current_usage {
- current_usage
- } else {
- false
- }
- } else {
- false
- };
+ let temperature_type = get_temperature_option(&matches, &config)?;
+ let show_average_cpu = get_avg_cpu_option(&matches, &config);
+ let use_dot = get_use_dot_option(&matches, &config);
+ let left_legend = get_use_left_legend_option(&matches, &config);
+ let use_current_cpu_total = get_use_current_cpu_total_option(&matches, &config);
// Create "app" struct, which will control most of the program and store settings/state
let mut app = app::App::new(
@@ -242,47 +142,10 @@ fn main() -> error::Result<()> {
use_current_cpu_total,
);
- // Enable grouping immediately if set.
- if matches.is_present("GROUP_PROCESSES") {
- app.toggle_grouping();
- } else if let Some(flags) = &config_toml.flags {
- if let Some(grouping) = flags.group_processes {
- if grouping {
- app.toggle_grouping();
- }
- }
- }
-
- // Set default search method
- if matches.is_present("CASE_SENSITIVE") {
- app.search_state.toggle_ignore_case();
- } else if let Some(flags) = &config_toml.flags {
- if let Some(case_sensitive) = flags.case_sensitive {
- if case_sensitive {
- app.search_state.toggle_ignore_case();
- }
- }
- }
-
- if matches.is_present("WHOLE_WORD") {
- app.search_state.toggle_search_whole_word();
- } else if let Some(flags) = &config_toml.flags {
- if let Some(whole_word) = flags.whole_word {
- if whole_word {
- app.search_state.toggle_search_whole_word();
- }
- }
- }
-
- if matches.is_present("REGEX_DEFAULT") {
- app.search_state.toggle_search_regex();
- } else if let Some(flags) = &config_toml.flags {
- if let Some(regex) = flags.regex {
- if regex {
- app.search_state.toggle_search_regex();
- }
- }
- }
+ enable_app_grouping(&matches, &config, &mut app);
+ enable_app_case_sensitive(&matches, &config, &mut app);
+ enable_app_match_whole_word(&matches, &config, &mut app);
+ enable_app_use_regex(&matches, &config, &mut app);
// Set up up tui and crossterm
let mut stdout_val = stdout();
@@ -299,37 +162,7 @@ fn main() -> error::Result<()> {
// Set up input handling
let (tx, rx) = mpsc::channel();
- {
- let tx = tx.clone();
- thread::spawn(move || loop {
- if poll(Duration::from_millis(20)).is_ok() {
- let mut mouse_timer = Instant::now();
- let mut keyboard_timer = Instant::now();
-
- loop {
- if poll(Duration::from_millis(20)).is_ok() {
- if let Ok(event) = read() {
- if let CEvent::Key(key) = event {
- if Instant::now().duration_since(keyboard_timer).as_millis() >= 20 {
- if tx.send(Event::KeyInput(key)).is_err() {
- return;
- }
- keyboard_timer = Instant::now();
- }
- } else if let CEvent::Mouse(mouse) = event {
- if Instant::now().duration_since(mouse_timer).as_millis() >= 20 {
- if tx.send(Event::MouseInput(mouse)).is_err() {
- return;
- }
- mouse_timer = Instant::now();
- }
- }
- }
- }
- }
- }
- });
- }
+ create_input_thread(tx.clone());
// Cleaning loop
{
@@ -343,33 +176,16 @@ fn main() -> error::Result<()> {
}
// Event loop
let (rtx, rrx) = mpsc::channel();
- {
- let tx = tx;
- let temp_type = app.temperature_type.clone();
- thread::spawn(move || {
- let tx = tx.clone();
- let mut data_state = data_harvester::DataState::default();
- data_state.init();
- data_state.set_temperature_type(temp_type);
- data_state.set_use_current_cpu_total(use_current_cpu_total);
- loop {
- if let Ok(message) = rrx.try_recv() {
- match message {
- ResetEvent::Reset => {
- data_state.data.first_run_cleanup();
- }
- }
- }
- futures::executor::block_on(data_state.update_data());
- let event = Event::Update(Box::from(data_state.data.clone()));
- tx.send(event).unwrap();
- thread::sleep(Duration::from_millis(update_rate_in_milliseconds as u64));
- }
- });
- }
+ create_event_thread(
+ tx,
+ rrx,
+ use_current_cpu_total,
+ update_rate_in_milliseconds as u64,
+ app.temperature_type.clone(),
+ );
let mut painter = canvas::Painter::default();
- if let Err(config_check) = generate_config_colours(&config_toml, &mut painter) {
+ if let Err(config_check) = generate_config_colours(&config, &mut painter) {
cleanup_terminal(&mut terminal)?;
return Err(config_check);
}
@@ -409,10 +225,10 @@ fn main() -> error::Result<()> {
match event.code {
KeyCode::Char('c') => break,
KeyCode::Char('f') => app.enable_searching(),
- KeyCode::Left => app.move_left(),
- KeyCode::Right => app.move_right(),
- KeyCode::Up => app.move_up(),
- KeyCode::Down => app.move_down(),
+ KeyCode::Left | KeyCode::Char('h') => app.move_left(),
+ KeyCode::Right | KeyCode::Char('l') => app.move_right(),
+ KeyCode::Up | KeyCode::Char('k') => app.move_up(),
+ KeyCode::Down | KeyCode::Char('j') => app.move_down(),
KeyCode::Char('r') => {
if rtx.send(ResetEvent::Reset).is_ok() {
app.reset();
@@ -424,10 +240,19 @@ fn main() -> error::Result<()> {
}
} else if let KeyModifiers::SHIFT = event.modifiers {
match event.code {
- KeyCode::Left => app.move_left(),
- KeyCode::Right => app.move_right(),
- KeyCode::Up => app.move_up(),
- KeyCode::Down => app.move_down(),
+ KeyCode::Left | KeyCode::Char('h') | KeyCode::Char('H') => {
+ app.move_left()
+ }
+ KeyCode::Right | KeyCode::Char('l') | KeyCode::Char('L') => {
+ app.move_right()
+ }
+ KeyCode::Up | KeyCode::Char('k') | KeyCode::Char('K') => {
+ app.move_up()
+ }
+ KeyCode::Down | KeyCode::Char('j') | KeyCode::Char('J') => {
+ app.move_down()
+ }
+ KeyCode::Char('/') | KeyCode::Char('?') => app.on_char_key('?'),
_ => {}
}
} else if let KeyModifiers::ALT = event.modifiers {
@@ -525,6 +350,189 @@ fn main() -> error::Result<()> {
Ok(())
}
+fn create_logger() -> error::Result<()> {
+ if cfg!(debug_assertions) {
+ utils::logging::init_logger()?;
+ }
+ Ok(())
+}
+
+fn create_config(flag_config_location: Option<&str>) -> error::Result<Config> {
+ let config_path = std::path::Path::new(flag_config_location.unwrap_or(
+ if cfg!(target_os = "windows") {
+ DEFAULT_WINDOWS_CONFIG_FILE_PATH
+ } else {
+ DEFAULT_UNIX_CONFIG_FILE_PATH
+ },
+ ));
+
+ if let Ok(config_str) = std::fs::read_to_string(config_path) {
+ Ok(toml::from_str(config_str.as_str())?)
+ } else {
+ Ok(Config::default())
+ }
+}
+
+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.
+ match temp_type.as_str() {
+ "fahrenheit" | "f" => {
+ return Ok(data_harvester::temperature::TemperatureType::Fahrenheit);
+ }
+ "kelvin" | "k" => {
+ return Ok(data_harvester::temperature::TemperatureType::Kelvin);
+ }
+ "celsius" | "c" => {
+ return Ok(data_harvester::temperature::TemperatureType::Celsius);
+ }
+ _ => {
+ return 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 enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::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::App,
+) {
+ if matches.is_present("CASE_SENSITIVE") {
+ app.search_state.toggle_ignore_case();
+ } else if let Some(flags) = &config.flags {
+ if let Some(case_sensitive) = flags.case_sensitive {
+ if case_sensitive {
+ app.search_state.toggle_ignore_case();
+ }
+ }
+ }
+}
+
+fn enable_app_match_whole_word(
+ matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App,
+) {
+ if matches.is_present("WHOLE_WORD") {
+ app.search_state.toggle_search_whole_word();
+ } else if let Some(flags) = &config.flags {
+ if let Some(whole_word) = flags.whole_word {
+ if whole_word {
+ app.search_state.toggle_search_whole_word();
+ }
+ }
+ }
+}
+
+fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App) {
+ if matches.is_present("REGEX_DEFAULT") {
+ app.search_state.toggle_search_regex();
+ } else if let Some(flags) = &config.flags {
+ if let Some(regex) = flags.regex {
+ if regex {
+ app.search_state.toggle_search_regex();
+ }
+ }
+ }
+}
+
fn try_drawing(
terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>,
app: &mut app::App, painter: &mut canvas::Painter,
@@ -549,10 +557,8 @@ fn cleanup_terminal(
Ok(())
}
-fn generate_config_colours(
- config_toml: &Config, painter: &mut canvas::Painter,
-) -> error::Result<()> {
- if let Some(colours) = &config_toml.colors {
+fn generate_config_colours(config: &Config, painter: &mut canvas::Painter) -> error::Result<()> {
+ if let Some(colours) = &config.colors {
if let Some(border_color) = &colours.border_color {
painter.colours.set_border_colour(border_color)?;
}
@@ -720,3 +726,63 @@ fn sort_process_data(to_sort_vec: &mut Vec<ConvertedProcessData>, app: &app::App
}
}
}
+
+fn create_input_thread(
+ tx: std::sync::mpsc::Sender<Event<crossterm::event::KeyEvent, crossterm::event::MouseEvent>>,
+) {
+ thread::spawn(move || loop {
+ if poll(Duration::from_millis(20)).is_ok() {
+ let mut mouse_timer = Instant::now();
+ let mut keyboard_timer = Instant::now();
+
+ loop {
+ if poll(Duration::from_millis(20)).is_ok() {
+ if let Ok(event) = read() {
+ if let CEvent::Key(key) = event {
+ if Instant::now().duration_since(keyboard_timer).as_millis() >= 20 {
+ if tx.send(Event::KeyInput(key)).is_err() {
+ return;
+ }
+ keyboard_timer = Instant::now();
+ }
+ } else if let CEvent::Mouse(mouse) = event {
+ if Instant::now().duration_since(mouse_timer).as_millis() >= 20 {
+ if tx.send(Event::MouseInput(mouse)).is_err() {
+ return;
+ }
+ mouse_timer = Instant::now();
+ }
+ }
+ }
+ }
+ }
+ }
+ });
+}
+
+fn create_event_thread(
+ tx: std::sync::mpsc::Sender<Event<crossterm::event::KeyEvent, crossterm::event::MouseEvent>>,
+ rrx: std::sync::mpsc::Receiver<ResetEvent>, use_current_cpu_total: bool,
+ update_rate_in_milliseconds: u64, temp_type: data_harvester::temperature::TemperatureType,
+) {
+ thread::spawn(move || {
+ let tx = tx.clone();
+ let mut data_state = data_harvester::DataState::default();
+ data_state.init();
+ data_state.set_temperature_type(temp_type);
+ data_state.set_use_current_cpu_total(use_current_cpu_total);
+ loop {
+ if let Ok(message) = rrx.try_recv() {
+ match message {
+ ResetEvent::Reset => {
+ data_state.data.first_run_cleanup();
+ }
+ }
+ }
+ futures::executor::block_on(data_state.update_data());
+ let event = Event::Update(Box::from(data_state.data.clone()));
+ tx.send(event).unwrap();
+ thread::sleep(Duration::from_millis(update_rate_in_milliseconds));
+ }
+ });
+}