feat: Implement threshold based styling for battery module (#318)

This commit is contained in:
谢祯晖 2019-09-13 02:06:59 +08:00 committed by Matan Kushner
parent 2f94cac5b3
commit a6c64e8457
3 changed files with 120 additions and 40 deletions

View File

@ -110,11 +110,11 @@ The module is only visible when the device's battery is below 10%.
### Options ### Options
| Variable | Default | Description | | Variable | Default | Description |
| -------------------- | ------------ | ------------------------------------------------- | | -------------------- | ------------------------ | ------------------------------------------------- |
| `full_symbol` | `"•"` | The symbol shown when the battery is full. | | `full_symbol` | `"•"` | The symbol shown when the battery is full. |
| `charging_symbol` | `"⇡"` | The symbol shown when the battery is charging. | | `charging_symbol` | `"⇡"` | The symbol shown when the battery is charging. |
| `discharging_symbol` | `"⇣"` | The symbol shown when the battery is discharging. | | `discharging_symbol` | `"⇣"` | The symbol shown when the battery is discharging. |
| `style` | `"bold red"` | The style for the module. | | `display` | [link](#battery-display) | Display threshold and style for the module. |
| `disabled` | `false` | Disables the `battery` module. | | `disabled` | `false` | Disables the `battery` module. |
### Example ### Example
@ -128,6 +128,41 @@ charging_symbol = "⚡️"
discharging_symbol = "💀" discharging_symbol = "💀"
``` ```
### Battery Display
The `display` configuration option is used to define when the battery indicator should be shown (threshold) and what it looks like (style).
If no `display` is provided. The default is as shown:
```toml
[[battery.display]]
threshold = 10
style = "bold red"
```
#### Options
The `display` option is an array of the following table.
| Variable | Description |
|-------------|-------------------------------------------------|
| `threshold` | The upper bound for the display option. |
| `style` | The style used if the display option is in use. |
#### Example
```toml
[[battery.display]] # "bold red" style when capacity is between 0% and 10%
threshold = 10
style = "bold red"
[[battery.display]] # "bold yellow" style when capacity is between 10% and 30%
threshold = 30
style = "bold yellow"
# when capacity is over 30%, the battery indicator will not be displayed
```
## Character ## Character
The `character` module shows a character (usually an arrow) beside where the text The `character` module shows a character (usually an arrow) beside where the text

View File

@ -145,6 +145,11 @@ impl<'a> Module<'a> {
pub fn config_value_style(&self, key: &str) -> Option<Style> { pub fn config_value_style(&self, key: &str) -> Option<Style> {
self.config.and_then(|config| config.get_as_ansi_style(key)) self.config.and_then(|config| config.get_as_ansi_style(key))
} }
/// Get a module's config value as an array
pub fn config_value_array(&self, key: &str) -> Option<&Vec<toml::Value>> {
self.config.and_then(|config| config.get_as_array(key))
}
} }
impl<'a> fmt::Display for Module<'a> { impl<'a> fmt::Display for Module<'a> {

View File

@ -1,13 +1,13 @@
use ansi_term::Color; use ansi_term::{Color, Style};
use super::{Context, Module}; use super::{Context, Module};
use crate::config::Config;
/// Creates a module for the battery percentage and charging state /// Creates a module for the battery percentage and charging state
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> { pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
const BATTERY_FULL: &str = ""; const BATTERY_FULL: &str = "";
const BATTERY_CHARGING: &str = ""; const BATTERY_CHARGING: &str = "";
const BATTERY_DISCHARGING: &str = ""; const BATTERY_DISCHARGING: &str = "";
const BATTERY_THRESHOLD: f32 = 10.0;
// TODO: Update when v1.0 printing refactor is implemented to only // TODO: Update when v1.0 printing refactor is implemented to only
// print escapes in a prompt context. // print escapes in a prompt context.
let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default(); let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
@ -19,21 +19,20 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let battery_status = get_battery_status()?; let battery_status = get_battery_status()?;
let BatteryStatus { state, percentage } = battery_status; let BatteryStatus { state, percentage } = battery_status;
if percentage > BATTERY_THRESHOLD {
log::debug!(
"Battery percentage is higher than threshold ({} > {})",
percentage,
BATTERY_THRESHOLD
);
return None;
}
// TODO: Set style based on percentage when threshold is modifiable
let mut module = context.new_module("battery"); let mut module = context.new_module("battery");
let module_style = module
.config_value_style("style") // Parse config under `display`
.unwrap_or_else(|| Color::Red.bold()); let display_styles = get_display_styles(&module);
module.set_style(module_style); let display_style = display_styles.iter().find(|display_style| {
let BatteryDisplayStyle { threshold, .. } = display_style;
percentage <= *threshold as f32
});
if let Some(display_style) = display_style {
let BatteryDisplayStyle { style, .. } = display_style;
// Set style based on percentage
module.set_style(*style);
module.get_prefix().set_value(""); module.get_prefix().set_value("");
match state { match state {
@ -56,6 +55,31 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
module.new_segment("percentage", percent_string.join("").as_ref()); module.new_segment("percentage", percent_string.join("").as_ref());
Some(module) Some(module)
} else {
None
}
}
fn get_display_styles(module: &Module) -> Vec<BatteryDisplayStyle> {
if let Some(display_configs) = module.config_value_array("display") {
let mut display_styles: Vec<BatteryDisplayStyle> = vec![];
for display_config in display_configs.iter() {
if let toml::Value::Table(config) = display_config {
if let Some(display_style) = BatteryDisplayStyle::from_config(config) {
display_styles.push(display_style);
}
}
}
// Return display styles as long as display array exists, even if it is empty.
display_styles
} else {
// Default display styles: [{ threshold = 10, style = "red bold" }]
vec![BatteryDisplayStyle {
threshold: 10,
style: Color::Red.bold(),
}]
}
} }
fn get_battery_status() -> Option<BatteryStatus> { fn get_battery_status() -> Option<BatteryStatus> {
@ -85,3 +109,19 @@ struct BatteryStatus {
percentage: f32, percentage: f32,
state: battery::State, state: battery::State,
} }
#[derive(Clone, Debug)]
struct BatteryDisplayStyle {
threshold: i64,
style: Style,
}
impl BatteryDisplayStyle {
/// construct battery display style from toml table
pub fn from_config(config: &toml::value::Table) -> Option<BatteryDisplayStyle> {
let threshold = config.get_as_i64("threshold")?;
let style = config.get_as_ansi_style("style")?;
Some(BatteryDisplayStyle { threshold, style })
}
}