From f091ebdc6a0a3c8a0b46da392a42749e381739d1 Mon Sep 17 00:00:00 2001 From: Clement Tsang <34804052+ClementTsang@users.noreply.github.com> Date: Tue, 30 Jul 2024 07:15:23 +0000 Subject: [PATCH] feature: support simple colour settings for text fields too (#1511) * feature: support simple colour settings for text fields too * also add 'color' back to some options * tests --- .../configuration/config-file/styling.md | 60 ++--- sample_configs/default_config.toml | 28 +-- schema/nightly/bottom.json | 117 ++++++---- src/constants.rs | 28 +-- src/options/config/style.rs | 54 ++--- src/options/config/style/battery.rs | 14 +- src/options/config/style/cpu.rs | 4 +- src/options/config/style/graphs.rs | 2 + src/options/config/style/memory.rs | 25 ++- src/options/config/style/network.rs | 21 +- src/options/config/style/tables.rs | 1 + src/options/config/style/utils.rs | 211 +++++++++++++++--- src/options/config/style/widgets.rs | 16 +- tests/valid_configs/styling.toml | 10 +- tests/valid_configs/styling_2.toml | 40 ++-- 15 files changed, 442 insertions(+), 189 deletions(-) diff --git a/docs/content/configuration/config-file/styling.md b/docs/content/configuration/config-file/styling.md index 5a533480..992e65ff 100644 --- a/docs/content/configuration/config-file/styling.md +++ b/docs/content/configuration/config-file/styling.md @@ -83,6 +83,14 @@ field = { color = "black", bg_color = "blue", bold = false } All fields are optional; by default if `bg_color` is not set then there will be no background color. +If you _just_ want to style text by setting the foreground colour, for brevity, then you can also just set the field +to be the colour itself. For example: + +```toml +[styles.widgets] +selected_text = "#fff" +``` + ### Configuration #### CPU @@ -99,34 +107,34 @@ These can be set under `[styles.cpu]`: These can be set under `[styles.memory]`: -| Config field | Details | Examples | -| ------------ | ------------------------------------------------------------------------------ | --------------------------------- | -| `ram` | The colour of the RAM label and graph line | `ram = "Red"` | -| `cache` | The colour of the cache label and graph line. Does not do anything on Windows. | `cache = "#ffffff"` | -| `swap` | The colour of the swap label and graph line | `swap = "255, 0, 255"` | -| `arc` | The colour of the ARC label and graph line | `arc = "Blue"` | -| `gpus` | Colour of each GPU's memory label and graph line. Read in order. | `gpus = ["Red", "Blue", "Green"]` | +| Config field | Details | Examples | +| ------------- | ------------------------------------------------------------------------------ | --------------------------------------- | +| `ram_color` | The colour of the RAM label and graph line | `ram_color = "Red"` | +| `cache_color` | The colour of the cache label and graph line. Does not do anything on Windows. | `cache_color = "#ffffff"` | +| `swap_color` | The colour of the swap label and graph line | `swap_color = "255, 0, 255"` | +| `arc_color` | The colour of the ARC label and graph line | `arc_color = "Blue"` | +| `gpu_colors` | Colour of each GPU's memory label and graph line. Read in order. | `gpu_colors = ["Red", "Blue", "Green"]` | #### Network These can be set under `[styles.network]`: -| Config field | Details | Examples | -| ------------ | --------------------------------------------------------- | ---------------------- | -| `rx` | The colour of the RX (download) label and graph line | `rx = "Red"` | -| `tx` | The colour of the TX (upload) label and graph line. | `tx = "#ffffff"` | -| `rx_total` | The colour of the total RX (download) label in basic mode | `rx_total = "0, 0, 0"` | -| `tx_total` | The colour of the total TX (upload) label in basic mode | `tx_total = "#000"` | +| Config field | Details | Examples | +| ---------------- | --------------------------------------------------------- | ---------------------------- | +| `rx_color` | The colour of the RX (download) label and graph line | `rx_color = "Red"` | +| `tx_color` | The colour of the TX (upload) label and graph line | `tx_color = "#ffffff"` | +| `rx_total_color` | The colour of the total RX (download) label in basic mode | `rx_total_color = "0, 0, 0"` | +| `tx_total_color` | The colour of the total TX (upload) label in basic mode | `tx_total_color = "#000"` | #### Battery These can be set under `[styles.battery]`: -| Config field | Details | Examples | -| ---------------- | ------------------------------------------------------------------------ | ---------------------------- | -| `high_battery` | The colour of the battery widget bar when the battery is over 50% | `high_battery = "Red"` | -| `medium_battery` | The colour of the battery widget bar when the battery between 10% to 50% | `medium_battery = "#ffffff"` | -| `low_battery` | The colour of the battery widget bar when the battery is under 10% | `low_battery = "0, 0, 0"` | +| Config field | Details | Examples | +| ---------------------- | ------------------------------------------------------------------------ | ---------------------------------- | +| `high_battery_color` | The colour of the battery widget bar when the battery is over 50% | `high_battery_color = "Red"` | +| `medium_battery_color` | The colour of the battery widget bar when the battery between 10% to 50% | `medium_battery_color = "#ffffff"` | +| `low_battery_color` | The colour of the battery widget bar when the battery is under 10% | `low_battery_color = "0, 0, 0"` | #### Tables @@ -149,11 +157,11 @@ These can be set under `[styles.graphs]`: These can be set under `[styles.widgets]`: -| Config field | Details | Examples | -| ----------------- | ------------------------------------------------------------ | --------------------------------------------------------------------- | -| `border` | The colour of the widgets' borders | `border = "white"` | -| `selected_border` | The colour of a widget's borders when the widget is selected | `selected_border = "white"` | -| `widget_title` | Text styling for a widget's title | `widget_title = { color = "black", bg_color = "blue", bold = true }` | -| `text` | Text styling for text in general | `text = { color = "black", bg_color = "blue", bold = true }` | -| `selected_text` | Text styling for text when representing something selected | `selected_text = { color = "black", bg_color = "blue", bold = true }` | -| `disabled_text` | Text styling for text when representing something disabled | `disabled_text = { color = "black", bg_color = "blue", bold = true }` | +| Config field | Details | Examples | +| ----------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------- | +| `border_color` | The colour of the widgets' borders | `border_color = "white"` | +| `selected_border_color` | The colour of a widget's borders when the widget is selected | `selected_border_color = "white"` | +| `widget_title` | Text styling for a widget's title | `widget_title = { color = "black", bg_color = "blue", bold = true }` | +| `text` | Text styling for text in general | `text = { color = "black", bg_color = "blue", bold = true }` | +| `selected_text` | Text styling for text when representing something that is selected | `selected_text = { color = "black", bg_color = "blue", bold = true }` | +| `disabled_text` | Text styling for text when representing something that is disabled | `disabled_text = { color = "black", bg_color = "blue", bold = true }` | diff --git a/sample_configs/default_config.toml b/sample_configs/default_config.toml index ce116e2e..d79c5373 100644 --- a/sample_configs/default_config.toml +++ b/sample_configs/default_config.toml @@ -147,22 +147,22 @@ #cpu_core_colors = ["light magenta", "light yellow", "light cyan", "light green", "light blue", "cyan", "green", "blue"] #[styles.memory] -#ram = "light magenta" -#cache = "light red" -#swap = "light yellow" -#arc = "light cyan" -#gpus = ["light blue", "light red", "cyan", "green", "blue", "red"] +#ram_color = "light magenta" +#cache_color = "light red" +#swap_color = "light yellow" +#arc_color = "light cyan" +#gpu_colors = ["light blue", "light red", "cyan", "green", "blue", "red"] #[styles.network] -#rx = "light magenta" -#tx = "light yellow" -#rx_total = "light cyan" -#tx_total = "light green" +#rx_color = "light magenta" +#tx_color = "light yellow" +#rx_total_color = "light cyan" +#tx_total_color = "light green" #[styles.battery] -#high_battery = "green" -#medium_battery = "yellow" -#low_battery = "red" +#high_battery_color = "green" +#medium_battery_color = "yellow" +#low_battery_color = "red" #[styles.tables] #headers = {color = "light blue"} @@ -172,8 +172,8 @@ #legend_text = {color = "gray"} #[styles.widgets] -#border = "gray" -#selected_border = "light blue" +#border_color = "gray" +#selected_border_color = "light blue" #widget_title = {color = "gray"} #text = {color = "gray"} #selected_text = {color = "black", bg_color = "light blue"} diff --git a/schema/nightly/bottom.json b/schema/nightly/bottom.json index 06dd6546..370cfc86 100644 --- a/schema/nightly/bottom.json +++ b/schema/nightly/bottom.json @@ -90,7 +90,8 @@ "description": "Styling specific to the battery widget.", "type": "object", "properties": { - "high_battery": { + "high_battery_color": { + "description": "The colour of the battery widget bar when the battery is over 50%.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -100,7 +101,8 @@ } ] }, - "low_battery": { + "low_battery_color": { + "description": "The colour of the battery widget bar when the battery is under 10%.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -110,7 +112,8 @@ } ] }, - "medium_battery": { + "medium_battery_color": { + "description": "The colour of the battery widget bar when the battery between 10% to 50%.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -147,6 +150,7 @@ "type": "object", "properties": { "all_entry_color": { + "description": "The colour of the \"All\" CPU label.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -157,6 +161,7 @@ ] }, "avg_entry_color": { + "description": "The colour of the average CPU label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -167,6 +172,7 @@ ] }, "cpu_core_colors": { + "description": "Colour of each CPU threads' label and graph line. Read in order.", "type": [ "array", "null" @@ -481,6 +487,7 @@ "type": "object", "properties": { "graph_color": { + "description": "The general colour of the parts of the graph.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -491,6 +498,7 @@ ] }, "legend_text": { + "description": "Text styling for graph's legend text.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" @@ -536,7 +544,8 @@ "description": "Styling specific to the memory widget.", "type": "object", "properties": { - "arc": { + "arc_color": { + "description": "The colour of the ARC label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -546,7 +555,8 @@ } ] }, - "cache": { + "cache_color": { + "description": "The colour of the cache label and graph line. Does not do anything on Windows.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -556,7 +566,8 @@ } ] }, - "gpus": { + "gpu_colors": { + "description": "Colour of each GPU's memory label and graph line. Read in order.", "type": [ "array", "null" @@ -565,7 +576,8 @@ "$ref": "#/definitions/ColorStr" } }, - "ram": { + "ram_color": { + "description": "The colour of the RAM label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -575,7 +587,8 @@ } ] }, - "swap": { + "swap_color": { + "description": "The colour of the swap label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -608,7 +621,8 @@ "description": "Styling specific to the network widget.", "type": "object", "properties": { - "rx": { + "rx_color": { + "description": "The colour of the RX (download) label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -618,8 +632,8 @@ } ] }, - "rx_total": { - "description": "Set the colour of the \"rx total\" text. This only affects basic mode.", + "rx_total_color": { + "description": "he colour of the total RX (download) label in basic mode.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -629,7 +643,8 @@ } ] }, - "tx": { + "tx_color": { + "description": "The colour of the TX (upload) label and graph line.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -639,8 +654,8 @@ } ] }, - "tx_total": { - "description": "Set the colour of the \"tx total\" text. This only affects basic mode.", + "tx_total_color": { + "description": "The colour of the total TX (upload) label in basic mode.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -831,6 +846,7 @@ "type": "object", "properties": { "headers": { + "description": "Text styling for table headers.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" @@ -861,44 +877,52 @@ }, "TextStyleConfig": { "description": "A style for text.", - "type": "object", - "properties": { - "bg_color": { - "description": "A built-in ANSI colour, RGB hex, or RGB colour code.", - "anyOf": [ - { - "$ref": "#/definitions/ColorStr" - }, - { - "type": "null" - } - ] + "anyOf": [ + { + "$ref": "#/definitions/ColorStr" }, - "bold": { - "description": "Whether to make this text bolded or not. If not set, will default to built-in defaults.", - "type": [ - "boolean", - "null" - ] - }, - "color": { - "description": "A built-in ANSI colour, RGB hex, or RGB colour code.", - "anyOf": [ - { - "$ref": "#/definitions/ColorStr" + { + "type": "object", + "properties": { + "bg_color": { + "description": "A built-in ANSI colour, RGB hex, or RGB colour code.", + "anyOf": [ + { + "$ref": "#/definitions/ColorStr" + }, + { + "type": "null" + } + ] }, - { - "type": "null" + "bold": { + "description": "Whether to make this text bolded or not. If not set, will default to built-in defaults.", + "type": [ + "boolean", + "null" + ] + }, + "color": { + "description": "A built-in ANSI colour, RGB hex, or RGB colour code.", + "anyOf": [ + { + "$ref": "#/definitions/ColorStr" + }, + { + "type": "null" + } + ] } - ] + } } - } + ] }, "WidgetStyle": { "description": "General styling for generic widgets.", "type": "object", "properties": { - "border": { + "border_color": { + "description": "The colour of the widgets' borders.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -909,6 +933,7 @@ ] }, "disabled_text": { + "description": "Text styling for text when representing something that is disabled.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" @@ -918,7 +943,8 @@ } ] }, - "selected_border": { + "selected_border_color": { + "description": "The colour of a widget's borders when the widget is selected.", "anyOf": [ { "$ref": "#/definitions/ColorStr" @@ -929,6 +955,7 @@ ] }, "selected_text": { + "description": "Text styling for text when representing something that is selected.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" @@ -939,6 +966,7 @@ ] }, "text": { + "description": "Text styling for text in general.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" @@ -949,6 +977,7 @@ ] }, "widget_title": { + "description": "Text styling for a widget's title.", "anyOf": [ { "$ref": "#/definitions/TextStyleConfig" diff --git a/src/constants.rs b/src/constants.rs index f5938d1b..21deaefa 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -411,22 +411,22 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al #cpu_core_colors = ["light magenta", "light yellow", "light cyan", "light green", "light blue", "cyan", "green", "blue"] #[styles.memory] -#ram = "light magenta" -#cache = "light red" -#swap = "light yellow" -#arc = "light cyan" -#gpus = ["light blue", "light red", "cyan", "green", "blue", "red"] +#ram_color = "light magenta" +#cache_color = "light red" +#swap_color = "light yellow" +#arc_color = "light cyan" +#gpu_colors = ["light blue", "light red", "cyan", "green", "blue", "red"] #[styles.network] -#rx = "light magenta" -#tx = "light yellow" -#rx_total = "light cyan" -#tx_total = "light green" +#rx_color = "light magenta" +#tx_color = "light yellow" +#rx_total_color = "light cyan" +#tx_total_color = "light green" #[styles.battery] -#high_battery = "green" -#medium_battery = "yellow" -#low_battery = "red" +#high_battery_color = "green" +#medium_battery_color = "yellow" +#low_battery_color = "red" #[styles.tables] #headers = {color = "light blue"} @@ -436,8 +436,8 @@ pub const CONFIG_TEXT: &str = r#"# This is a default config file for bottom. Al #legend_text = {color = "gray"} #[styles.widgets] -#border = "gray" -#selected_border = "light blue" +#border_color = "gray" +#selected_border_color = "light blue" #widget_title = {color = "gray"} #text = {color = "gray"} #selected_text = {color = "black", bg_color = "light blue"} diff --git a/src/options/config/style.rs b/src/options/config/style.rs index 4b60acaf..52ec804f 100644 --- a/src/options/config/style.rs +++ b/src/options/config/style.rs @@ -32,20 +32,24 @@ use super::Config; pub(crate) struct ColorStr(Cow<'static, str>); /// A style for text. -#[derive(Clone, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(untagged)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] -pub(crate) struct TextStyleConfig { - /// A built-in ANSI colour, RGB hex, or RGB colour code. - #[serde(alias = "colour")] - pub(crate) color: Option, +pub(crate) enum TextStyleConfig { + Colour(ColorStr), + TextStyle { + /// A built-in ANSI colour, RGB hex, or RGB colour code. + #[serde(alias = "colour")] + color: Option, - /// A built-in ANSI colour, RGB hex, or RGB colour code. - #[serde(alias = "bg_colour")] - pub(crate) bg_color: Option, + /// A built-in ANSI colour, RGB hex, or RGB colour code. + #[serde(alias = "bg_colour")] + bg_color: Option, - /// Whether to make this text bolded or not. If not set, - /// will default to built-in defaults. - pub(crate) bold: Option, + /// Whether to make this text bolded or not. If not set, + /// will default to built-in defaults. + bold: Option, + }, } /// Style-related configs. @@ -161,28 +165,28 @@ impl ColourPalette { set_colour_list!(self.cpu_colour_styles, config.cpu, cpu_core_colors); // Memory - set_colour!(self.ram_style, config.memory, ram); - set_colour!(self.swap_style, config.memory, swap); + set_colour!(self.ram_style, config.memory, ram_color); + set_colour!(self.swap_style, config.memory, swap_color); #[cfg(not(target_os = "windows"))] - set_colour!(self.cache_style, config.memory, cache); + set_colour!(self.cache_style, config.memory, cache_color); #[cfg(feature = "zfs")] - set_colour!(self.arc_style, config.memory, arc); + set_colour!(self.arc_style, config.memory, arc_color); #[cfg(feature = "gpu")] - set_colour_list!(self.gpu_colours, config.memory, gpus); + set_colour_list!(self.gpu_colours, config.memory, gpu_colors); // Network - set_colour!(self.rx_style, config.network, rx); - set_colour!(self.tx_style, config.network, tx); - set_colour!(self.total_rx_style, config.network, rx_total); - set_colour!(self.total_tx_style, config.network, tx_total); + set_colour!(self.rx_style, config.network, rx_color); + set_colour!(self.tx_style, config.network, tx_color); + set_colour!(self.total_rx_style, config.network, rx_total_color); + set_colour!(self.total_tx_style, config.network, tx_total_color); // Battery - set_colour!(self.high_battery, config.battery, high_battery); - set_colour!(self.medium_battery, config.battery, medium_battery); - set_colour!(self.low_battery, config.battery, low_battery); + set_colour!(self.high_battery, config.battery, high_battery_color); + set_colour!(self.medium_battery, config.battery, medium_battery_color); + set_colour!(self.low_battery, config.battery, low_battery_color); // Tables set_style!(self.table_header_style, config.tables, headers); @@ -198,11 +202,11 @@ impl ColourPalette { set_style!(self.disabled_text_style, config.widgets, disabled_text); // Widget borders - set_colour!(self.border_style, config.widgets, border); + set_colour!(self.border_style, config.widgets, border_color); set_colour!( self.highlighted_border_style, config.widgets, - selected_border + selected_border_color ); Ok(()) diff --git a/src/options/config/style/battery.rs b/src/options/config/style/battery.rs index 99bc0928..e643a635 100644 --- a/src/options/config/style/battery.rs +++ b/src/options/config/style/battery.rs @@ -6,7 +6,15 @@ use super::ColorStr; #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct BatteryStyle { - pub(crate) high_battery: Option, - pub(crate) medium_battery: Option, - pub(crate) low_battery: Option, + /// The colour of the battery widget bar when the battery is over 50%. + #[serde(alias = "high_battery_colour")] + pub(crate) high_battery_color: Option, + + /// The colour of the battery widget bar when the battery between 10% to 50%. + #[serde(alias = "medium_battery_colour")] + pub(crate) medium_battery_color: Option, + + /// The colour of the battery widget bar when the battery is under 10%. + #[serde(alias = "low_battery_colour")] + pub(crate) low_battery_color: Option, } diff --git a/src/options/config/style/cpu.rs b/src/options/config/style/cpu.rs index 345e2977..01bf95cb 100644 --- a/src/options/config/style/cpu.rs +++ b/src/options/config/style/cpu.rs @@ -6,13 +6,15 @@ use super::ColorStr; #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct CpuStyle { - // TODO: Should I change the name of these? + /// The colour of the "All" CPU label. #[serde(alias = "all_entry_colour")] pub(crate) all_entry_color: Option, + /// The colour of the average CPU label and graph line. #[serde(alias = "avg_entry_colour")] pub(crate) avg_entry_color: Option, + /// Colour of each CPU threads' label and graph line. Read in order. #[serde(alias = "cpu_core_colours")] pub(crate) cpu_core_colors: Option>, } diff --git a/src/options/config/style/graphs.rs b/src/options/config/style/graphs.rs index ec221c22..77603756 100644 --- a/src/options/config/style/graphs.rs +++ b/src/options/config/style/graphs.rs @@ -6,8 +6,10 @@ use super::{ColorStr, TextStyleConfig}; #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct GraphStyle { + /// The general colour of the parts of the graph. #[serde(alias = "graph_colour")] pub(crate) graph_color: Option, + /// Text styling for graph's legend text. pub(crate) legend_text: Option, } diff --git a/src/options/config/style/memory.rs b/src/options/config/style/memory.rs index a3559783..f1c6d419 100644 --- a/src/options/config/style/memory.rs +++ b/src/options/config/style/memory.rs @@ -1,15 +1,30 @@ use serde::{Deserialize, Serialize}; use super::ColorStr; +// TODO: Maybe I should swap the alias and the field name since internally I use u. /// Styling specific to the memory widget. #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct MemoryStyle { - pub(crate) ram: Option, + /// The colour of the RAM label and graph line. + #[serde(alias = "ram_colour")] + pub(crate) ram_color: Option, + + /// The colour of the cache label and graph line. Does not do anything on Windows. #[cfg(not(target_os = "windows"))] - pub(crate) cache: Option, - pub(crate) swap: Option, - pub(crate) arc: Option, - pub(crate) gpus: Option>, + #[serde(alias = "cache_colour")] + pub(crate) cache_color: Option, + + /// The colour of the swap label and graph line. + #[serde(alias = "swap_colour")] + pub(crate) swap_color: Option, + + /// The colour of the ARC label and graph line. + #[serde(alias = "arc_colour")] + pub(crate) arc_color: Option, + + /// Colour of each GPU's memory label and graph line. Read in order. + #[serde(alias = "gpu_colours")] + pub(crate) gpu_colors: Option>, } diff --git a/src/options/config/style/network.rs b/src/options/config/style/network.rs index d5350c59..83ad1307 100644 --- a/src/options/config/style/network.rs +++ b/src/options/config/style/network.rs @@ -6,14 +6,19 @@ use super::ColorStr; #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct NetworkStyle { - pub(crate) rx: Option, - pub(crate) tx: Option, + /// The colour of the RX (download) label and graph line. + #[serde(alias = "rx_colour")] + pub(crate) rx_color: Option, - /// Set the colour of the "rx total" text. This only affects - /// basic mode. - pub(crate) rx_total: Option, + /// The colour of the TX (upload) label and graph line. + #[serde(alias = "tx_colour")] + pub(crate) tx_color: Option, - /// Set the colour of the "tx total" text. This only affects - /// basic mode. - pub(crate) tx_total: Option, + /// he colour of the total RX (download) label in basic mode. + #[serde(alias = "rx_total_colour")] + pub(crate) rx_total_color: Option, + + /// The colour of the total TX (upload) label in basic mode. + #[serde(alias = "tx_total_colour")] + pub(crate) tx_total_color: Option, } diff --git a/src/options/config/style/tables.rs b/src/options/config/style/tables.rs index de0739ad..834178f8 100644 --- a/src/options/config/style/tables.rs +++ b/src/options/config/style/tables.rs @@ -6,5 +6,6 @@ use super::TextStyleConfig; #[derive(Clone, Debug, Default, Deserialize, Serialize)] #[cfg_attr(feature = "generate_schema", derive(schemars::JsonSchema))] pub(crate) struct TableStyle { + /// Text styling for table headers. pub(crate) headers: Option, } diff --git a/src/options/config/style/utils.rs b/src/options/config/style/utils.rs index 9de20642..c4cadc41 100644 --- a/src/options/config/style/utils.rs +++ b/src/options/config/style/utils.rs @@ -1,5 +1,5 @@ use concat_string::concat_string; -use tui::style::{Color, Style}; +use tui::style::Color; use unicode_segmentation::UnicodeSegmentation; /// Convert a hex string to a colour. @@ -53,10 +53,6 @@ pub fn str_to_colour(input_val: &str) -> Result { } } -pub(super) fn str_to_fg(input_val: &str) -> Result { - Ok(Style::default().fg(str_to_colour(input_val)?)) -} - fn convert_rgb_to_color(rgb_str: &str) -> Result { let rgb_list = rgb_str.split(',').collect::>(); if rgb_list.len() != 3 { @@ -136,18 +132,55 @@ macro_rules! opt { macro_rules! set_style { ($palette_field:expr, $config_location:expr, $field:tt) => { if let Some(style) = &(opt!($config_location.as_ref()?.$field.as_ref())) { - if let Some(colour) = &style.color { - $palette_field = crate::options::config::style::utils::str_to_fg(&colour.0) - .map_err(|err| match stringify!($config_location).split_once(".") { - Some((_, loc)) => OptionError::config(format!( - "Please update 'styles.{loc}.{}' in your config file. {err}", - stringify!($field) - )), - None => OptionError::config(format!( - "Please update 'styles.{}' in your config file. {err}", - stringify!($field) - )), - })?; + match &style { + TextStyleConfig::Colour(colour) => { + $palette_field = $palette_field.fg( + crate::options::config::style::utils::str_to_colour(&colour.0) + .map_err(|err| match stringify!($config_location).split_once(".") { + Some((_, loc)) => crate::options::OptionError::config(format!( + "Please update 'styles.{loc}.{}' in your config file. {err}", + stringify!($field) + )), + None => crate::options::OptionError::config(format!( + "Please update 'styles.{}' in your config file. {err}", + stringify!($field) + )), + })? + ); + } + TextStyleConfig::TextStyle {color, bg_color, bold: _} => { + if let Some(fg) = &color { + $palette_field = $palette_field.fg( + crate::options::config::style::utils::str_to_colour(&fg.0) + .map_err(|err| match stringify!($config_location).split_once(".") { + Some((_, loc)) => crate::options::OptionError::config(format!( + "Please update 'styles.{loc}.{}' in your config file. {err}", + stringify!($field) + )), + None => crate::options::OptionError::config(format!( + "Please update 'styles.{}' in your config file. {err}", + stringify!($field) + )), + })? + ); + } + + if let Some(bg) = &bg_color { + $palette_field = $palette_field.bg( + crate::options::config::style::utils::str_to_colour(&bg.0) + .map_err(|err| match stringify!($config_location).split_once(".") { + Some((_, loc)) => crate::options::OptionError::config(format!( + "Please update 'styles.{loc}.{}' in your config file. {err}", + stringify!($field) + )), + None => crate::options::OptionError::config(format!( + "Please update 'styles.{}' in your config file. {err}", + stringify!($field) + )), + })? + ); + } + } } } }; @@ -156,19 +189,20 @@ macro_rules! set_style { macro_rules! set_colour { ($palette_field:expr, $config_location:expr, $field:tt) => { if let Some(colour) = &(opt!($config_location.as_ref()?.$field.as_ref())) { - $palette_field = - crate::options::config::style::utils::str_to_fg(&colour.0).map_err(|err| { + $palette_field = $palette_field.fg( + crate::options::config::style::utils::str_to_colour(&colour.0).map_err(|err| { match stringify!($config_location).split_once(".") { - Some((_, loc)) => OptionError::config(format!( + Some((_, loc)) => crate::options::OptionError::config(format!( "Please update 'styles.{loc}.{}' in your config file. {err}", stringify!($field) )), - None => OptionError::config(format!( + None => crate::options::OptionError::config(format!( "Please update 'styles.{}' in your config file. {err}", stringify!($field) )), } - })?; + })?, + ); } }; } @@ -178,14 +212,17 @@ macro_rules! set_colour_list { if let Some(colour_list) = &(opt!($config_location.as_ref()?.$field.as_ref())) { $palette_field = colour_list .iter() - .map(|s| crate::options::config::style::utils::str_to_fg(&s.0)) + .map(|s| { + Ok(Style::default() + .fg(crate::options::config::style::utils::str_to_colour(&s.0)?)) + }) .collect::, String>>() .map_err(|err| match stringify!($config_location).split_once(".") { - Some((_, loc)) => OptionError::config(format!( + Some((_, loc)) => crate::options::OptionError::config(format!( "Please update 'styles.{loc}.{}' in your config file. {err}", stringify!($field) )), - None => OptionError::config(format!( + None => crate::options::OptionError::config(format!( "Please update 'styles.{}' in your config file. {err}", stringify!($field) )), @@ -199,6 +236,10 @@ pub(super) use {opt, set_colour, set_colour_list, set_style}; #[cfg(test)] mod test { + use tui::style::Style; + + use crate::options::config::style::{ColorStr, TextStyleConfig}; + use super::*; #[test] @@ -351,4 +392,124 @@ mod test { assert!(convert_rgb_to_color("1, -100000, 1").is_err()); assert!(convert_rgb_to_color("1, -100000, 100000").is_err()); } + + struct DummyConfig { + inner: Option, + } + + struct InnerDummyConfig { + color_a: Option, + color_b: Option, + color_c: Option, + color_d: Option, + many_colors: Option>, + text_a: Option, + text_b: Option, + text_c: Option, + text_d: Option, + text_e: Option, + } + + impl Default for InnerDummyConfig { + fn default() -> Self { + Self { + color_a: None, + color_b: Some(ColorStr("red".into())), + color_c: Some(ColorStr("255, 255, 255".into())), + color_d: Some(ColorStr("#000000".into())), + many_colors: Some(vec![ColorStr("red".into()), ColorStr("blue".into())]), + text_a: Some(TextStyleConfig::Colour(ColorStr("green".into()))), + text_b: Some(TextStyleConfig::TextStyle { + color: None, + bg_color: None, + bold: None, + }), + text_c: Some(TextStyleConfig::TextStyle { + color: Some(ColorStr("magenta".into())), + bg_color: Some(ColorStr("255, 255, 255".into())), + bold: Some(false), + }), + text_d: Some(TextStyleConfig::TextStyle { + color: Some(ColorStr("#fff".into())), + bg_color: Some(ColorStr("1, 1, 1".into())), + bold: Some(true), + }), + text_e: None, + } + } + } + + #[test] + fn test_set_colour() -> anyhow::Result<()> { + let mut s = Style::default().fg(Color::Black); + let dummy = DummyConfig { + inner: Some(InnerDummyConfig::default()), + }; + + set_colour!(s, &dummy.inner, color_a); + assert_eq!(s.fg.unwrap(), Color::Black); + assert_eq!(s.bg, None); + + set_colour!(s, &dummy.inner, color_b); + assert_eq!(s.fg.unwrap(), Color::Red); + assert_eq!(s.bg, None); + + set_colour!(s, &dummy.inner, color_c); + assert_eq!(s.fg.unwrap(), Color::Rgb(255, 255, 255)); + assert_eq!(s.bg, None); + + set_colour!(s, &dummy.inner, color_d); + assert_eq!(s.fg.unwrap(), Color::Rgb(0, 0, 0)); + assert_eq!(s.bg, None); + + Ok(()) + } + + #[test] + fn test_set_multi_colours() -> anyhow::Result<()> { + let mut s: Vec