feat(env_var): allow multiple instances (#2797)
Allows displaying multiple instances of the env_var module.
This commit is contained in:
parent
c9249dbe0b
commit
88ed0ed45a
|
@ -977,12 +977,25 @@ format = "via [ $version](cyan bold) "
|
||||||
|
|
||||||
## Environment Variable
|
## Environment Variable
|
||||||
|
|
||||||
The `env_var` module displays the current value of a selected environment variable.
|
The `env_var` module displays the current value of a selected environment variables.
|
||||||
The module will be shown only if any of the following conditions are met:
|
The module will be shown only if any of the following conditions are met:
|
||||||
|
|
||||||
- The `variable` configuration option matches an existing environment variable
|
- The `variable` configuration option matches an existing environment variable
|
||||||
- The `variable` configuration option is not defined, but the `default` configuration option is
|
- The `variable` configuration option is not defined, but the `default` configuration option is
|
||||||
|
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
Multiple environmental variables can be displayed by using a `.`. (see example)
|
||||||
|
If the `variable` configuration option is not set, the module will display value of variable under the name of text after the `.` character.
|
||||||
|
|
||||||
|
Example: following configuration will display value of USER environment variable
|
||||||
|
```toml
|
||||||
|
# ~/.config/starship.toml
|
||||||
|
|
||||||
|
[env_var.USER]
|
||||||
|
default = "unknown user"
|
||||||
|
```
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
| Option | Default | Description |
|
| Option | Default | Description |
|
||||||
|
@ -1013,6 +1026,17 @@ variable = "SHELL"
|
||||||
default = "unknown shell"
|
default = "unknown shell"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Displaying multiple environmental variables:
|
||||||
|
```toml
|
||||||
|
# ~/.config/starship.toml
|
||||||
|
|
||||||
|
[env_var.SHELL]
|
||||||
|
variable = "SHELL"
|
||||||
|
default = "unknown shell"
|
||||||
|
[env_var.USER]
|
||||||
|
default = "unknown user"
|
||||||
|
```
|
||||||
|
|
||||||
## Erlang
|
## Erlang
|
||||||
|
|
||||||
The `erlang` module shows the currently installed version of [Erlang/OTP](https://erlang.org/doc/).
|
The `erlang` module shows the currently installed version of [Erlang/OTP](https://erlang.org/doc/).
|
||||||
|
|
|
@ -342,6 +342,10 @@ impl StarshipConfig {
|
||||||
pub fn get_custom_modules(&self) -> Option<&toml::value::Table> {
|
pub fn get_custom_modules(&self) -> Option<&toml::value::Table> {
|
||||||
self.get_config(&["custom"])?.as_table()
|
self.get_config(&["custom"])?.as_table()
|
||||||
}
|
}
|
||||||
|
/// Get the table of all the registered env_var modules, if any
|
||||||
|
pub fn get_env_var_modules(&self) -> Option<&toml::value::Table> {
|
||||||
|
self.get_config(&["env_var"])?.as_table()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_root_config(&self) -> StarshipRootConfig {
|
pub fn get_root_config(&self) -> StarshipRootConfig {
|
||||||
if let Some(root_config) = &self.config {
|
if let Some(root_config) = &self.config {
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub struct FullConfig<'a> {
|
||||||
dotnet: dotnet::DotnetConfig<'a>,
|
dotnet: dotnet::DotnetConfig<'a>,
|
||||||
elixir: elixir::ElixirConfig<'a>,
|
elixir: elixir::ElixirConfig<'a>,
|
||||||
elm: elm::ElmConfig<'a>,
|
elm: elm::ElmConfig<'a>,
|
||||||
env_var: env_var::EnvVarConfig<'a>,
|
env_var: IndexMap<String, env_var::EnvVarConfig<'a>>,
|
||||||
erlang: erlang::ErlangConfig<'a>,
|
erlang: erlang::ErlangConfig<'a>,
|
||||||
gcloud: gcloud::GcloudConfig<'a>,
|
gcloud: gcloud::GcloudConfig<'a>,
|
||||||
git_branch: git_branch::GitBranchConfig<'a>,
|
git_branch: git_branch::GitBranchConfig<'a>,
|
||||||
|
|
|
@ -105,7 +105,10 @@ impl<'a> ModuleConfig<'a> for StarshipRootConfig<'a> {
|
||||||
"command_timeout" => self.command_timeout.load_config(v),
|
"command_timeout" => self.command_timeout.load_config(v),
|
||||||
"add_newline" => self.add_newline.load_config(v),
|
"add_newline" => self.add_newline.load_config(v),
|
||||||
unknown => {
|
unknown => {
|
||||||
if !ALL_MODULES.contains(&unknown) && unknown != "custom" {
|
if !ALL_MODULES.contains(&unknown)
|
||||||
|
&& unknown != "custom"
|
||||||
|
&& unknown != "env_var"
|
||||||
|
{
|
||||||
log::warn!("Unknown config key '{}'", unknown);
|
log::warn!("Unknown config key '{}'", unknown);
|
||||||
|
|
||||||
let did_you_mean = &[
|
let did_you_mean = &[
|
||||||
|
@ -116,6 +119,7 @@ impl<'a> ModuleConfig<'a> for StarshipRootConfig<'a> {
|
||||||
"add_newline",
|
"add_newline",
|
||||||
// Modules
|
// Modules
|
||||||
"custom",
|
"custom",
|
||||||
|
"env_var",
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.chain(ALL_MODULES.iter())
|
.chain(ALL_MODULES.iter())
|
||||||
|
|
|
@ -3,6 +3,36 @@ use super::{Context, Module};
|
||||||
use crate::config::RootModuleConfig;
|
use crate::config::RootModuleConfig;
|
||||||
use crate::configs::env_var::EnvVarConfig;
|
use crate::configs::env_var::EnvVarConfig;
|
||||||
use crate::formatter::StringFormatter;
|
use crate::formatter::StringFormatter;
|
||||||
|
use crate::segment::Segment;
|
||||||
|
|
||||||
|
/// Creates env_var_module displayer which displays all configured environmental variables
|
||||||
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
|
let config_table = context.config.get_env_var_modules()?;
|
||||||
|
let mut env_modules = config_table
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, config)| config.is_table())
|
||||||
|
.filter_map(|(variable, _)| env_var_module(vec!["env_var", variable], context))
|
||||||
|
.collect::<Vec<Module>>();
|
||||||
|
// Old configuration is present in starship configuration
|
||||||
|
if config_table.iter().any(|(_, config)| !config.is_table()) {
|
||||||
|
if let Some(fallback_env_var_module) = env_var_module(vec!["env_var"], context) {
|
||||||
|
env_modules.push(fallback_env_var_module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(env_var_displayer(env_modules, context))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A utility module to display multiple env_variable modules
|
||||||
|
fn env_var_displayer<'a>(modules: Vec<Module>, context: &'a Context) -> Module<'a> {
|
||||||
|
let mut module = context.new_module("env_var_displayer");
|
||||||
|
|
||||||
|
let module_segments = modules
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|module| module.segments)
|
||||||
|
.collect::<Vec<Segment>>();
|
||||||
|
module.set_segments(module_segments);
|
||||||
|
module
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a module with the value of the chosen environment variable
|
/// Creates a module with the value of the chosen environment variable
|
||||||
///
|
///
|
||||||
|
@ -10,11 +40,20 @@ use crate::formatter::StringFormatter;
|
||||||
/// - env_var.disabled is absent or false
|
/// - env_var.disabled is absent or false
|
||||||
/// - env_var.variable is defined
|
/// - env_var.variable is defined
|
||||||
/// - 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>> {
|
fn env_var_module<'a>(module_config_path: Vec<&str>, context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("env_var");
|
let mut module = context.new_module(&module_config_path.join("."));
|
||||||
let config: EnvVarConfig = EnvVarConfig::try_load(module.config);
|
let config_value = context.config.get_config(&module_config_path);
|
||||||
|
let config = EnvVarConfig::load(config_value.expect(
|
||||||
|
"modules::env_var::module should only be called after ensuring that the module exists",
|
||||||
|
));
|
||||||
|
|
||||||
let env_value = get_env_value(context, config.variable?, config.default)?;
|
if config.disabled {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let variable_name = get_variable_name(module_config_path, &config);
|
||||||
|
|
||||||
|
let env_value = get_env_value(context, variable_name?, config.default)?;
|
||||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||||
formatter
|
formatter
|
||||||
.map_meta(|var, _| match var {
|
.map_meta(|var, _| match var {
|
||||||
|
@ -43,6 +82,19 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
Some(module)
|
Some(module)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_variable_name<'a>(
|
||||||
|
module_config_path: Vec<&'a str>,
|
||||||
|
config: &'a EnvVarConfig,
|
||||||
|
) -> Option<&'a str> {
|
||||||
|
match config.variable {
|
||||||
|
Some(v) => Some(v),
|
||||||
|
None => {
|
||||||
|
let last_element = module_config_path.last()?;
|
||||||
|
Some(*last_element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_env_value(context: &Context, name: &str, default: Option<&str>) -> Option<String> {
|
fn get_env_value(context: &Context, name: &str, default: Option<&str>) -> Option<String> {
|
||||||
match context.get_env(name) {
|
match context.get_env(name) {
|
||||||
Some(value) => Some(value),
|
Some(value) => Some(value),
|
||||||
|
@ -59,18 +111,14 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_config() {
|
fn empty_config() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var").collect();
|
||||||
.config(toml::toml! {
|
|
||||||
[env_var]
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
let expected = None;
|
let expected = None;
|
||||||
|
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defined_variable() {
|
fn fallback_config() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var]
|
||||||
|
@ -83,12 +131,24 @@ mod test {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn defined_variable() {
|
||||||
|
let actual = ModuleRenderer::new("env_var")
|
||||||
|
.config(toml::toml! {
|
||||||
|
[env_var.TEST_VAR]
|
||||||
|
})
|
||||||
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
.collect();
|
||||||
|
let expected = Some(format!("with {} ", style().paint(TEST_VAR_VALUE)));
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn undefined_variable() {
|
fn undefined_variable() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.TEST_VAR]
|
||||||
variable = "TEST_VAR"
|
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let expected = None;
|
let expected = None;
|
||||||
|
@ -100,8 +160,7 @@ mod test {
|
||||||
fn default_has_no_effect() {
|
fn default_has_no_effect() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.TEST_VAR]
|
||||||
variable = "TEST_VAR"
|
|
||||||
default = "N/A"
|
default = "N/A"
|
||||||
})
|
})
|
||||||
.env("TEST_VAR", TEST_VAR_VALUE)
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
@ -115,8 +174,7 @@ mod test {
|
||||||
fn default_takes_effect() {
|
fn default_takes_effect() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.UNDEFINED_TEST_VAR]
|
||||||
variable = "UNDEFINED_TEST_VAR"
|
|
||||||
default = "N/A"
|
default = "N/A"
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -129,8 +187,7 @@ mod test {
|
||||||
fn symbol() {
|
fn symbol() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.TEST_VAR]
|
||||||
variable = "TEST_VAR"
|
|
||||||
format = "with [■ $env_value](black bold dimmed) "
|
format = "with [■ $env_value](black bold dimmed) "
|
||||||
})
|
})
|
||||||
.env("TEST_VAR", TEST_VAR_VALUE)
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
@ -147,8 +204,7 @@ mod test {
|
||||||
fn prefix() {
|
fn prefix() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.TEST_VAR]
|
||||||
variable = "TEST_VAR"
|
|
||||||
format = "with [_$env_value](black bold dimmed) "
|
format = "with [_$env_value](black bold dimmed) "
|
||||||
})
|
})
|
||||||
.env("TEST_VAR", TEST_VAR_VALUE)
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
@ -165,8 +221,7 @@ mod test {
|
||||||
fn suffix() {
|
fn suffix() {
|
||||||
let actual = ModuleRenderer::new("env_var")
|
let actual = ModuleRenderer::new("env_var")
|
||||||
.config(toml::toml! {
|
.config(toml::toml! {
|
||||||
[env_var]
|
[env_var.TEST_VAR]
|
||||||
variable = "TEST_VAR"
|
|
||||||
format = "with [${env_value}_](black bold dimmed) "
|
format = "with [${env_value}_](black bold dimmed) "
|
||||||
})
|
})
|
||||||
.env("TEST_VAR", TEST_VAR_VALUE)
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
@ -179,6 +234,25 @@ mod test {
|
||||||
assert_eq!(expected, actual);
|
assert_eq!(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn display_few() {
|
||||||
|
let actual = ModuleRenderer::new("env_var")
|
||||||
|
.config(toml::toml! {
|
||||||
|
[env_var.TEST_VAR]
|
||||||
|
[env_var.TEST_VAR2]
|
||||||
|
})
|
||||||
|
.env("TEST_VAR", TEST_VAR_VALUE)
|
||||||
|
.env("TEST_VAR2", TEST_VAR_VALUE)
|
||||||
|
.collect();
|
||||||
|
let expected = Some(format!(
|
||||||
|
"with {} with {} ",
|
||||||
|
style().paint(TEST_VAR_VALUE),
|
||||||
|
style().paint(TEST_VAR_VALUE)
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
fn style() -> Style {
|
fn style() -> Style {
|
||||||
// default style
|
// default style
|
||||||
Color::Black.bold().dimmed()
|
Color::Black.bold().dimmed()
|
||||||
|
|
|
@ -75,7 +75,6 @@ use std::time::Instant;
|
||||||
|
|
||||||
pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
||||||
let start: Instant = Instant::now();
|
let start: Instant = Instant::now();
|
||||||
|
|
||||||
let mut m: Option<Module> = {
|
let mut m: Option<Module> = {
|
||||||
match module {
|
match module {
|
||||||
// Keep these ordered alphabetically.
|
// Keep these ordered alphabetically.
|
||||||
|
|
Loading…
Reference in New Issue