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 |
| ---------- | --------------- | ---------------------------------------------------------- |
| `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. |
| `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 battery;
pub mod character;
pub mod cmd_duration;
pub mod conda;
pub mod directory;
pub mod dotnet;
pub mod env_var;
pub mod go;
pub mod hostname;
pub mod jobs;

View File

@ -1,13 +1,15 @@
use ansi_term::Color;
use super::{Context, Module};
use crate::config::RootModuleConfig;
use crate::configs::cmd_duration::CmdDurationConfig;
/// 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
/// execute. Default is two seconds, but can be set by config option `min_time`.
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("cmd_duration");
let config: CmdDurationConfig = CmdDurationConfig::try_load(module.config);
let arguments = &context.arguments;
let elapsed = arguments
@ -16,36 +18,27 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
.parse::<u64>()
.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
min time is nonsensical */
if signed_config_min < 0 {
if config.min_time < 0 {
log::debug!(
"[WARN]: min_time in [cmd_duration] ({}) was less than zero",
signed_config_min
config.min_time
);
return None;
}
let config_min = signed_config_min as u64;
let config_min = config.min_time as u64;
let module_color = match elapsed {
time if time < config_min => return None,
_ => module
.config_value_style("style")
.unwrap_or_else(|| Color::Yellow.bold()),
_ => config.style,
};
module.set_style(module_color);
module.new_segment(
"cmd_duration",
&format!("{}{}", prefix, render_time(elapsed)),
&format!("{}{}", config.prefix, render_time(elapsed)),
);
module.get_prefix().set_value("");

View File

@ -1,9 +1,11 @@
use ansi_term::Color;
use path_slash::PathExt;
use std::path::Path;
use super::{Context, Module};
use crate::config::{RootModuleConfig, SegmentConfig};
use crate::configs::directory::DirectoryConfig;
/// Creates a module with the current directory
///
/// 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.
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
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 module_color = module
.config_value_style("style")
.unwrap_or_else(|| Color::Cyan.bold());
module.set_style(module_color);
let config: DirectoryConfig = DirectoryConfig::try_load(module.config);
let truncation_length = module
.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);
module.set_style(config.style);
// 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
let logical_current_dir = if use_logical_path {
let logical_current_dir = if config.use_logical_path {
match std::env::var("PWD") {
Ok(x) => Some(x),
Err(_) => {
@ -58,7 +48,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let repo = &context.get_repo().ok()?;
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();
// 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
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
let contracted_home_dir = contract_path(&current_dir, &home_dir, HOME_SYMBOL);
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,
&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 ");

View File

@ -1,8 +1,10 @@
use ansi_term::Color;
use std::env;
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
///
/// 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
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("env_var");
let module_style = module
.config_value_style("style")
.unwrap_or_else(|| Color::Black.bold().dimmed());
let config: EnvVarConfig = EnvVarConfig::try_load(module.config);
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");
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.set_style(config.style);
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)
}