refactor: Rewrite cmd_duration, directory and env_var module to use module config (#460)

This PR is a batched rewrite of the following modules:
- cmd_duration
- directory
- env_var
This commit is contained in:
Zhenhui Xie 2019-10-15 19:34:48 +08:00 committed by Matan Kushner
parent 2fd1920f7d
commit be2d5cf1cd
8 changed files with 132 additions and 54 deletions

View File

@ -264,7 +264,7 @@ running `eval $(starship init $0)`, and then proceed as normal.
| Variable | Default | Description | | Variable | Default | Description |
| ---------- | --------------- | ---------------------------------------------------------- | | ---------- | --------------- | ---------------------------------------------------------- |
| `min_time` | `2` | Shortest duration to show time for. | | `min_time` | `2` | Shortest duration to show time for. |
| `prefix` | `took` | Prefix to display immediately before the command duration. | | `prefix` | `took ` | Prefix to display immediately before the command duration. |
| `style` | `"bold yellow"` | The style for the module. | | `style` | `"bold yellow"` | The style for the module. |
| `disabled` | `false` | Disables the `cmd_duration` module. | | `disabled` | `false` | Disables the `cmd_duration` module. |

View File

@ -0,0 +1,23 @@
use crate::config::{ModuleConfig, RootModuleConfig};
use ansi_term::{Color, Style};
use starship_module_config_derive::ModuleConfig;
#[derive(Clone, ModuleConfig)]
pub struct CmdDurationConfig<'a> {
pub min_time: i64,
pub prefix: &'a str,
pub style: Style,
pub disabled: bool,
}
impl<'a> RootModuleConfig<'a> for CmdDurationConfig<'a> {
fn new() -> Self {
CmdDurationConfig {
min_time: 2,
prefix: "took ",
style: Color::Yellow.bold(),
disabled: false,
}
}
}

27
src/configs/directory.rs Normal file
View File

@ -0,0 +1,27 @@
use crate::config::{ModuleConfig, RootModuleConfig};
use ansi_term::{Color, Style};
use starship_module_config_derive::ModuleConfig;
#[derive(Clone, ModuleConfig)]
pub struct DirectoryConfig {
pub truncation_length: i64,
pub truncate_to_repo: bool,
pub fish_style_pwd_dir_length: i64,
pub use_logical_path: bool,
pub style: Style,
pub disabled: bool,
}
impl<'a> RootModuleConfig<'a> for DirectoryConfig {
fn new() -> Self {
DirectoryConfig {
truncation_length: 3,
truncate_to_repo: true,
fish_style_pwd_dir_length: 0,
use_logical_path: true,
style: Color::Cyan.bold(),
disabled: false,
}
}
}

29
src/configs/env_var.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig};
use ansi_term::{Color, Style};
use starship_module_config_derive::ModuleConfig;
#[derive(Clone, ModuleConfig)]
pub struct EnvVarConfig<'a> {
pub symbol: Option<SegmentConfig<'a>>,
pub variable: Option<&'a str>,
pub default: Option<&'a str>,
pub prefix: &'a str,
pub suffix: &'a str,
pub style: Style,
pub disabled: bool,
}
impl<'a> RootModuleConfig<'a> for EnvVarConfig<'a> {
fn new() -> Self {
EnvVarConfig {
symbol: None,
variable: None,
default: None,
prefix: "",
suffix: "",
style: Color::Black.bold().dimmed(),
disabled: false,
}
}
}

View File

@ -1,8 +1,11 @@
pub mod aws; pub mod aws;
pub mod battery; pub mod battery;
pub mod character; pub mod character;
pub mod cmd_duration;
pub mod conda; pub mod conda;
pub mod directory;
pub mod dotnet; pub mod dotnet;
pub mod env_var;
pub mod go; pub mod go;
pub mod hostname; pub mod hostname;
pub mod jobs; pub mod jobs;

View File

@ -1,13 +1,15 @@
use ansi_term::Color;
use super::{Context, Module}; use super::{Context, Module};
use crate::config::RootModuleConfig;
use crate::configs::cmd_duration::CmdDurationConfig;
/// Outputs the time it took the last command to execute /// Outputs the time it took the last command to execute
/// ///
/// Will only print if last command took more than a certain amount of time to /// Will only print if last command took more than a certain amount of time to
/// execute. Default is two seconds, but can be set by config option `min_time`. /// execute. Default is two seconds, but can be set by config option `min_time`.
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> { pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("cmd_duration"); let mut module = context.new_module("cmd_duration");
let config: CmdDurationConfig = CmdDurationConfig::try_load(module.config);
let arguments = &context.arguments; let arguments = &context.arguments;
let elapsed = arguments let elapsed = arguments
@ -16,36 +18,27 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
.parse::<u64>() .parse::<u64>()
.ok()?; .ok()?;
let prefix = module
.config_value_str("prefix")
.unwrap_or("took ")
.to_owned();
let signed_config_min = module.config_value_i64("min_time").unwrap_or(2);
/* TODO: Once error handling is implemented, warn the user if their config /* TODO: Once error handling is implemented, warn the user if their config
min time is nonsensical */ min time is nonsensical */
if signed_config_min < 0 { if config.min_time < 0 {
log::debug!( log::debug!(
"[WARN]: min_time in [cmd_duration] ({}) was less than zero", "[WARN]: min_time in [cmd_duration] ({}) was less than zero",
signed_config_min config.min_time
); );
return None; return None;
} }
let config_min = signed_config_min as u64; let config_min = config.min_time as u64;
let module_color = match elapsed { let module_color = match elapsed {
time if time < config_min => return None, time if time < config_min => return None,
_ => module _ => config.style,
.config_value_style("style")
.unwrap_or_else(|| Color::Yellow.bold()),
}; };
module.set_style(module_color); module.set_style(module_color);
module.new_segment( module.new_segment(
"cmd_duration", "cmd_duration",
&format!("{}{}", prefix, render_time(elapsed)), &format!("{}{}", config.prefix, render_time(elapsed)),
); );
module.get_prefix().set_value(""); module.get_prefix().set_value("");

View File

@ -1,9 +1,11 @@
use ansi_term::Color;
use path_slash::PathExt; use path_slash::PathExt;
use std::path::Path; use std::path::Path;
use super::{Context, Module}; use super::{Context, Module};
use crate::config::{RootModuleConfig, SegmentConfig};
use crate::configs::directory::DirectoryConfig;
/// Creates a module with the current directory /// Creates a module with the current directory
/// ///
/// Will perform path contraction and truncation. /// Will perform path contraction and truncation.
@ -16,27 +18,15 @@ use super::{Context, Module};
/// Paths will be limited in length to `3` path components by default. /// Paths will be limited in length to `3` path components by default.
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> { pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
const HOME_SYMBOL: &str = "~"; const HOME_SYMBOL: &str = "~";
const DIR_TRUNCATION_LENGTH: i64 = 3;
const FISH_STYLE_PWD_DIR_LENGTH: i64 = 0;
let mut module = context.new_module("directory"); let mut module = context.new_module("directory");
let module_color = module let config: DirectoryConfig = DirectoryConfig::try_load(module.config);
.config_value_style("style")
.unwrap_or_else(|| Color::Cyan.bold());
module.set_style(module_color);
let truncation_length = module module.set_style(config.style);
.config_value_i64("truncation_length")
.unwrap_or(DIR_TRUNCATION_LENGTH);
let truncate_to_repo = module.config_value_bool("truncate_to_repo").unwrap_or(true);
let fish_style_pwd_dir_length = module
.config_value_i64("fish_style_pwd_dir_length")
.unwrap_or(FISH_STYLE_PWD_DIR_LENGTH);
// Using environment PWD is the standard approach for determining logical path // Using environment PWD is the standard approach for determining logical path
let use_logical_path = module.config_value_bool("use_logical_path").unwrap_or(true);
// If this is None for any reason, we fall back to reading the os-provided path // If this is None for any reason, we fall back to reading the os-provided path
let logical_current_dir = if use_logical_path { let logical_current_dir = if config.use_logical_path {
match std::env::var("PWD") { match std::env::var("PWD") {
Ok(x) => Some(x), Ok(x) => Some(x),
Err(_) => { Err(_) => {
@ -58,7 +48,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let repo = &context.get_repo().ok()?; let repo = &context.get_repo().ok()?;
let dir_string = match &repo.root { let dir_string = match &repo.root {
Some(repo_root) if truncate_to_repo && (repo_root != &home_dir) => { Some(repo_root) if config.truncate_to_repo && (repo_root != &home_dir) => {
let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap(); let repo_folder_name = repo_root.file_name().unwrap().to_str().unwrap();
// Contract the path to the git repo root // Contract the path to the git repo root
@ -69,21 +59,33 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}; };
// Truncate the dir string to the maximum number of path components // Truncate the dir string to the maximum number of path components
let truncated_dir_string = truncate(dir_string, truncation_length as usize); let truncated_dir_string = truncate(dir_string, config.truncation_length as usize);
if fish_style_pwd_dir_length > 0 { if config.fish_style_pwd_dir_length > 0 {
// If user is using fish style path, we need to add the segment first // If user is using fish style path, we need to add the segment first
let contracted_home_dir = contract_path(&current_dir, &home_dir, HOME_SYMBOL); let contracted_home_dir = contract_path(&current_dir, &home_dir, HOME_SYMBOL);
let fish_style_dir = to_fish_style( let fish_style_dir = to_fish_style(
fish_style_pwd_dir_length as usize, config.fish_style_pwd_dir_length as usize,
contracted_home_dir, contracted_home_dir,
&truncated_dir_string, &truncated_dir_string,
); );
module.new_segment("path", &fish_style_dir); module.create_segment(
"path",
&SegmentConfig {
value: &fish_style_dir,
style: None,
},
);
} }
module.new_segment("path", &truncated_dir_string); module.create_segment(
"path",
&SegmentConfig {
value: &truncated_dir_string,
style: None,
},
);
module.get_prefix().set_value("in "); module.get_prefix().set_value("in ");

View File

@ -1,8 +1,10 @@
use ansi_term::Color;
use std::env; use std::env;
use super::{Context, Module}; use super::{Context, Module};
use crate::config::RootModuleConfig;
use crate::configs::env_var::EnvVarConfig;
/// Creates a module with the value of the chosen environment variable /// Creates a module with the value of the chosen environment variable
/// ///
/// Will display the environment variable's value if all of the following criteria are met: /// Will display the environment variable's value if all of the following criteria are met:
@ -11,23 +13,22 @@ use super::{Context, Module};
/// - a variable named as the value of env_var.variable is defined /// - a variable named as the value of env_var.variable is defined
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> { pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("env_var"); let mut module = context.new_module("env_var");
let module_style = module let config: EnvVarConfig = EnvVarConfig::try_load(module.config);
.config_value_style("style")
.unwrap_or_else(|| Color::Black.bold().dimmed());
let env_name = module.config_value_str("variable")?; let env_value = get_env_value(config.variable?, config.default)?;
let default_value = module.config_value_str("default"); module.set_style(config.style);
let env_value = get_env_value(env_name, default_value)?;
let prefix = module.config_value_str("prefix").unwrap_or("").to_owned();
let suffix = module.config_value_str("suffix").unwrap_or("").to_owned();
module.set_style(module_style);
module.get_prefix().set_value("with "); module.get_prefix().set_value("with ");
module.new_segment_if_config_exists("symbol");
module.new_segment("env_var", &format!("{}{}{}", prefix, env_value, suffix)); if let Some(symbol) = config.symbol {
module.create_segment("symbol", &symbol);
}
// TODO: Use native prefix and suffix instead of stacking custom ones together with env_value.
module.new_segment(
"env_var",
&format!("{}{}{}", config.prefix, env_value, config.suffix),
);
Some(module) Some(module)
} }