mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-22 04:03:06 +00:00
feature: default colour schemes (#296)
Adds some default colour choices to choose from.
This commit is contained in:
parent
4573194cec
commit
e43456207b
18 changed files with 456 additions and 244 deletions
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
|
@ -70,6 +70,7 @@
|
||||||
"n'th",
|
"n'th",
|
||||||
"nixos",
|
"nixos",
|
||||||
"noheader",
|
"noheader",
|
||||||
|
"nord",
|
||||||
"ntdef",
|
"ntdef",
|
||||||
"nuget",
|
"nuget",
|
||||||
"nvme",
|
"nvme",
|
||||||
|
|
|
@ -21,10 +21,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- [#269](https://github.com/ClementTsang/bottom/pull/269): Add simple indicator for when data updating is frozen.
|
- [#269](https://github.com/ClementTsang/bottom/pull/269): Add simple indicator for when data updating is frozen.
|
||||||
|
|
||||||
|
- [#296](https://github.com/ClementTsang/bottom/pull/296): Built-in colour themes.
|
||||||
|
|
||||||
### 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.
|
||||||
|
|
||||||
|
- [#296](https://github.com/ClementTsang/bottom/pull/296): Changed how we do battery theming. We now only set high, medium, and low colours and we deal with the ratios.
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- [#211](https://github.com/ClementTsang/bottom/pull/211): Fixes a bug where you could move down in the process widget even if the process widget search was closed.
|
- [#211](https://github.com/ClementTsang/bottom/pull/211): Fixes a bug where you could move down in the process widget even if the process widget search was closed.
|
||||||
|
@ -52,6 +56,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- [#291](https://github.com/ClementTsang/bottom/pull/291): Fixed spacing problems in basic CPU mode.
|
- [#291](https://github.com/ClementTsang/bottom/pull/291): Fixed spacing problems in basic CPU mode.
|
||||||
|
|
||||||
|
- [#296](https://github.com/ClementTsang/bottom/pull/296): Fixed an incorrect offset affecting the graph CPU colour mismatching the legend.
|
||||||
|
|
||||||
|
- [#296](https://github.com/ClementTsang/bottom/pull/296): Removes an accidental extra comma in one of the headers in the disk widget.
|
||||||
|
|
||||||
## [0.4.7] - 2020-08-26
|
## [0.4.7] - 2020-08-26
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
78
Cargo.lock
generated
78
Cargo.lock
generated
|
@ -117,7 +117,7 @@ dependencies = [
|
||||||
"cargo-husky",
|
"cargo-husky",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"crossterm 0.18.2",
|
"crossterm",
|
||||||
"ctrlc",
|
"ctrlc",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"fern",
|
"fern",
|
||||||
|
@ -199,15 +199,6 @@ dependencies = [
|
||||||
"vec_map",
|
"vec_map",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cloudabi"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloudabi"
|
name = "cloudabi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -286,22 +277,6 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossterm"
|
|
||||||
version = "0.17.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6f4919d60f26ae233e14233cc39746c8c8bb8cd7b05840ace83604917b51b6c7"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"crossterm_winapi",
|
|
||||||
"lazy_static",
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"parking_lot 0.10.2",
|
|
||||||
"signal-hook",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
version = "0.18.2"
|
version = "0.18.2"
|
||||||
|
@ -313,7 +288,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"parking_lot 0.11.0",
|
"parking_lot",
|
||||||
"signal-hook",
|
"signal-hook",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
@ -767,15 +742,6 @@ version = "0.2.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.3.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75"
|
|
||||||
dependencies = [
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -957,9 +923,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.4.1"
|
version = "1.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
|
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
|
@ -970,16 +936,6 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.10.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api 0.3.4",
|
|
||||||
"parking_lot_core 0.7.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -987,22 +943,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
|
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"instant",
|
"instant",
|
||||||
"lock_api 0.4.1",
|
"lock_api",
|
||||||
"parking_lot_core 0.8.0",
|
"parking_lot_core",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.7.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"cloudabi 0.0.3",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"winapi",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1012,7 +954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"cloudabi 0.1.0",
|
"cloudabi",
|
||||||
"instant",
|
"instant",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
|
@ -1388,13 +1330,13 @@ checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tui"
|
name = "tui"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2eaeee894a1e9b90f80aa466fe59154fdb471980b5e104d8836fcea309ae17e"
|
checksum = "5d4e6c82bb967df89f20b875fa8835fab5d5622c6a5efa574a1f0b6d0aa6e8f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"crossterm 0.17.7",
|
"crossterm",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
|
@ -42,7 +42,7 @@ serde = {version = "1.0", features = ["derive"] }
|
||||||
sysinfo = "0.15.3"
|
sysinfo = "0.15.3"
|
||||||
thiserror = "1.0.21"
|
thiserror = "1.0.21"
|
||||||
toml = "0.5.7"
|
toml = "0.5.7"
|
||||||
tui = {version = "0.12.0", features = ["crossterm"], default-features = false }
|
tui = {version = "0.13.0", features = ["crossterm"], default-features = false }
|
||||||
typed-builder = "0.7.0"
|
typed-builder = "0.7.0"
|
||||||
unicode-segmentation = "1.6.0"
|
unicode-segmentation = "1.6.0"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
|
|
51
README.md
51
README.md
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop).
|
A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop).
|
||||||
|
|
||||||
![Quick demo recording showing off searching, expanding, and process killing.](assets/demo.gif) _Theme based on [gruvbox](https://github.com/morhetz/gruvbox) (see [sample config](./sample_configs/demo_config.toml))._ Recorded on version 0.4.7.
|
![Quick demo recording showing off searching, expanding, and process killing.](assets/demo.gif) _Theme based on [gruvbox](https://github.com/morhetz/gruvbox) (see [sample config](./sample_configs/demo_config.toml)). Font is [IBM Plex Mono](https://www.ibm.com/plex/), terminal is [Kitty](https://sw.kovidgoyal.net/kitty/)_ Recorded on version **0.4.7**.
|
||||||
|
|
||||||
**Note**: If you are reading this on the master branch, then it may refer to in-development or un-released features/changes. Please refer to [release branch](https://github.com/ClementTsang/bottom/tree/release/README.md) or [crates.io](https://crates.io/crates/bottom) for the most up-to-date _release_ documentation.
|
**Note**: If you are reading this on the master branch, then it may refer to in-development or un-released features/changes. Please refer to [release branch](https://github.com/ClementTsang/bottom/tree/release/README.md) or [crates.io](https://crates.io/crates/bottom) for the most up-to-date _release_ documentation.
|
||||||
|
|
||||||
|
@ -215,7 +215,9 @@ Run using `btm`.
|
||||||
--battery Shows the battery widget.
|
--battery Shows the battery widget.
|
||||||
-S, --case_sensitive Enables case sensitivity by default.
|
-S, --case_sensitive Enables case sensitivity by default.
|
||||||
-c, --celsius Sets the temperature type to Celsius.
|
-c, --celsius Sets the temperature type to Celsius.
|
||||||
|
--color <COLOR SCHEME> Use a color scheme, use --help for supported values.
|
||||||
-C, --config <CONFIG PATH> Sets the location of the config file.
|
-C, --config <CONFIG PATH> Sets the location of the config file.
|
||||||
|
-u, --current_usage Sets process CPU% to be based on current CPU%.
|
||||||
--debug Enables debug logging.
|
--debug Enables debug logging.
|
||||||
-t, --default_time_value <MS> Default time value for graphs in ms.
|
-t, --default_time_value <MS> Default time value for graphs in ms.
|
||||||
--default_widget_count <INT> Sets the n'th selected widget type as the default.
|
--default_widget_count <INT> Sets the n'th selected widget type as the default.
|
||||||
|
@ -224,19 +226,19 @@ Run using `btm`.
|
||||||
-m, --dot_marker Uses a dot marker for graphs.
|
-m, --dot_marker Uses a dot marker for graphs.
|
||||||
-f, --fahrenheit Sets the temperature type to Fahrenheit.
|
-f, --fahrenheit Sets the temperature type to Fahrenheit.
|
||||||
-g, --group Groups processes with the same name by default.
|
-g, --group Groups processes with the same name by default.
|
||||||
|
-h, --help Prints help information. Use --help for more info.
|
||||||
-a, --hide_avg_cpu Hides the average CPU usage.
|
-a, --hide_avg_cpu Hides the average CPU usage.
|
||||||
--hide_table_gap Hides the spacing between table headers and entries.
|
--hide_table_gap Hides the spacing between table headers and entries.
|
||||||
--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.
|
||||||
|
--no_write Disables writing to the config file.
|
||||||
-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.
|
||||||
-u, --current_usage Sets process CPU% to be based on current CPU%.
|
|
||||||
--use_old_network_legend DEPRECATED - uses the older network legend.
|
--use_old_network_legend DEPRECATED - uses the older network legend.
|
||||||
-W, --whole_word Enables whole-word matching by default.
|
|
||||||
-h, --help Prints help information. Use --help for more info.
|
|
||||||
-V, --version Prints version information.
|
-V, --version Prints version information.
|
||||||
|
-W, --whole_word Enables whole-word matching by default.
|
||||||
```
|
```
|
||||||
|
|
||||||
### Keybindings
|
### Keybindings
|
||||||
|
@ -538,6 +540,7 @@ These are the following supported flag config values, which correspond to the fl
|
||||||
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) |
|
| `default_widget_type` | String (one of ["cpu", "proc", "net", "temp", "mem", "disk"], same as layout options) |
|
||||||
| `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"]) |
|
||||||
|
|
||||||
#### Theming
|
#### Theming
|
||||||
|
|
||||||
|
@ -545,25 +548,27 @@ The config file can be used to set custom colours for parts of the application u
|
||||||
|
|
||||||
Supported named colours are one of the following strings: `Reset, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, DarkGray, LightRed, LightGreen, LightYellow, LightBlue, LightMagenta, LightCyan, White`.
|
Supported named colours are one of the following strings: `Reset, Black, Red, Green, Yellow, Blue, Magenta, Cyan, Gray, DarkGray, LightRed, LightGreen, LightYellow, LightBlue, LightMagenta, LightCyan, White`.
|
||||||
|
|
||||||
| Labels | Details | Example |
|
| Labels | Details | Example |
|
||||||
| ------------------------------- | ----------------------------------------------------- | ------------------------------------------------------- |
|
| ------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
|
||||||
| Table header colours | Colour of table headers | `table_header_color="255, 255, 255"` |
|
| Table header colours | Colour of table headers | `table_header_color="255, 255, 255"` |
|
||||||
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "white", "255, 255, 255"]` |
|
| CPU colour per core | Colour of each core. Read in order. | `cpu_core_colors=["#ffffff", "white", "255, 255, 255"]` |
|
||||||
| Average CPU colour | The average CPU color | `avg_cpu_color="White"` |
|
| Average CPU colour | The average CPU color | `avg_cpu_color="White"` |
|
||||||
| All CPUs colour | The colour for the "All" CPU label | `all_cpu_color="White"` |
|
| All CPUs colour | The colour for the "All" CPU label | `all_cpu_color="White"` |
|
||||||
| RAM | The colour RAM will use | `ram_color="#ffffff"` |
|
| RAM | The colour RAM will use | `ram_color="#ffffff"` |
|
||||||
| SWAP | The colour SWAP will use | `swap_color="#ffffff"` |
|
| SWAP | The colour SWAP will use | `swap_color="#ffffff"` |
|
||||||
| RX | The colour rx will use | `rx_color="#ffffff"` |
|
| RX | The colour rx will use | `rx_color="#ffffff"` |
|
||||||
| TX | The colour tx will use | `tx_color="#ffffff"` |
|
| TX | The colour tx will use | `tx_color="#ffffff"` |
|
||||||
| Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` |
|
| Widget title colour | The colour of the label each widget has | `widget_title_color="#ffffff"` |
|
||||||
| Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` |
|
| Border colour | The colour of the border of unselected widgets | `border_color="#ffffff"` |
|
||||||
| Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` |
|
| Selected border colour | The colour of the border of selected widgets | `highlighted_border_color="#ffffff"` |
|
||||||
| Text colour | The colour of most text | `text_color="#ffffff"` |
|
| Text colour | The colour of most text | `text_color="#ffffff"` |
|
||||||
| Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` |
|
| Graph colour | The colour of the lines and text of the graph | `graph_color="#ffffff"` |
|
||||||
| Cursor colour | The cursor's colour | `cursor_color="#ffffff"` |
|
| Cursor colour | The cursor's colour | `cursor_color="#ffffff"` |
|
||||||
| Selected text colour | The colour of text that is selected | `scroll_entry_text_color="#ffffff"` |
|
| Selected text colour | The colour of text that is selected | `scroll_entry_text_color="#ffffff"` |
|
||||||
| Selected text background colour | The background colour of text that is selected | `scroll_entry_bg_color="#ffffff"` |
|
| Selected text background colour | The background colour of text that is selected | `scroll_entry_bg_color="#ffffff"` |
|
||||||
| Battery bar colours | Colour used is based on percentage and no. of colours | `battery_colors=["green", "yellow", "red"]` |
|
| High battery level colour | The colour used for a high battery level (100% to 50%) | `high_battery_color="green"` |
|
||||||
|
| Medium battery level colour | The colour used for a medium battery level (50% to 10%) | `medium_battery_color="yellow"` |
|
||||||
|
| Low battery level colour | The colour used for a low battery level (10% to 0%) | `low_battery_color="red"` |
|
||||||
|
|
||||||
#### Layout
|
#### Layout
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ fn main() -> Result<()> {
|
||||||
app.app_config_fields.table_gap,
|
app.app_config_fields.table_gap,
|
||||||
app.app_config_fields.use_basic_mode,
|
app.app_config_fields.use_basic_mode,
|
||||||
&config,
|
&config,
|
||||||
|
get_color_scheme(&matches, &config)?,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Create termination mutex and cvar
|
// Create termination mutex and cvar
|
||||||
|
|
153
src/canvas.rs
153
src/canvas.rs
|
@ -1,6 +1,5 @@
|
||||||
use anyhow::Context;
|
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
|
@ -25,6 +24,7 @@ use crate::{
|
||||||
data_conversion::{ConvertedBatteryData, ConvertedCpuData, ConvertedProcessData},
|
data_conversion::{ConvertedBatteryData, ConvertedCpuData, ConvertedProcessData},
|
||||||
options::Config,
|
options::Config,
|
||||||
utils::error,
|
utils::error,
|
||||||
|
utils::error::BottomError,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod canvas_colours;
|
mod canvas_colours;
|
||||||
|
@ -59,6 +59,35 @@ pub struct DisplayableData {
|
||||||
pub battery_data: Vec<ConvertedBatteryData>,
|
pub battery_data: Vec<ConvertedBatteryData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ColourScheme {
|
||||||
|
Default,
|
||||||
|
DefaultLight,
|
||||||
|
Gruvbox,
|
||||||
|
GruvboxLight,
|
||||||
|
// Nord,
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for ColourScheme {
|
||||||
|
type Err = BottomError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> error::Result<Self> {
|
||||||
|
let lower_case = s.to_lowercase();
|
||||||
|
match lower_case.as_str() {
|
||||||
|
"default" => Ok(ColourScheme::Default),
|
||||||
|
"default-light" => Ok(ColourScheme::DefaultLight),
|
||||||
|
"gruvbox" => Ok(ColourScheme::Gruvbox),
|
||||||
|
"gruvbox-light" => Ok(ColourScheme::GruvboxLight),
|
||||||
|
// "nord" => Ok(ColourScheme::Nord),
|
||||||
|
_ => Err(BottomError::ConfigError(format!(
|
||||||
|
"\"{}\" is an invalid built-in color scheme.",
|
||||||
|
s
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Handles the canvas' state. TODO: [OPT] implement this.
|
/// Handles the canvas' state. TODO: [OPT] implement this.
|
||||||
pub struct Painter {
|
pub struct Painter {
|
||||||
pub colours: CanvasColours,
|
pub colours: CanvasColours,
|
||||||
|
@ -78,6 +107,7 @@ pub struct Painter {
|
||||||
impl Painter {
|
impl Painter {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
widget_layout: BottomLayout, table_gap: u16, is_basic_mode: bool, config: &Config,
|
widget_layout: BottomLayout, table_gap: u16, is_basic_mode: bool, config: &Config,
|
||||||
|
colour_scheme: ColourScheme,
|
||||||
) -> anyhow::Result<Self> {
|
) -> anyhow::Result<Self> {
|
||||||
// Now for modularity; we have to also initialize the base layouts!
|
// Now for modularity; we have to also initialize the base layouts!
|
||||||
// We want to do this ONCE and reuse; after this we can just construct
|
// We want to do this ONCE and reuse; after this we can just construct
|
||||||
|
@ -161,117 +191,48 @@ impl Painter {
|
||||||
table_height_offset: if is_basic_mode { 2 } else { 4 } + table_gap,
|
table_height_offset: if is_basic_mode { 2 } else { 4 } + table_gap,
|
||||||
};
|
};
|
||||||
|
|
||||||
painter.generate_config_colours(config)?;
|
if let ColourScheme::Custom = colour_scheme {
|
||||||
|
painter.generate_config_colours(config)?;
|
||||||
|
} else {
|
||||||
|
painter.generate_colour_scheme(colour_scheme)?;
|
||||||
|
}
|
||||||
painter.colours.generate_remaining_cpu_colours();
|
painter.colours.generate_remaining_cpu_colours();
|
||||||
painter.complete_painter_init();
|
painter.complete_painter_init();
|
||||||
|
|
||||||
Ok(painter)
|
Ok(painter)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_config_colours(&mut self, config: &Config) -> anyhow::Result<()> {
|
fn generate_config_colours(&mut self, config: &Config) -> anyhow::Result<()> {
|
||||||
if let Some(colours) = &config.colors {
|
if let Some(colours) = &config.colors {
|
||||||
if let Some(border_color) = &colours.border_color {
|
self.colours.set_colours_from_palette(colours)?;
|
||||||
self.colours
|
}
|
||||||
.set_border_colour(border_color)
|
|
||||||
.context("Update 'border_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(highlighted_border_color) = &colours.highlighted_border_color {
|
Ok(())
|
||||||
self.colours
|
}
|
||||||
.set_highlighted_border_colour(highlighted_border_color)
|
|
||||||
.context("Update 'highlighted_border_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(text_color) = &colours.text_color {
|
fn generate_colour_scheme(&mut self, colour_scheme: ColourScheme) -> anyhow::Result<()> {
|
||||||
self.colours
|
match colour_scheme {
|
||||||
.set_text_colour(text_color)
|
ColourScheme::Default => {
|
||||||
.context("Update 'text_color' in your config file..")?;
|
// Don't have to do anything.
|
||||||
}
|
}
|
||||||
|
ColourScheme::DefaultLight => {
|
||||||
if let Some(avg_cpu_color) = &colours.avg_cpu_color {
|
|
||||||
self.colours
|
self.colours
|
||||||
.set_avg_cpu_colour(avg_cpu_color)
|
.set_colours_from_palette(&*DEFAULT_LIGHT_MODE_COLOUR_PALETTE)?;
|
||||||
.context("Update 'avg_cpu_color' in your config file..")?;
|
|
||||||
}
|
}
|
||||||
|
ColourScheme::Gruvbox => {
|
||||||
if let Some(all_cpu_color) = &colours.all_cpu_color {
|
|
||||||
self.colours
|
self.colours
|
||||||
.set_all_cpu_colour(all_cpu_color)
|
.set_colours_from_palette(&*GRUVBOX_COLOUR_PALETTE)?;
|
||||||
.context("Update 'all_cpu_color' in your config file..")?;
|
|
||||||
}
|
}
|
||||||
|
ColourScheme::GruvboxLight => {
|
||||||
if let Some(cpu_core_colors) = &colours.cpu_core_colors {
|
|
||||||
self.colours
|
self.colours
|
||||||
.set_cpu_colours(cpu_core_colors)
|
.set_colours_from_palette(&*GRUVBOX_LIGHT_COLOUR_PALETTE)?;
|
||||||
.context("Update 'cpu_core_colors' in your config file..")?;
|
|
||||||
}
|
}
|
||||||
|
// ColourScheme::Nord => {
|
||||||
if let Some(ram_color) = &colours.ram_color {
|
// self.colours
|
||||||
self.colours
|
// .set_colours_from_palette(&*NORD_COLOUR_PALETTE)?;
|
||||||
.set_ram_colour(ram_color)
|
|
||||||
.context("Update 'ram_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(swap_color) = &colours.swap_color {
|
|
||||||
self.colours
|
|
||||||
.set_swap_colour(swap_color)
|
|
||||||
.context("Update 'swap_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rx_color) = &colours.rx_color {
|
|
||||||
self.colours
|
|
||||||
.set_rx_colour(rx_color)
|
|
||||||
.context("Update 'rx_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tx_color) = &colours.tx_color {
|
|
||||||
self.colours
|
|
||||||
.set_tx_colour(tx_color)
|
|
||||||
.context("Update 'tx_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if let Some(rx_total_color) = &colours.rx_total_color {
|
|
||||||
// painter.colours.set_rx_total_colour(rx_total_color)?;
|
|
||||||
// }
|
// }
|
||||||
|
ColourScheme::Custom => {
|
||||||
// if let Some(tx_total_color) = &colours.tx_total_color {
|
// This case should never occur, just do nothing.
|
||||||
// painter.colours.set_tx_total_colour(tx_total_color)?;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if let Some(table_header_color) = &colours.table_header_color {
|
|
||||||
self.colours
|
|
||||||
.set_table_header_colour(table_header_color)
|
|
||||||
.context("Update 'table_header_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(scroll_entry_text_color) = &colours.selected_text_color {
|
|
||||||
self.colours
|
|
||||||
.set_scroll_entry_text_color(scroll_entry_text_color)
|
|
||||||
.context("Update 'selected_text_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(scroll_entry_bg_color) = &colours.selected_bg_color {
|
|
||||||
self.colours
|
|
||||||
.set_scroll_entry_bg_color(scroll_entry_bg_color)
|
|
||||||
.context("Update 'selected_bg_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(widget_title_color) = &colours.widget_title_color {
|
|
||||||
self.colours
|
|
||||||
.set_widget_title_colour(widget_title_color)
|
|
||||||
.context("Update 'widget_title_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(graph_color) = &colours.graph_color {
|
|
||||||
self.colours
|
|
||||||
.set_graph_colour(graph_color)
|
|
||||||
.context("Update 'graph_color' in your config file..")?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(battery_colors) = &colours.battery_colors {
|
|
||||||
self.colours
|
|
||||||
.set_battery_colors(battery_colors)
|
|
||||||
.context("Update 'battery_colors' in your config file.")?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use tui::style::{Color, Style};
|
use crate::{constants::*, options::ConfigColours, utils::error};
|
||||||
|
use anyhow::Context;
|
||||||
use colour_utils::*;
|
use colour_utils::*;
|
||||||
|
use tui::style::{Color, Style};
|
||||||
use crate::{constants::*, utils::error};
|
|
||||||
|
|
||||||
mod colour_utils;
|
mod colour_utils;
|
||||||
|
|
||||||
pub struct CanvasColours {
|
pub struct CanvasColours {
|
||||||
|
@ -60,6 +58,10 @@ impl Default for CanvasColours {
|
||||||
Style::default().fg(Color::Red),
|
Style::default().fg(Color::Red),
|
||||||
Style::default().fg(Color::Yellow),
|
Style::default().fg(Color::Yellow),
|
||||||
Style::default().fg(Color::Yellow),
|
Style::default().fg(Color::Yellow),
|
||||||
|
Style::default().fg(Color::Yellow),
|
||||||
|
Style::default().fg(Color::Green),
|
||||||
|
Style::default().fg(Color::Green),
|
||||||
|
Style::default().fg(Color::Green),
|
||||||
Style::default().fg(Color::Green),
|
Style::default().fg(Color::Green),
|
||||||
Style::default().fg(Color::Green),
|
Style::default().fg(Color::Green),
|
||||||
Style::default().fg(Color::Green),
|
Style::default().fg(Color::Green),
|
||||||
|
@ -71,6 +73,118 @@ impl Default for CanvasColours {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CanvasColours {
|
impl CanvasColours {
|
||||||
|
pub fn set_colours_from_palette(&mut self, colours: &ConfigColours) -> anyhow::Result<()> {
|
||||||
|
if let Some(border_color) = &colours.border_color {
|
||||||
|
self.set_border_colour(border_color)
|
||||||
|
.context("Update 'border_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(highlighted_border_color) = &colours.highlighted_border_color {
|
||||||
|
self.set_highlighted_border_colour(highlighted_border_color)
|
||||||
|
.context("Update 'highlighted_border_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(text_color) = &colours.text_color {
|
||||||
|
self.set_text_colour(text_color)
|
||||||
|
.context("Update 'text_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(avg_cpu_color) = &colours.avg_cpu_color {
|
||||||
|
self.set_avg_cpu_colour(avg_cpu_color)
|
||||||
|
.context("Update 'avg_cpu_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(all_cpu_color) = &colours.all_cpu_color {
|
||||||
|
self.set_all_cpu_colour(all_cpu_color)
|
||||||
|
.context("Update 'all_cpu_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(cpu_core_colors) = &colours.cpu_core_colors {
|
||||||
|
self.set_cpu_colours(cpu_core_colors)
|
||||||
|
.context("Update 'cpu_core_colors' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ram_color) = &colours.ram_color {
|
||||||
|
self.set_ram_colour(ram_color)
|
||||||
|
.context("Update 'ram_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(swap_color) = &colours.swap_color {
|
||||||
|
self.set_swap_colour(swap_color)
|
||||||
|
.context("Update 'swap_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(rx_color) = &colours.rx_color {
|
||||||
|
self.set_rx_colour(rx_color)
|
||||||
|
.context("Update 'rx_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tx_color) = &colours.tx_color {
|
||||||
|
self.set_tx_colour(tx_color)
|
||||||
|
.context("Update 'tx_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(table_header_color) = &colours.table_header_color {
|
||||||
|
self.set_table_header_colour(table_header_color)
|
||||||
|
.context("Update 'table_header_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(scroll_entry_text_color) = &colours.selected_text_color {
|
||||||
|
self.set_scroll_entry_text_color(scroll_entry_text_color)
|
||||||
|
.context("Update 'selected_text_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(scroll_entry_bg_color) = &colours.selected_bg_color {
|
||||||
|
self.set_scroll_entry_bg_color(scroll_entry_bg_color)
|
||||||
|
.context("Update 'selected_bg_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(widget_title_color) = &colours.widget_title_color {
|
||||||
|
self.set_widget_title_colour(widget_title_color)
|
||||||
|
.context("Update 'widget_title_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(graph_color) = &colours.graph_color {
|
||||||
|
self.set_graph_colour(graph_color)
|
||||||
|
.context("Update 'graph_color' in your config file..")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(high_battery_color) = &colours.high_battery_color {
|
||||||
|
self.set_high_battery_color(high_battery_color)
|
||||||
|
.context("Update 'high_battery_color' in your config file.")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(medium_battery_color) = &colours.medium_battery_color {
|
||||||
|
self.set_medium_battery_color(medium_battery_color)
|
||||||
|
.context("Update 'medium_battery_color' in your config file.")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(low_battery_color) = &colours.low_battery_color {
|
||||||
|
self.set_low_battery_color(low_battery_color)
|
||||||
|
.context("Update 'low_battery_color' in your config file.")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(disabled_text_color) = &colours.disabled_text_color {
|
||||||
|
self.set_disabled_text_colour(disabled_text_color)
|
||||||
|
.context("Update 'disabled_text_color' in your config file.")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(rx_total_color) = &colours.rx_total_color {
|
||||||
|
self.set_rx_total_colour(rx_total_color)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tx_total_color) = &colours.tx_total_color {
|
||||||
|
self.set_tx_total_colour(tx_total_color)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_disabled_text_colour(&mut self, colour: &str) -> error::Result<()> {
|
||||||
|
self.disabled_text_style = get_style_from_config(colour)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_text_colour(&mut self, colour: &str) -> error::Result<()> {
|
pub fn set_text_colour(&mut self, colour: &str) -> error::Result<()> {
|
||||||
self.text_style = get_style_from_config(colour)?;
|
self.text_style = get_style_from_config(colour)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -113,15 +227,15 @@ impl CanvasColours {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn set_rx_total_colour(&mut self, colour: &str) -> error::Result<()> {
|
pub fn set_rx_total_colour(&mut self, colour: &str) -> error::Result<()> {
|
||||||
// self.total_rx_style = get_style_from_config(colour)?;
|
self.total_rx_style = get_style_from_config(colour)?;
|
||||||
// Ok(())
|
Ok(())
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub fn set_tx_total_colour(&mut self, colour: &str) -> error::Result<()> {
|
pub fn set_tx_total_colour(&mut self, colour: &str) -> error::Result<()> {
|
||||||
// self.total_tx_style = get_style_from_config(colour)?;
|
self.total_tx_style = get_style_from_config(colour)?;
|
||||||
// Ok(())
|
Ok(())
|
||||||
// }
|
}
|
||||||
|
|
||||||
pub fn set_avg_cpu_colour(&mut self, colour: &str) -> error::Result<()> {
|
pub fn set_avg_cpu_colour(&mut self, colour: &str) -> error::Result<()> {
|
||||||
self.avg_colour_style = get_style_from_config(colour)?;
|
self.avg_colour_style = get_style_from_config(colour)?;
|
||||||
|
@ -176,19 +290,27 @@ impl CanvasColours {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_battery_colors(&mut self, colours: &[String]) -> error::Result<()> {
|
pub fn set_high_battery_color(&mut self, colour: &str) -> error::Result<()> {
|
||||||
if colours.is_empty() {
|
let style = get_style_from_config(colour)?;
|
||||||
Err(error::BottomError::ConfigError(
|
self.battery_bar_styles[0] = style;
|
||||||
"battery colour list must have at least one colour.".to_string(),
|
self.battery_bar_styles[1] = style;
|
||||||
))
|
self.battery_bar_styles[2] = style;
|
||||||
} else {
|
self.battery_bar_styles[3] = style;
|
||||||
let generated_colours: Result<Vec<_>, _> = colours
|
self.battery_bar_styles[4] = style;
|
||||||
.iter()
|
self.battery_bar_styles[5] = style;
|
||||||
.map(|colour| get_style_from_config(colour))
|
Ok(())
|
||||||
.collect();
|
}
|
||||||
|
|
||||||
self.battery_bar_styles = generated_colours?;
|
pub fn set_medium_battery_color(&mut self, colour: &str) -> error::Result<()> {
|
||||||
Ok(())
|
let style = get_style_from_config(colour)?;
|
||||||
}
|
self.battery_bar_styles[6] = style;
|
||||||
|
self.battery_bar_styles[7] = style;
|
||||||
|
self.battery_bar_styles[8] = style;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_low_battery_color(&mut self, colour: &str) -> error::Result<()> {
|
||||||
|
self.battery_bar_styles[9] = get_style_from_config(colour)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ lazy_static! {
|
||||||
("magenta", Color::Magenta),
|
("magenta", Color::Magenta),
|
||||||
("cyan", Color::Cyan),
|
("cyan", Color::Cyan),
|
||||||
("gray", Color::Gray),
|
("gray", Color::Gray),
|
||||||
|
("grey", Color::Gray),
|
||||||
("darkgray", Color::DarkGray),
|
("darkgray", Color::DarkGray),
|
||||||
("lightred", Color::LightRed),
|
("lightred", Color::LightRed),
|
||||||
("lightgreen", Color::LightGreen),
|
("lightgreen", Color::LightGreen),
|
||||||
|
|
|
@ -143,10 +143,10 @@ impl BatteryDisplayWidget for Painter {
|
||||||
item.iter(),
|
item.iter(),
|
||||||
if itx == 0 {
|
if itx == 0 {
|
||||||
let colour_index = ((charge_percentage
|
let colour_index = ((charge_percentage
|
||||||
* self.colours.battery_bar_styles.len() as f64
|
* self.colours.battery_bar_styles.len() as f64)
|
||||||
- 1.0)
|
|
||||||
/ 100.0)
|
/ 100.0)
|
||||||
.floor() as usize;
|
.ceil() as usize
|
||||||
|
- 1;
|
||||||
*self
|
*self
|
||||||
.colours
|
.colours
|
||||||
.battery_bar_styles
|
.battery_bar_styles
|
||||||
|
|
|
@ -220,7 +220,12 @@ impl CpuGraphWidget for Painter {
|
||||||
self.colours.cpu_colour_styles[cpu_widget_state
|
self.colours.cpu_colour_styles[cpu_widget_state
|
||||||
.scroll_state
|
.scroll_state
|
||||||
.current_scroll_position
|
.current_scroll_position
|
||||||
% self.colours.cpu_colour_styles.len()]
|
- 1 // Because of the all position
|
||||||
|
- (if show_avg_cpu {
|
||||||
|
AVG_POSITION
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}) % self.colours.cpu_colour_styles.len()]
|
||||||
})
|
})
|
||||||
.data(&cpu.cpu_data[..])
|
.data(&cpu.cpu_data[..])
|
||||||
.graph_type(tui::widgets::GraphType::Line)]
|
.graph_type(tui::widgets::GraphType::Line)]
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl DiskTableWidget for Painter {
|
||||||
Span::styled(" Disk ", self.colours.widget_title_style),
|
Span::styled(" Disk ", self.colours.widget_title_style),
|
||||||
Span::styled(
|
Span::styled(
|
||||||
format!(
|
format!(
|
||||||
"─{}─ Esc to go back, ",
|
"─{}─ Esc to go back ",
|
||||||
"─".repeat(usize::from(draw_loc.width).saturating_sub(
|
"─".repeat(usize::from(draw_loc.width).saturating_sub(
|
||||||
UnicodeSegmentation::graphemes(TITLE_BASE, true).count() + 2
|
UnicodeSegmentation::graphemes(TITLE_BASE, true).count() + 2
|
||||||
))
|
))
|
||||||
|
|
|
@ -408,7 +408,7 @@ impl ProcessTableWidget for Painter {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: gotop's "x out of y" thing is really nice to help keep track of the scroll position. Add to everything?
|
// FIXME: gotop's "x out of y" thing is really nice to help keep track of the scroll position. Add to everything?
|
||||||
f.render_stateful_widget(
|
f.render_stateful_widget(
|
||||||
Table::new(process_headers.iter(), process_rows)
|
Table::new(process_headers.iter(), process_rows)
|
||||||
.block(process_block)
|
.block(process_block)
|
||||||
|
|
31
src/clap.rs
31
src/clap.rs
|
@ -197,6 +197,36 @@ entire query by default.\n\n",
|
||||||
Sets the location of the config file. Expects a config
|
Sets the location of the config file. Expects a config
|
||||||
file in the TOML format. If it doesn't exist, one is created.\n\n\n",
|
file in the TOML format. If it doesn't exist, one is created.\n\n\n",
|
||||||
);
|
);
|
||||||
|
let color = Arg::with_name("color")
|
||||||
|
.long("color")
|
||||||
|
.takes_value(true)
|
||||||
|
.value_name("COLOR SCHEME")
|
||||||
|
.help("Use a color scheme, use --help for supported values.")
|
||||||
|
.long_help(
|
||||||
|
"\
|
||||||
|
Use a pre-defined color scheme. Currently supported values are:
|
||||||
|
|
||||||
|
+------------------------------------------------------------+
|
||||||
|
| default |
|
||||||
|
+------------------------------------------------------------+
|
||||||
|
| default-light (default but for use with light backgrounds) |
|
||||||
|
+------------------------------------------------------------+
|
||||||
|
| gruvbox (a bright theme with 'retro groove' colors) |
|
||||||
|
+------------------------------------------------------------+
|
||||||
|
| gruvbox-light (gruvbox but for use with light backgrounds) |
|
||||||
|
+------------------------------------------------------------+
|
||||||
|
|
||||||
|
Defaults to \"default\".
|
||||||
|
\n\n",
|
||||||
|
)
|
||||||
|
.possible_values(&[
|
||||||
|
"default",
|
||||||
|
"default-light",
|
||||||
|
"gruvbox",
|
||||||
|
"gruvbox-light",
|
||||||
|
"nord",
|
||||||
|
])
|
||||||
|
.hide_possible_values(true);
|
||||||
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")
|
||||||
|
@ -313,6 +343,7 @@ The minimum is 1s (1000), and defaults to 15s (15000).\n\n\n",
|
||||||
.arg(battery)
|
.arg(battery)
|
||||||
.arg(case_sensitive)
|
.arg(case_sensitive)
|
||||||
.arg(config_location)
|
.arg(config_location)
|
||||||
|
.arg(color)
|
||||||
.arg(debug)
|
.arg(debug)
|
||||||
.arg(default_time_value)
|
.arg(default_time_value)
|
||||||
.arg(default_widget_count)
|
.arg(default_widget_count)
|
||||||
|
|
121
src/constants.rs
121
src/constants.rs
|
@ -1,5 +1,7 @@
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use crate::options::ConfigColours;
|
||||||
|
|
||||||
// Default widget ID
|
// Default widget ID
|
||||||
pub const DEFAULT_WIDGET_ID: u64 = 56709;
|
pub const DEFAULT_WIDGET_ID: u64 = 56709;
|
||||||
|
|
||||||
|
@ -37,6 +39,125 @@ lazy_static! {
|
||||||
tui::style::Style::default().fg(tui::style::Color::LightBlue);
|
tui::style::Style::default().fg(tui::style::Color::LightBlue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Colour profiles
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref DEFAULT_LIGHT_MODE_COLOUR_PALETTE: ConfigColours = ConfigColours {
|
||||||
|
text_color: Some("black".to_string()),
|
||||||
|
border_color: Some("black".to_string()),
|
||||||
|
table_header_color: Some("black".to_string()),
|
||||||
|
widget_title_color: Some("black".to_string()),
|
||||||
|
selected_text_color: Some("white".to_string()),
|
||||||
|
graph_color: Some("black".to_string()),
|
||||||
|
disabled_text_color: Some("gray".to_string()),
|
||||||
|
..ConfigColours::default()
|
||||||
|
};
|
||||||
|
pub static ref GRUVBOX_COLOUR_PALETTE: ConfigColours = ConfigColours {
|
||||||
|
table_header_color: Some("#ebdbb2".to_string()),
|
||||||
|
all_cpu_color: Some("#cc241d".to_string()),
|
||||||
|
avg_cpu_color: Some("#98971a".to_string()),
|
||||||
|
cpu_core_colors: Some(vec![
|
||||||
|
"#d79921".to_string(),
|
||||||
|
"#458588".to_string(),
|
||||||
|
"#b16286".to_string(),
|
||||||
|
"#689d6a".to_string(),
|
||||||
|
"#fb4934".to_string(),
|
||||||
|
"#b8bb26".to_string(),
|
||||||
|
"#fe8019".to_string(),
|
||||||
|
"#fabd2f".to_string(),
|
||||||
|
"#83a598".to_string(),
|
||||||
|
"#d3869b".to_string(),
|
||||||
|
"#8ec07c".to_string(),
|
||||||
|
"#d65d0e".to_string(),
|
||||||
|
"#fbf1c7".to_string(),
|
||||||
|
"#ebdbb2".to_string(),
|
||||||
|
"#d5c4a1".to_string(),
|
||||||
|
"#bdae93".to_string(),
|
||||||
|
"#a89984".to_string(),
|
||||||
|
]),
|
||||||
|
ram_color: Some("#458588".to_string()),
|
||||||
|
swap_color: Some("#fabd2f".to_string()),
|
||||||
|
rx_color: Some("#458588".to_string()),
|
||||||
|
tx_color: Some("#fabd2f".to_string()),
|
||||||
|
rx_total_color: Some("#83a598".to_string()),
|
||||||
|
tx_total_color: Some("#d79921".to_string()),
|
||||||
|
border_color: Some("#ebdbb2".to_string()),
|
||||||
|
highlighted_border_color: Some("#fe8019".to_string()),
|
||||||
|
disabled_text_color: Some("#665c54".to_string()),
|
||||||
|
text_color: Some("#ebdbb2".to_string()),
|
||||||
|
selected_text_color: Some("#1d2021".to_string()),
|
||||||
|
selected_bg_color: Some("#ebdbb2".to_string()),
|
||||||
|
widget_title_color: Some("#ebdbb2".to_string()),
|
||||||
|
graph_color: Some("#ebdbb2".to_string()),
|
||||||
|
high_battery_color: Some("#98971a".to_string()),
|
||||||
|
medium_battery_color: Some("#fabd2f".to_string()),
|
||||||
|
low_battery_color: Some("#fb4934".to_string())
|
||||||
|
};
|
||||||
|
pub static ref GRUVBOX_LIGHT_COLOUR_PALETTE: ConfigColours = ConfigColours {
|
||||||
|
table_header_color: Some("#3c3836".to_string()),
|
||||||
|
all_cpu_color: Some("#cc241d".to_string()),
|
||||||
|
avg_cpu_color: Some("#98971a".to_string()),
|
||||||
|
cpu_core_colors: Some(vec![
|
||||||
|
"#d79921".to_string(),
|
||||||
|
"#458588".to_string(),
|
||||||
|
"#b16286".to_string(),
|
||||||
|
"#689d6a".to_string(),
|
||||||
|
"#fb4934".to_string(),
|
||||||
|
"#b8bb26".to_string(),
|
||||||
|
"#fe8019".to_string(),
|
||||||
|
"#fabd2f".to_string(),
|
||||||
|
"#83a598".to_string(),
|
||||||
|
"#d3869b".to_string(),
|
||||||
|
"#8ec07c".to_string(),
|
||||||
|
"#d65d0e".to_string(),
|
||||||
|
"#928374".to_string(),
|
||||||
|
"#665c54".to_string(),
|
||||||
|
"#504945".to_string(),
|
||||||
|
"#3c3836".to_string(),
|
||||||
|
"#282828".to_string(),
|
||||||
|
]),
|
||||||
|
ram_color: Some("#458588".to_string()),
|
||||||
|
swap_color: Some("#cc241d".to_string()),
|
||||||
|
rx_color: Some("#458588".to_string()),
|
||||||
|
tx_color: Some("#cc241d".to_string()),
|
||||||
|
rx_total_color: Some("#83a598".to_string()),
|
||||||
|
tx_total_color: Some("#9d0006".to_string()),
|
||||||
|
border_color: Some("#3c3836".to_string()),
|
||||||
|
highlighted_border_color: Some("#fe8019".to_string()),
|
||||||
|
disabled_text_color: Some("#665c54".to_string()),
|
||||||
|
text_color: Some("#3c3836".to_string()),
|
||||||
|
selected_text_color: Some("#f9f5d7".to_string()),
|
||||||
|
selected_bg_color: Some("#665c54".to_string()),
|
||||||
|
widget_title_color: Some("#3c3836".to_string()),
|
||||||
|
graph_color: Some("#3c3836".to_string()),
|
||||||
|
high_battery_color: Some("#98971a".to_string()),
|
||||||
|
medium_battery_color: Some("#fabd2f".to_string()),
|
||||||
|
low_battery_color: Some("#fb4934".to_string())
|
||||||
|
};
|
||||||
|
// pub static ref NORD_COLOUR_PALETTE: ConfigColours = ConfigColours {
|
||||||
|
// table_header_color: None,
|
||||||
|
// all_cpu_color: None,
|
||||||
|
// avg_cpu_color: None,
|
||||||
|
// cpu_core_colors: None,
|
||||||
|
// ram_color: None,
|
||||||
|
// swap_color: None,
|
||||||
|
// rx_color: None,
|
||||||
|
// tx_color: None,
|
||||||
|
// rx_total_color: None,
|
||||||
|
// tx_total_color: None,
|
||||||
|
// border_color: None,
|
||||||
|
// highlighted_border_color: None,
|
||||||
|
// text_color: None,
|
||||||
|
// selected_text_color: None,
|
||||||
|
// selected_bg_color: None,
|
||||||
|
// widget_title_color: None,
|
||||||
|
// graph_color: None,
|
||||||
|
// high_battery_color: None,
|
||||||
|
// medium_battery_color: None,
|
||||||
|
// low_battery_color: None,
|
||||||
|
// disabled_text_color: None,
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: [HELP] I wanna update this before release... it's missing mouse too.
|
// FIXME: [HELP] I wanna update this before release... it's missing mouse too.
|
||||||
// Help text
|
// Help text
|
||||||
pub const HELP_CONTENTS_TEXT: [&str; 8] = [
|
pub const HELP_CONTENTS_TEXT: [&str; 8] = [
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{borrow::Cow, time::Instant};
|
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
|
str::FromStr,
|
||||||
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{layout_manager::*, *},
|
app::{layout_manager::*, *},
|
||||||
|
canvas::ColourScheme,
|
||||||
constants::*,
|
constants::*,
|
||||||
utils::error::{self, BottomError},
|
utils::error::{self, BottomError},
|
||||||
};
|
};
|
||||||
|
@ -112,6 +115,9 @@ pub struct ConfigFlags {
|
||||||
#[builder(default, setter(strip_option))]
|
#[builder(default, setter(strip_option))]
|
||||||
pub no_write: Option<bool>,
|
pub no_write: Option<bool>,
|
||||||
|
|
||||||
|
#[builder(default, setter(strip_option))]
|
||||||
|
pub color: Option<String>,
|
||||||
|
|
||||||
// This is a huge hack to enable hashmap functionality WITHOUT being able to serializing the field.
|
// This is a huge hack to enable hashmap functionality WITHOUT being able to serializing the field.
|
||||||
// Basically, keep a hashmap in the struct, and convert to a vector every time.
|
// Basically, keep a hashmap in the struct, and convert to a vector every time.
|
||||||
#[builder(default, setter(strip_option))]
|
#[builder(default, setter(strip_option))]
|
||||||
|
@ -164,16 +170,19 @@ pub struct ConfigColours {
|
||||||
pub swap_color: Option<String>,
|
pub swap_color: Option<String>,
|
||||||
pub rx_color: Option<String>,
|
pub rx_color: Option<String>,
|
||||||
pub tx_color: Option<String>,
|
pub tx_color: Option<String>,
|
||||||
pub rx_total_color: Option<String>,
|
pub rx_total_color: Option<String>, // These only affect basic mode.
|
||||||
pub tx_total_color: Option<String>,
|
pub tx_total_color: Option<String>, // These only affect basic mode.
|
||||||
pub border_color: Option<String>,
|
pub border_color: Option<String>,
|
||||||
pub highlighted_border_color: Option<String>,
|
pub highlighted_border_color: Option<String>,
|
||||||
|
pub disabled_text_color: Option<String>,
|
||||||
pub text_color: Option<String>,
|
pub text_color: Option<String>,
|
||||||
pub selected_text_color: Option<String>,
|
pub selected_text_color: Option<String>,
|
||||||
pub selected_bg_color: Option<String>,
|
pub selected_bg_color: Option<String>,
|
||||||
pub widget_title_color: Option<String>,
|
pub widget_title_color: Option<String>,
|
||||||
pub graph_color: Option<String>,
|
pub graph_color: Option<String>,
|
||||||
pub battery_colors: Option<Vec<String>>,
|
pub high_battery_color: Option<String>,
|
||||||
|
pub medium_battery_color: Option<String>,
|
||||||
|
pub low_battery_color: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||||
|
@ -803,7 +812,7 @@ fn get_disable_click(matches: &clap::ArgMatches<'static>, config: &Config) -> bo
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_use_old_network_legend(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
fn get_use_old_network_legend(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||||
if matches.is_present("use_old_network_legend") {
|
if matches.is_present("use_old_network_legend") {
|
||||||
return true;
|
return true;
|
||||||
} else if let Some(flags) = &config.flags {
|
} else if let Some(flags) = &config.flags {
|
||||||
|
@ -814,7 +823,7 @@ pub fn get_use_old_network_legend(matches: &clap::ArgMatches<'static>, config: &
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_hide_table_gap(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
fn get_hide_table_gap(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||||
if matches.is_present("hide_table_gap") {
|
if matches.is_present("hide_table_gap") {
|
||||||
return true;
|
return true;
|
||||||
} else if let Some(flags) = &config.flags {
|
} else if let Some(flags) = &config.flags {
|
||||||
|
@ -825,7 +834,7 @@ pub fn get_hide_table_gap(matches: &clap::ArgMatches<'static>, config: &Config)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_use_battery(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
fn get_use_battery(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||||
if matches.is_present("battery") {
|
if matches.is_present("battery") {
|
||||||
return true;
|
return true;
|
||||||
} else if let Some(flags) = &config.flags {
|
} else if let Some(flags) = &config.flags {
|
||||||
|
@ -836,7 +845,7 @@ pub fn get_use_battery(matches: &clap::ArgMatches<'static>, config: &Config) ->
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_no_write(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
fn get_no_write(matches: &clap::ArgMatches<'static>, config: &Config) -> bool {
|
||||||
if matches.is_present("no_write") {
|
if matches.is_present("no_write") {
|
||||||
return true;
|
return true;
|
||||||
} else if let Some(flags) = &config.flags {
|
} else if let Some(flags) = &config.flags {
|
||||||
|
@ -847,7 +856,7 @@ pub fn get_no_write(matches: &clap::ArgMatches<'static>, config: &Config) -> boo
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ignore_list(ignore_list: &Option<IgnoreList>) -> error::Result<Option<Filter>> {
|
fn get_ignore_list(ignore_list: &Option<IgnoreList>) -> error::Result<Option<Filter>> {
|
||||||
if let Some(ignore_list) = ignore_list {
|
if let Some(ignore_list) = ignore_list {
|
||||||
let list: Result<Vec<_>, _> = ignore_list
|
let list: Result<Vec<_>, _> = ignore_list
|
||||||
.list
|
.list
|
||||||
|
@ -888,3 +897,23 @@ pub fn get_ignore_list(ignore_list: &Option<IgnoreList>) -> error::Result<Option
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_color_scheme(
|
||||||
|
matches: &clap::ArgMatches<'static>, config: &Config,
|
||||||
|
) -> error::Result<ColourScheme> {
|
||||||
|
if let Some(color) = matches.value_of("color") {
|
||||||
|
// Highest priority is always command line flags...
|
||||||
|
return ColourScheme::from_str(color);
|
||||||
|
} else if config.colors.is_some() {
|
||||||
|
// Then, give priority to custom colours...
|
||||||
|
return Ok(ColourScheme::Custom);
|
||||||
|
} else if let Some(flags) = &config.flags {
|
||||||
|
// Last priority is config file flags...
|
||||||
|
if let Some(color) = &flags.color {
|
||||||
|
return ColourScheme::from_str(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// And lastly, the final case is just "default".
|
||||||
|
Ok(ColourScheme::Default)
|
||||||
|
}
|
||||||
|
|
|
@ -135,19 +135,6 @@ fn test_invalid_colour_string() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_empty_battery() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
Command::new(get_binary_location())
|
|
||||||
.arg("-C")
|
|
||||||
.arg("./tests/invalid_configs/empty_battery.toml")
|
|
||||||
.assert()
|
|
||||||
.failure()
|
|
||||||
.stderr(predicate::str::contains(
|
|
||||||
"battery colour list must have at least one colour.",
|
|
||||||
));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lone_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
fn test_lone_default_widget_count() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Command::new(get_binary_location())
|
Command::new(get_binary_location())
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[colors]
|
|
||||||
battery_colors=[]
|
|
Loading…
Reference in a new issue