Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add nord and nord-light colours #406

Merged
merged 7 commits into from
Feb 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Features

- [#263](https://github.com/ClementTsang/bottom/pull/263): Adds the option for fine-grained kill signals on Unix-like systems.

- [#333](https://github.com/ClementTsang/bottom/pull/333): Adds an "out of" indicator that can be enabled using `--show_table_scroll_position` (and its corresponding config option) to help keep track of scrolled position.

- [#379](https://github.com/ClementTsang/bottom/pull/379): Adds `--process_command` flag and corresponding config option to default to showing a process' command.

- [#381](https://github.com/ClementTsang/bottom/pull/381): Adds a filter in the config file for network interfaces.

## [0.5.8] - Unreleased
- [#406](https://github.com/ClementTsang/bottom/pull/406): Adds the Nord colour scheme, as well as a light variant.

## Changes

Expand Down
50 changes: 25 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -563,31 +563,31 @@ The following options can be set under `[flags]` to achieve the same effect as p

These are the following supported flag config values, which correspond to the flag of the same name described in [Flags](#flags):

| Field | Type | Functionality |
| ---------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
| `left_legend` | Boolean | Puts the CPU chart legend to the left side. |
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
| `group_processes` | Boolean | Groups processes with the same name by default. |
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
| `whole_word` | Boolean | Enables whole-word matching by default. |
| `regex` | Boolean | Enables regex by default. |
| `basic` | Boolean | Hides graphs and uses a more basic look. |
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
| `battery` | Boolean | Shows the battery widget. |
| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. |
| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. |
| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. |
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
| `disable_click` | Boolean | Disables mouse clicks. |
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light"]) | Use a color scheme, use --help for supported values. |
| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. |
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
| `process_command` | Boolean | Show processes as their commands by default. |
| Field | Type | Functionality |
| ---------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `hide_avg_cpu` | Boolean | Hides the average CPU usage. |
| `dot_marker` | Boolean | Uses a dot marker for graphs. |
| `left_legend` | Boolean | Puts the CPU chart legend to the left side. |
| `current_usage` | Boolean | Sets process CPU% to be based on current CPU%. |
| `group_processes` | Boolean | Groups processes with the same name by default. |
| `case_sensitive` | Boolean | Enables case sensitivity by default. |
| `whole_word` | Boolean | Enables whole-word matching by default. |
| `regex` | Boolean | Enables regex by default. |
| `basic` | Boolean | Hides graphs and uses a more basic look. |
| `use_old_network_legend` | Boolean | DEPRECATED - uses the older network legend. |
| `battery` | Boolean | Shows the battery widget. |
| `rate` | Unsigned Int (represents milliseconds) | Sets a refresh rate in ms. |
| `default_time_value` | Unsigned Int (represents milliseconds) | Default time value for graphs in ms. |
| `time_delta` | Unsigned Int (represents milliseconds) | The amount in ms changed upon zooming. |
| `temperature_type` | String (one of ["k", "f", "c", "kelvin", "fahrenheit", "celsius"]) | Sets the temperature unit type. |
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) | Sets the default widget type, use --help for more info. |
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) | Sets the n'th selected widget type as the default. |
| `disable_click` | Boolean | Disables mouse clicks. |
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"]) | Use a color scheme, use --help for supported values. |
| `mem_as_value` | Boolean | Defaults to showing process memory usage by value. |
| `tree` | Boolean | Defaults to showing the process widget in tree mode. |
| `show_table_scroll_position` | Boolean | Shows the scroll position tracker in table widgets. |
| `process_command` | Boolean | Show processes as their commands by default. |

#### Theming

Expand Down
48 changes: 24 additions & 24 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ impl App {
);
}

self.did_config_fail_to_save = self.update_config_file().is_err();
// self.did_config_fail_to_save = self.update_config_file().is_err();
}
}

Expand Down Expand Up @@ -586,7 +586,7 @@ impl App {
);
}

self.did_config_fail_to_save = self.update_config_file().is_err();
// self.did_config_fail_to_save = self.update_config_file().is_err();
}
}

Expand Down Expand Up @@ -642,7 +642,7 @@ impl App {
);
}

self.did_config_fail_to_save = self.update_config_file().is_err();
// self.did_config_fail_to_save = self.update_config_file().is_err();
}
}

Expand Down Expand Up @@ -1565,28 +1565,28 @@ impl App {
self.is_force_redraw = true;
}

/// TODO: Disabled.
/// Call this whenever the config value is updated!
fn update_config_file(&mut self) -> anyhow::Result<()> {
// TODO: Disabled.
// if self.app_config_fields.no_write {
// // debug!("No write enabled. Config will not be written.");
// // Don't write!
// // FIXME: [CONFIG] This should be made VERY clear to the user... make a thing saying "it will not write due to no_write option"
// Ok(())
// } else if let Some(config_path) = &self.config_path {
// // Update
// // debug!("Updating config file - writing to: {:?}", config_path);
// std::fs::File::create(config_path)?
// .write_all(self.config.get_config_as_bytes()?.as_ref())?;
// Ok(())
// } else {
// // FIXME: [CONFIG] Put an actual error message?
// Err(anyhow::anyhow!(
// "Config path was missing, please try restarting bottom..."
// ))
// }
Ok(())
}
// fn update_config_file(&mut self) -> anyhow::Result<()> {
// if self.app_config_fields.no_write {
// // debug!("No write enabled. Config will not be written.");
// // Don't write!
// // FIXME: [CONFIG] This should be made VERY clear to the user... make a thing saying "it will not write due to no_write option"
// Ok(())
// } else if let Some(config_path) = &self.config_path {
// // Update
// // debug!("Updating config file - writing to: {:?}", config_path);
// std::fs::File::create(config_path)?
// .write_all(self.config.get_config_as_bytes()?.as_ref())?;
// Ok(())
// } else {
// // FIXME: [CONFIG] Put an actual error message?
// Err(anyhow::anyhow!(
// "Config path was missing, please try restarting bottom..."
// ))
// }
// Ok(())
// }

pub fn kill_highlighted_process(&mut self) -> Result<()> {
if let BottomWidgetType::Proc = self.current_widget.widget_type {
Expand Down
22 changes: 13 additions & 9 deletions src/app/layout_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,24 @@ pub struct BottomLayout {
pub total_row_height_ratio: u32,
}

type WidgetMappings = (u32, BTreeMap<(u32, u32), u64>);
type ColumnRowMappings = (u32, BTreeMap<(u32, u32), WidgetMappings>);
type ColumnMappings = (u32, BTreeMap<(u32, u32), ColumnRowMappings>);
// Represents a start and end coordinate in some dimension.
type LineSegment = (u32, u32);

type WidgetMappings = (u32, BTreeMap<LineSegment, u64>);
type ColumnRowMappings = (u32, BTreeMap<LineSegment, WidgetMappings>);
type ColumnMappings = (u32, BTreeMap<LineSegment, ColumnRowMappings>);

impl BottomLayout {
pub fn get_movement_mappings(&mut self) {
fn is_intersecting(a: (u32, u32), b: (u32, u32)) -> bool {
#[allow(clippy::suspicious_operation_groupings)] // Have to enable this, clippy really doesn't like me doing this with tuples...
fn is_intersecting(a: LineSegment, b: LineSegment) -> bool {
a.0 >= b.0 && a.1 <= b.1
|| a.1 >= b.1 && a.0 <= b.0
|| a.0 <= b.0 && a.1 >= b.0
|| a.0 >= b.0 && a.0 < b.1 && a.1 >= b.1
}

fn get_distance(target: (u32, u32), candidate: (u32, u32)) -> u32 {
fn get_distance(target: LineSegment, candidate: LineSegment) -> u32 {
if candidate.0 < target.0 {
candidate.1 - target.0
} else if candidate.1 < target.1 {
Expand All @@ -38,20 +42,20 @@ impl BottomLayout {
// Now we need to create the correct mapping for moving from a specific
// widget to another

let mut layout_mapping: BTreeMap<(u32, u32), ColumnMappings> = BTreeMap::new();
let mut layout_mapping: BTreeMap<LineSegment, ColumnMappings> = BTreeMap::new();
let mut total_height = 0;
for row in &self.rows {
let mut row_width = 0;
let mut row_mapping: BTreeMap<(u32, u32), ColumnRowMappings> = BTreeMap::new();
let mut row_mapping: BTreeMap<LineSegment, ColumnRowMappings> = BTreeMap::new();
let mut is_valid_row = false;
for col in &row.children {
let mut col_row_height = 0;
let mut col_mapping: BTreeMap<(u32, u32), WidgetMappings> = BTreeMap::new();
let mut col_mapping: BTreeMap<LineSegment, WidgetMappings> = BTreeMap::new();
let mut is_valid_col = false;

for col_row in &col.children {
let mut widget_width = 0;
let mut col_row_mapping: BTreeMap<(u32, u32), u64> = BTreeMap::new();
let mut col_row_mapping: BTreeMap<LineSegment, u64> = BTreeMap::new();
let mut is_valid_col_row = false;
for widget in &col_row.children {
match widget.widget_type {
Expand Down
6 changes: 5 additions & 1 deletion src/app/process_killer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ impl Process {
}

fn kill(self) -> Result<(), String> {
unsafe { TerminateProcess(self.0, 1) };
let result = unsafe { TerminateProcess(self.0, 1) };
if result == 0 {
return Err("Failed to kill process".to_string());
}

Ok(())
}
}
Expand Down
51 changes: 25 additions & 26 deletions src/app/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,34 +625,33 @@ impl Prefix {
is_ignoring_case,
is_searching_with_regex,
);
} else if let Some((prefix_type, query_content)) = &mut self.regex_prefix {
if let StringQuery::Value(regex_string) = query_content {
match prefix_type {
PrefixType::Pid | PrefixType::Name | PrefixType::State => {
let escaped_regex: String;
let final_regex_string = &format!(
"{}{}{}{}",
if is_searching_whole_word { "^" } else { "" },
if is_ignoring_case { "(?i)" } else { "" },
if !is_searching_with_regex {
escaped_regex = regex::escape(regex_string);
&escaped_regex
} else {
regex_string
},
if is_searching_whole_word { "$" } else { "" },
);

let taken_pwc = self.regex_prefix.take();
if let Some((taken_pt, _)) = taken_pwc {
self.regex_prefix = Some((
taken_pt,
StringQuery::Regex(regex::Regex::new(final_regex_string)?),
));
}
} else if let Some((prefix_type, StringQuery::Value(regex_string))) = &mut self.regex_prefix
{
match prefix_type {
PrefixType::Pid | PrefixType::Name | PrefixType::State => {
let escaped_regex: String;
let final_regex_string = &format!(
"{}{}{}{}",
if is_searching_whole_word { "^" } else { "" },
if is_ignoring_case { "(?i)" } else { "" },
if !is_searching_with_regex {
escaped_regex = regex::escape(regex_string);
&escaped_regex
} else {
regex_string
},
if is_searching_whole_word { "$" } else { "" },
);

let taken_pwc = self.regex_prefix.take();
if let Some((taken_pt, _)) = taken_pwc {
self.regex_prefix = Some((
taken_pt,
StringQuery::Regex(regex::Regex::new(final_regex_string)?),
));
}
_ => {}
}
_ => {}
}
}

Expand Down
Loading