mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-26 06:00:21 +00:00
feature: Add mem_as_value flag (#309)
Adds a new flag, --mem_as_value (and its corresponding config option, mem_as_value = true), which defaults to showing process memory values by their amount rather than percentage.
This commit is contained in:
parent
c0a8c347e1
commit
92636f3bf9
8 changed files with 186 additions and 22 deletions
|
@ -31,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- [#296](https://github.com/ClementTsang/bottom/pull/296): Built-in colour themes.
|
- [#296](https://github.com/ClementTsang/bottom/pull/296): Built-in colour themes.
|
||||||
|
|
||||||
|
- [#309](https://github.com/ClementTsang/bottom/pull/309): Adds a `mem_as_value` flag to default displaying process memory as value rather than percentage.
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
- [#213](https://github.com/ClementTsang/bottom/pull/213), [#214](https://github.com/ClementTsang/bottom/pull/214): Updated help descriptions, added auto-complete generation.
|
- [#213](https://github.com/ClementTsang/bottom/pull/213), [#214](https://github.com/ClementTsang/bottom/pull/214): Updated help descriptions, added auto-complete generation.
|
||||||
|
|
|
@ -233,6 +233,7 @@ Run using `btm`.
|
||||||
--hide_time Completely hides the time scaling.
|
--hide_time Completely hides the time scaling.
|
||||||
-k, --kelvin Sets the temperature type to Kelvin.
|
-k, --kelvin Sets the temperature type to Kelvin.
|
||||||
-l, --left_legend Puts the CPU chart legend to the left side.
|
-l, --left_legend Puts the CPU chart legend to the left side.
|
||||||
|
--mem_as_value Defaults to showing process memory usage by value.
|
||||||
-r, --rate <MS> Sets a refresh rate in ms.
|
-r, --rate <MS> Sets a refresh rate in ms.
|
||||||
-R, --regex Enables regex by default.
|
-R, --regex Enables regex by default.
|
||||||
-d, --time_delta <MS> The amount in ms changed upon zooming.
|
-d, --time_delta <MS> The amount in ms changed upon zooming.
|
||||||
|
@ -547,6 +548,7 @@ These are the following supported flag config values, which correspond to the fl
|
||||||
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) |
|
| `default_widget_count` | Unsigned Int (represents which `default_widget_type`) |
|
||||||
| `disable_click` | Boolean |
|
| `disable_click` | Boolean |
|
||||||
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light"]) |
|
| `color` | String (one of ["default", "default-light", "gruvbox", "gruvbox-light"]) |
|
||||||
|
| `mem_as_value` | Boolean |
|
||||||
|
|
||||||
#### Theming
|
#### Theming
|
||||||
|
|
||||||
|
|
37
src/app.rs
37
src/app.rs
|
@ -1,4 +1,5 @@
|
||||||
use std::{collections::HashMap, io::Write, path::PathBuf, time::Instant};
|
// use std::io::Write;
|
||||||
|
use std::{collections::HashMap, path::PathBuf, time::Instant};
|
||||||
|
|
||||||
use unicode_segmentation::GraphemeCursor;
|
use unicode_segmentation::GraphemeCursor;
|
||||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||||
|
@ -1405,23 +1406,25 @@ impl App {
|
||||||
|
|
||||||
/// Call this whenever the config value is updated!
|
/// Call this whenever the config value is updated!
|
||||||
fn update_config_file(&mut self) -> anyhow::Result<()> {
|
fn update_config_file(&mut self) -> anyhow::Result<()> {
|
||||||
if self.app_config_fields.no_write {
|
// TODO: Disabled.
|
||||||
// debug!("No write enabled. Config will not be written.");
|
// if self.app_config_fields.no_write {
|
||||||
// Don't write!
|
// // debug!("No write enabled. Config will not be written.");
|
||||||
// FIXME: [CONFIG] This should be made VERY clear to the user... make a thing saying "it will not write due to no_write option"
|
// // 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(())
|
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..."
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill_highlighted_process(&mut self) -> Result<()> {
|
pub fn kill_highlighted_process(&mut self) -> Result<()> {
|
||||||
|
|
|
@ -391,6 +391,7 @@ pub struct ProcWidgetState {
|
||||||
impl ProcWidgetState {
|
impl ProcWidgetState {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
is_case_sensitive: bool, is_match_whole_word: bool, is_use_regex: bool, is_grouped: bool,
|
is_case_sensitive: bool, is_match_whole_word: bool, is_use_regex: bool, is_grouped: bool,
|
||||||
|
show_memory_as_values: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut process_search_state = ProcessSearchState::default();
|
let mut process_search_state = ProcessSearchState::default();
|
||||||
if is_case_sensitive {
|
if is_case_sensitive {
|
||||||
|
@ -410,9 +411,15 @@ impl ProcWidgetState {
|
||||||
let mut columns = ProcColumn::default();
|
let mut columns = ProcColumn::default();
|
||||||
columns.set_to_sorted_index(&process_sorting_type);
|
columns.set_to_sorted_index(&process_sorting_type);
|
||||||
if is_grouped {
|
if is_grouped {
|
||||||
|
// Normally defaults to showing by PID, toggle count on instead.
|
||||||
columns.toggle(&ProcessSorting::Count);
|
columns.toggle(&ProcessSorting::Count);
|
||||||
columns.toggle(&ProcessSorting::Pid);
|
columns.toggle(&ProcessSorting::Pid);
|
||||||
}
|
}
|
||||||
|
if show_memory_as_values {
|
||||||
|
// Normally defaults to showing by percent, toggle value on instead.
|
||||||
|
columns.toggle(&ProcessSorting::Mem);
|
||||||
|
columns.toggle(&ProcessSorting::MemPercent);
|
||||||
|
}
|
||||||
|
|
||||||
ProcWidgetState {
|
ProcWidgetState {
|
||||||
process_search_state,
|
process_search_state,
|
||||||
|
|
|
@ -227,6 +227,13 @@ Defaults to \"default\".
|
||||||
"nord",
|
"nord",
|
||||||
])
|
])
|
||||||
.hide_possible_values(true);
|
.hide_possible_values(true);
|
||||||
|
let mem_as_value = Arg::with_name("mem_as_value")
|
||||||
|
.long("mem_as_value")
|
||||||
|
.help("Defaults to showing process memory usage by value.")
|
||||||
|
.long_help(
|
||||||
|
"\
|
||||||
|
Defaults to showing process memory usage by value. Otherwise, it defaults to showing it by percentage.\n\n",
|
||||||
|
);
|
||||||
let default_time_value = Arg::with_name("default_time_value")
|
let default_time_value = Arg::with_name("default_time_value")
|
||||||
.short("t")
|
.short("t")
|
||||||
.long("default_time_value")
|
.long("default_time_value")
|
||||||
|
@ -345,6 +352,7 @@ The minimum is 1s (1000), and defaults to 15s (15000).\n\n\n",
|
||||||
.arg(config_location)
|
.arg(config_location)
|
||||||
.arg(color)
|
.arg(color)
|
||||||
.arg(debug)
|
.arg(debug)
|
||||||
|
.arg(mem_as_value)
|
||||||
.arg(default_time_value)
|
.arg(default_time_value)
|
||||||
.arg(default_widget_count)
|
.arg(default_widget_count)
|
||||||
.arg(default_widget_type)
|
.arg(default_widget_type)
|
||||||
|
|
130
src/constants.rs
130
src/constants.rs
|
@ -365,9 +365,133 @@ pub const DEFAULT_BATTERY_LAYOUT: &str = r##"
|
||||||
// Config and flags
|
// Config and flags
|
||||||
pub const DEFAULT_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";
|
pub const DEFAULT_CONFIG_FILE_PATH: &str = "bottom/bottom.toml";
|
||||||
|
|
||||||
pub const CONFIG_TOP_HEAD: &str = r##"# This is bottom's config file. Values in this config file will change when changed in the
|
pub const OLD_CONFIG_TEXT: &str = r##"# This is a default config file for bottom. All of the settings are commented
|
||||||
# interface. You can also manually change these values. Be aware that contents of this file will be overwritten if something is
|
# out by default; if you wish to change them uncomment and modify as you see
|
||||||
# changed in the application; you can disable writing via the --no_write flag or no_write config option.
|
# fit.
|
||||||
|
|
||||||
|
# This group of options represents a command-line flag/option. Flags explicitly
|
||||||
|
# added when running (ie: btm -a) will override this config file if an option
|
||||||
|
# is also set here.
|
||||||
|
[flags]
|
||||||
|
# Whether to hide the average cpu entry.
|
||||||
|
#hide_avg_cpu = false
|
||||||
|
# Whether to use dot markers rather than braille.
|
||||||
|
#dot_marker = false
|
||||||
|
# The update rate of the application.
|
||||||
|
#rate = 1000
|
||||||
|
# Whether to put the CPU legend to the left.
|
||||||
|
#left_legend = false
|
||||||
|
# Whether to set CPU% on a process to be based on the total CPU or just current usage.
|
||||||
|
#current_usage = false
|
||||||
|
# Whether to group processes with the same name together by default.
|
||||||
|
#group_processes = false
|
||||||
|
# Whether to make process searching case sensitive by default.
|
||||||
|
#case_sensitive = false
|
||||||
|
# Whether to make process searching look for matching the entire word by default.
|
||||||
|
#whole_word = false
|
||||||
|
# Whether to make process searching use regex by default.
|
||||||
|
#regex = false
|
||||||
|
# Defaults to Celsius. Temperature is one of:
|
||||||
|
#temperature_type = "k"
|
||||||
|
#temperature_type = "f"
|
||||||
|
#temperature_type = "c"
|
||||||
|
#temperature_type = "kelvin"
|
||||||
|
#temperature_type = "fahrenheit"
|
||||||
|
#temperature_type = "celsius"
|
||||||
|
# The default time interval (in milliseconds).
|
||||||
|
#default_time_value = 60000
|
||||||
|
# The time delta on each zoom in/out action (in milliseconds).
|
||||||
|
#time_delta = 15000
|
||||||
|
# Override layout default widget
|
||||||
|
#default_widget_type = "proc"
|
||||||
|
#default_widget_count = 1
|
||||||
|
# Use basic mode
|
||||||
|
#basic = false
|
||||||
|
# Use the old network legend style
|
||||||
|
#use_old_network_legend = false
|
||||||
|
# Remove space in tables
|
||||||
|
#hide_table_gap = false
|
||||||
|
# Disable mouse clicks
|
||||||
|
#disable_click = false
|
||||||
|
# Built-in themes. Valid values are "default", "default-light", "gruvbox", "gruvbox-light"
|
||||||
|
#color = "default"
|
||||||
|
# Show memory values in the processes widget as values by default
|
||||||
|
# mem_as_value = false
|
||||||
|
|
||||||
|
# These are all the components that support custom theming. Note that colour support
|
||||||
|
# will depend on terminal support.
|
||||||
|
[colors]
|
||||||
|
# Represents the colour of table headers (processes, CPU, disks, temperature).
|
||||||
|
#table_header_color="LightBlue"
|
||||||
|
# Represents the colour of the label each widget has.
|
||||||
|
#widget_title_color="Gray"
|
||||||
|
# Represents the average CPU color.
|
||||||
|
#avg_cpu_color="Red"
|
||||||
|
# Represents the colour the core will use in the CPU legend and graph.
|
||||||
|
#cpu_core_colors=["LightMagenta", "LightYellow", "LightCyan", "LightGreen", "LightBlue", "LightRed", "Cyan", "Green", "Blue", "Red"]
|
||||||
|
# Represents the colour RAM will use in the memory legend and graph.
|
||||||
|
#ram_color="LightMagenta"
|
||||||
|
# Represents the colour SWAP will use in the memory legend and graph.
|
||||||
|
#swap_color="LightYellow"
|
||||||
|
# Represents the colour rx will use in the network legend and graph.
|
||||||
|
#rx_color="LightCyan"
|
||||||
|
# Represents the colour tx will use in the network legend and graph.
|
||||||
|
#tx_color="LightGreen"
|
||||||
|
# Represents the colour of the border of unselected widgets.
|
||||||
|
#border_color="Gray"
|
||||||
|
# Represents the colour of the border of selected widgets.
|
||||||
|
#highlighted_border_color="LightBlue"
|
||||||
|
# Represents the colour of most text.
|
||||||
|
#text_color="Gray"
|
||||||
|
# Represents the colour of text that is selected.
|
||||||
|
#selected_text_color="Black"
|
||||||
|
# Represents the background colour of text that is selected.
|
||||||
|
#selected_bg_color="LightBlue"
|
||||||
|
# Represents the colour of the lines and text of the graph.
|
||||||
|
#graph_color="Gray"
|
||||||
|
# Represents the colours of the battery based on charge
|
||||||
|
#high_battery_color="green"
|
||||||
|
#medium_battery_color="yellow"
|
||||||
|
#low_battery_color="red"
|
||||||
|
|
||||||
|
# Layout - layouts follow a pattern like this:
|
||||||
|
# [[row]] represents a row in the application.
|
||||||
|
# [[row.child]] represents either a widget or a column.
|
||||||
|
# [[row.child.child]] represents a widget.
|
||||||
|
#
|
||||||
|
# All widgets must have the type value set to one of ["cpu", "mem", "proc", "net", "temp", "disk", "empty"].
|
||||||
|
# All layout components have a ratio value - if this is not set, then it defaults to 1.
|
||||||
|
# The default widget layout:
|
||||||
|
#[[row]]
|
||||||
|
# ratio=30
|
||||||
|
# [[row.child]]
|
||||||
|
# type="cpu"
|
||||||
|
#[[row]]
|
||||||
|
# ratio=40
|
||||||
|
# [[row.child]]
|
||||||
|
# ratio=4
|
||||||
|
# type="mem"
|
||||||
|
# [[row.child]]
|
||||||
|
# ratio=3
|
||||||
|
# [[row.child.child]]
|
||||||
|
# type="temp"
|
||||||
|
# [[row.child.child]]
|
||||||
|
# type="disk"
|
||||||
|
#[[row]]
|
||||||
|
# ratio=30
|
||||||
|
# [[row.child]]
|
||||||
|
# type="net"
|
||||||
|
# [[row.child]]
|
||||||
|
# type="proc"
|
||||||
|
# default=true
|
||||||
|
"##;
|
||||||
|
|
||||||
|
pub const CONFIG_TOP_HEAD: &str = r##"# This is bottom's config file.
|
||||||
|
# Values in this config file will change when changed in the interface.
|
||||||
|
# You can also manually change these values.
|
||||||
|
# Be aware that contents of this file will be overwritten if something is
|
||||||
|
# changed in the application; you can disable writing via the
|
||||||
|
# --no_write flag or no_write config option.
|
||||||
|
|
||||||
"##;
|
"##;
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,8 @@ pub fn create_or_get_config(config_path: &Option<PathBuf>) -> error::Result<Conf
|
||||||
if let Some(parent_path) = path.parent() {
|
if let Some(parent_path) = path.parent() {
|
||||||
fs::create_dir_all(parent_path)?;
|
fs::create_dir_all(parent_path)?;
|
||||||
}
|
}
|
||||||
fs::File::create(path)?.write_all(CONFIG_TOP_HEAD.as_bytes())?;
|
// fs::File::create(path)?.write_all(CONFIG_TOP_HEAD.as_bytes())?;
|
||||||
|
fs::File::create(path)?.write_all(OLD_CONFIG_TEXT.as_bytes())?;
|
||||||
Ok(Config::default())
|
Ok(Config::default())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -141,6 +141,9 @@ pub struct ConfigFlags {
|
||||||
|
|
||||||
#[builder(default, setter(strip_option))]
|
#[builder(default, setter(strip_option))]
|
||||||
pub search_regex_enabled_widgets: Option<Vec<WidgetIdEnabled>>,
|
pub search_regex_enabled_widgets: Option<Vec<WidgetIdEnabled>>,
|
||||||
|
|
||||||
|
#[builder(default, setter(strip_option))]
|
||||||
|
pub mem_as_value: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
|
||||||
|
@ -231,6 +234,8 @@ pub fn build_app(
|
||||||
let is_custom_layout = config.row.is_some();
|
let is_custom_layout = config.row.is_some();
|
||||||
let mut used_widget_set = HashSet::new();
|
let mut used_widget_set = HashSet::new();
|
||||||
|
|
||||||
|
let show_memory_as_values = get_mem_as_value(matches, config);
|
||||||
|
|
||||||
for row in &widget_layout.rows {
|
for row in &widget_layout.rows {
|
||||||
for col in &row.children {
|
for col in &row.children {
|
||||||
for col_row in &col.children {
|
for col_row in &col.children {
|
||||||
|
@ -296,6 +301,7 @@ pub fn build_app(
|
||||||
is_match_whole_word,
|
is_match_whole_word,
|
||||||
is_use_regex,
|
is_use_regex,
|
||||||
is_grouped,
|
is_grouped,
|
||||||
|
show_memory_as_values,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -920,3 +926,14 @@ pub fn get_color_scheme(
|
||||||
// And lastly, the final case is just "default".
|
// And lastly, the final case is just "default".
|
||||||
Ok(ColourScheme::Default)
|
Ok(ColourScheme::Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_mem_as_value(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||||
|
if matches.is_present("mem_as_value") {
|
||||||
|
return true;
|
||||||
|
} else if let Some(flags) = &config.flags {
|
||||||
|
if let Some(mem_as_value) = flags.mem_as_value {
|
||||||
|
return mem_as_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue