summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Wonjoon <lyuha@users.noreply.github.com>2024-04-02 05:06:01 +0000
committerGitHub <noreply@github.com>2024-04-02 01:06:01 -0400
commita083ec00dd4e74c29bb96bd7c9b0e9cec1cd22b3 (patch)
tree43299d972046f64d8ea4afb8e9d7157ad7cd6d28
parent2ee0df1502925e1a5cae75f543110233006ef743 (diff)
feature: Add option to set a position of legend (#1430)
* Add option to set a position of legend * some small changes --------- Co-authored-by: ClementTsang <34804052+ClementTsang@users.noreply.github.com>
-rw-r--r--docs/content/configuration/command-line-options.md2
-rw-r--r--docs/content/configuration/config-file/flags.md72
-rw-r--r--src/app.rs3
-rw-r--r--src/canvas/components/time_graph.rs9
-rw-r--r--src/canvas/components/tui_widget/time_chart.rs23
-rw-r--r--src/canvas/widgets/cpu_graph.rs1
-rw-r--r--src/canvas/widgets/mem_graph.rs1
-rw-r--r--src/canvas/widgets/network_graph.rs1
-rw-r--r--src/constants.rs6
-rw-r--r--src/options.rs49
-rw-r--r--src/options/args.rs41
-rw-r--r--src/options/config.rs2
12 files changed, 169 insertions, 41 deletions
diff --git a/docs/content/configuration/command-line-options.md b/docs/content/configuration/command-line-options.md
index 2ce134b4..e0c6286b 100644
--- a/docs/content/configuration/command-line-options.md
+++ b/docs/content/configuration/command-line-options.md
@@ -58,6 +58,7 @@ see information on these options by running `btm -h`, or run `btm --help` to dis
| ----------------------- | --------------------------------------------------------- |
| `--enable_cache_memory` | Enable collecting and displaying cache and buffer memory. |
| `--mem_as_value` | Defaults to showing process memory usage by value. |
+| `--memory_legend` | Where to place the legend for the memory widget. |
## Network Options
@@ -66,6 +67,7 @@ see information on these options by running `btm -h`, or run `btm --help` to dis
| `--network_use_binary_prefix` | Displays the network widget with binary prefixes. |
| `--network_use_bytes` | Displays the network widget using bytes. |
| `--network_use_log` | Displays the network widget with a log scale. |
+| `--network_legend` | Where to place the legend for the network widget. |
| `--use_old_network_legend` | DEPRECATED - uses a separate network legend. |
## Battery Options
diff --git a/docs/content/configuration/config-file/flags.md b/docs/content/configuration/config-file/flags.md
index c110af6d..f8bacfbb 100644
--- a/docs/content/configuration/config-file/flags.md
+++ b/docs/content/configuration/config-file/flags.md
@@ -7,38 +7,40 @@
Most of the [command line flags](../command-line-options.md) have config file equivalents to avoid having to type them out
each time:
-| 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) or String (represents human time) | Sets a refresh rate in ms. |
-| `default_time_value` | Unsigned Int (represents milliseconds) or String (represents human time) | Default time value for graphs in ms. |
-| `time_delta` | Unsigned Int (represents milliseconds) or String (represents human time) | The amount in ms changed upon zooming. |
-| `hide_time` | Boolean | Hides the time scale. |
-| `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. |
-| `enable_cache_memory` | Boolean | Enable collecting and displaying cache and buffer memory (not available on Windows). |
-| `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. |
-| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. |
-| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. |
-| `network_use_bytes` | Boolean | Displays the network widget using bytes. |
-| `network_use_log` | Boolean | Displays the network widget with a log scale. |
-| `enable_gpu` | Boolean | Shows the GPU widgets. |
-| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. |
-| `unnormalized_cpu` | Boolean | Show process CPU% without normalizing over the number of cores. |
-| `expanded_on_startup` | Boolean | Expand the default widget upon starting the app. |
+| 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) or String (represents human time) | Sets a refresh rate in ms. |
+| `default_time_value` | Unsigned Int (represents milliseconds) or String (represents human time) | Default time value for graphs in ms. |
+| `time_delta` | Unsigned Int (represents milliseconds) or String (represents human time) | The amount in ms changed upon zooming. |
+| `hide_time` | Boolean | Hides the time scale. |
+| `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. |
+| `enable_cache_memory` | Boolean | Enable cache and buffer memory stats (not available on Windows). |
+| `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. |
+| `disable_advanced_kill` | Boolean | Hides advanced options to stop a process on Unix-like systems. |
+| `network_use_binary_prefix` | Boolean | Displays the network widget with binary prefixes. |
+| `network_use_bytes` | Boolean | Displays the network widget using bytes. |
+| `network_use_log` | Boolean | Displays the network widget with a log scale. |
+| `enable_gpu` | Boolean | Shows the GPU widgets. |
+| `retention` | String (human readable time, such as "10m", "1h", etc.) | How much data is stored at once in terms of time. |
+| `unnormalized_cpu` | Boolean | Show process CPU% without normalizing over the number of cores. |
+| `expanded_on_startup` | Boolean | Expand the default widget upon starting the app. |
+| `memory_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the memory widget. |
+| `network_legend` | String (one of ["none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right"]) | Where to place the legend for the network widget. |
diff --git a/src/app.rs b/src/app.rs
index a149869f..60ad35b8 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -21,6 +21,7 @@ pub use states::*;
use unicode_segmentation::{GraphemeCursor, UnicodeSegmentation};
use crate::{
+ canvas::components::time_chart::LegendPosition,
constants,
data_collection::temperature,
data_conversion::ConvertedData,
@@ -62,8 +63,10 @@ pub struct AppConfigFields {
pub enable_cache_memory: bool,
pub show_table_scroll_position: bool,
pub is_advanced_kill: bool,
+ pub memory_legend_position: Option<LegendPosition>,
// TODO: Remove these, move network details state-side.
pub network_unit_type: DataUnit,
+ pub network_legend_position: Option<LegendPosition>,
pub network_scale_type: AxisScaling,
pub network_use_binary_prefix: bool,
pub retention_ms: u64,
diff --git a/src/canvas/components/time_graph.rs b/src/canvas/components/time_graph.rs
index 3f438349..361b502e 100644
--- a/src/canvas/components/time_graph.rs
+++ b/src/canvas/components/time_graph.rs
@@ -11,7 +11,9 @@ use tui::{
};
use unicode_segmentation::UnicodeSegmentation;
-use super::time_chart::{Axis, Dataset, Point, TimeChart, DEFAULT_LEGEND_CONSTRAINTS};
+use super::time_chart::{
+ Axis, Dataset, LegendPosition, Point, TimeChart, DEFAULT_LEGEND_CONSTRAINTS,
+};
/// Represents the data required by the [`TimeGraph`].
pub struct GraphData<'a> {
@@ -48,6 +50,9 @@ pub struct TimeGraph<'a> {
/// The title style.
pub title_style: Style,
+ /// The legend position.
+ pub legend_position: Option<LegendPosition>,
+
/// Any legend constraints.
pub legend_constraints: Option<(Constraint, Constraint)>,
@@ -142,6 +147,7 @@ impl<'a> TimeGraph<'a> {
.y_axis(y_axis)
.marker(self.marker)
.legend_style(self.graph_style)
+ .legend_position(self.legend_position)
.hidden_legend_constraints(
self.legend_constraints
.unwrap_or(DEFAULT_LEGEND_CONSTRAINTS),
@@ -202,6 +208,7 @@ mod test {
border_style: Style::default().fg(Color::Blue),
is_expanded: false,
title_style: Style::default().fg(Color::Cyan),
+ legend_position: None,
legend_constraints: None,
marker: Marker::Braille,
}
diff --git a/src/canvas/components/tui_widget/time_chart.rs b/src/canvas/components/tui_widget/time_chart.rs
index 60c797bc..04f491bc 100644
--- a/src/canvas/components/tui_widget/time_chart.rs
+++ b/src/canvas/components/tui_widget/time_chart.rs
@@ -7,7 +7,7 @@
mod canvas;
mod points;
-use std::cmp::max;
+use std::{cmp::max, str::FromStr};
use canvas::*;
use tui::{
@@ -213,6 +213,27 @@ impl LegendPosition {
}
}
+#[derive(Debug, PartialEq)]
+pub struct ParseLegendPositionError;
+
+impl FromStr for LegendPosition {
+ type Err = ParseLegendPositionError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s.to_ascii_lowercase().as_str() {
+ "top" => Ok(Self::Top),
+ "top-left" => Ok(Self::TopLeft),
+ "top-right" => Ok(Self::TopRight),
+ "left" => Ok(Self::Left),
+ "right" => Ok(Self::Right),
+ "bottom-left" => Ok(Self::BottomLeft),
+ "bottom" => Ok(Self::Bottom),
+ "bottom-right" => Ok(Self::BottomRight),
+ _ => Err(ParseLegendPositionError),
+ }
+ }
+}
+
/// A group of data points
///
/// This is the main element composing a [`TimeChart`].
diff --git a/src/canvas/widgets/cpu_graph.rs b/src/canvas/widgets/cpu_graph.rs
index b5027bc6..f882b210 100644
--- a/src/canvas/widgets/cpu_graph.rs
+++ b/src/canvas/widgets/cpu_graph.rs
@@ -233,6 +233,7 @@ impl Painter {
title,
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
+ legend_position: None,
legend_constraints: None,
marker,
}
diff --git a/src/canvas/widgets/mem_graph.rs b/src/canvas/widgets/mem_graph.rs
index b9782e5a..5c814f51 100644
--- a/src/canvas/widgets/mem_graph.rs
+++ b/src/canvas/widgets/mem_graph.rs
@@ -133,6 +133,7 @@ impl Painter {
title: " Memory ".into(),
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
+ legend_position: app_state.app_config_fields.memory_legend_position,
legend_constraints: Some((Constraint::Ratio(3, 4), Constraint::Ratio(3, 4))),
marker,
}
diff --git a/src/canvas/widgets/network_graph.rs b/src/canvas/widgets/network_graph.rs
index 35ab9373..ec7e5fbd 100644
--- a/src/canvas/widgets/network_graph.rs
+++ b/src/canvas/widgets/network_graph.rs
@@ -162,6 +162,7 @@ impl Painter {
title: " Network ".into(),
is_expanded: app_state.is_expanded,
title_style: self.colours.widget_title_style,
+ legend_position: app_state.app_config_fields.network_legend_position,
legend_constraints: Some(legend_constraints),
marker,
}
diff --git a/src/constants.rs b/src/constants.rs
index eb185779..1c3aa097 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -573,7 +573,7 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al
#battery = false
# Disable mouse clicks
#disable_click = false
-# Built-in themes. Valid values are "default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"
+# Built-in themes. Valid values are "default", "default-light", "gruvbox", "gruvbox-light", "nord", "nord-light"
#color = "default"
# Show memory values in the processes widget as values by default
#mem_as_value = false
@@ -597,6 +597,10 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al
#enable_cache_memory = false
# How much data is stored at once in terms of time.
#retention = "10m"
+# Where to place the legend for the memory widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
+#memory_legend = "TopRight".
+# Where to place the legend for the network widget. One of "none", "top-left", "top", "top-right", "left", "right", "bottom-left", "bottom", "bottom-right".
+#network_legend = "TopRight".
# These are flags around the process widget.
#[processes]
diff --git a/src/options.rs b/src/options.rs
index 902c5c87..e36685ea 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -24,7 +24,7 @@ use starship_battery::Manager;
use self::config::{layout::Row, IgnoreList, StringOrNum};
use crate::{
app::{filter::Filter, layout_manager::*, *},
- canvas::{styling::CanvasStyling, ColourScheme},
+ canvas::{components::time_chart::LegendPosition, styling::CanvasStyling, ColourScheme},
constants::*,
data_collection::temperature::TemperatureType,
utils::{
@@ -126,6 +126,9 @@ pub fn init_app(
}
};
+ let network_legend_position = get_network_legend(matches, config)?;
+ let memory_legend_position = get_memory_legend(matches, config)?;
+
// TODO: Can probably just reuse the options struct.
let app_config_fields = AppConfigFields {
update_rate: get_update_rate(matches, config)
@@ -150,6 +153,8 @@ pub fn init_app(
enable_cache_memory: get_enable_cache_memory(matches, config),
show_table_scroll_position: is_flag_enabled!(show_table_scroll_position, matches, config),
is_advanced_kill,
+ memory_legend_position,
+ network_legend_position,
network_scale_type,
network_unit_type,
network_use_binary_prefix,
@@ -772,6 +777,48 @@ fn get_retention(matches: &ArgMatches, config: &Config) -> error::Result<u64> {
}
}
+fn get_network_legend(
+ matches: &ArgMatches, config: &Config,
+) -> error::Result<Option<LegendPosition>> {
+ let error =
+ |_| BottomError::ConfigError("network_legend is set to an invalid value".to_string());
+ if let Some(s) = matches.get_one::<String>("network_legend") {
+ match s.to_ascii_lowercase().trim() {
+ "none" => Ok(None),
+ position => Ok(Some(position.parse::<LegendPosition>().map_err(error)?)),
+ }
+ } else if let Some(flags) = &config.flags {
+ if let Some(legend) = &flags.network_legend {
+ Ok(Some(legend.parse::<LegendPosition>().map_err(error)?))
+ } else {
+ Ok(Some(LegendPosition::default()))
+ }
+ } else {
+ Ok(Some(LegendPosition::default()))
+ }
+}
+
+fn get_memory_legend(
+ matches: &ArgMatches, config: &Config,
+) -> error::Result<Option<LegendPosition>> {
+ let error =
+ |_| BottomError::ConfigError("memory_legend is set to an invalid value".to_string());
+ if let Some(s) = matches.get_one::<String>("memory_legend") {
+ match s.to_ascii_lowercase().trim() {
+ "none" => Ok(None),
+ position => Ok(Some(position.parse::<LegendPosition>().map_err(error)?)),
+ }
+ } else if let Some(flags) = &config.flags {
+ if let Some(legend) = &flags.memory_legend {
+ Ok(Some(legend.parse::<LegendPosition>().map_err(error)?))
+ } else {
+ Ok(Some(LegendPosition::default()))
+ }
+ } else {
+ Ok(Some(LegendPosition::default()))
+ }
+}
+
#[cfg(test)]
mod test {
use clap::ArgMatches;
diff --git a/src/options/args.rs b/src/options/args.rs
index b410eba4..c8fe35320 100644
--- a/src/options/args.rs
+++ b/src/options/args.rs
@@ -436,6 +436,24 @@ fn mem_args(cmd: Command) -> Command {
to showing it by percentage.",
);
+ let memory_legend = Arg::new("memory_legend")
+ .long("memory_legend")
+ .action(ArgAction::Set)
+ .value_name("POSITION")
+ .ignore_case(true)
+ .help("Where to place the legend for the memory widget.")
+ .value_parser([
+ "none",
+ "top-left",
+ "top",
+ "top-right",
+ "left",
+ "right",
+ "bottom-left",
+ "bottom",
+ "bottom-right",
+ ]);
+
#[cfg(not(target_os = "windows"))]
{
let enable_cache_memory = Arg::new("enable_cache_memory")
@@ -443,11 +461,11 @@ fn mem_args(cmd: Command) -> Command {
.action(ArgAction::SetTrue)
.help("Enable collecting and displaying cache and buffer memory.");
- cmd.args(args![mem_as_value, enable_cache_memory])
+ cmd.args(args![mem_as_value, memory_legend, enable_cache_memory])
}
#[cfg(target_os = "windows")]
{
- cmd.arg(mem_as_value)
+ cmd.args(args![mem_as_value, memory_legend])
}
}
@@ -464,6 +482,24 @@ fn network_args(cmd: Command) -> Command {
display is not tested anymore and may be broken.",
);
+ let network_legend = Arg::new("network_legend")
+ .long("network_legend")
+ .action(ArgAction::Set)
+ .value_name("POSITION")
+ .ignore_case(true)
+ .help("Where to place the legend for the network widget.")
+ .value_parser([
+ "none",
+ "top-left",
+ "top",
+ "top-right",
+ "left",
+ "right",
+ "bottom-left",
+ "bottom",
+ "bottom-right",
+ ]);
+
let network_use_bytes = Arg::new("network_use_bytes")
.long("network_use_bytes")
.action(ArgAction::SetTrue)
@@ -487,6 +523,7 @@ fn network_args(cmd: Command) -> Command {
cmd.args(args![
use_old_network_legend,
+ network_legend,
network_use_bytes,
network_use_log,
network_use_binary_prefix,
diff --git a/src/options/config.rs b/src/options/config.rs
index 23c2f956..6b3643f0 100644
--- a/src/options/config.rs
+++ b/src/options/config.rs
@@ -68,6 +68,8 @@ pub(crate) struct ConfigFlags {
pub(crate) battery: Option<bool>,
pub(crate) disable_click: Option<bool>,
pub(crate) no_write: Option<bool>,
+ pub(crate) network_legend: Option<String>,
+ pub(crate) memory_legend: Option<String>,
/// For built-in colour palettes.
pub(crate) color: Option<String>,
pub(crate) mem_as_value: Option<bool>,