summaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
authorZhenhui Xie <xiezh0831@yahoo.co.jp>2020-07-08 06:45:32 +0800
committerGitHub <noreply@github.com>2020-07-07 18:45:32 -0400
commitec76fafff08933f6f31fb99ea974bdb5ae97a0af (patch)
treebb2c822cdf291635f03d27677c419488ecf77f53 /src/modules
parent0f52b7b12e8c1a2060aa873a68032937dfa2c044 (diff)
feat: refactor modules to use format strings (#1374)
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/aws.rs98
-rw-r--r--src/modules/battery.rs92
-rw-r--r--src/modules/character.rs55
-rw-r--r--src/modules/cmd_duration.rs37
-rw-r--r--src/modules/conda.rs34
-rw-r--r--src/modules/crystal.rs31
-rw-r--r--src/modules/custom.rs56
-rw-r--r--src/modules/directory.rs55
-rw-r--r--src/modules/docker_context.rs47
-rw-r--r--src/modules/dotnet.rs91
-rw-r--r--src/modules/elixir.rs44
-rw-r--r--src/modules/elm.rs32
-rw-r--r--src/modules/env_var.rs38
-rw-r--r--src/modules/erlang.rs30
-rw-r--r--src/modules/git_branch.rs64
-rw-r--r--src/modules/git_commit.rs44
-rw-r--r--src/modules/git_state.rs171
-rw-r--r--src/modules/git_status.rs475
-rw-r--r--src/modules/golang.rs36
-rw-r--r--src/modules/hg_branch.rs36
-rw-r--r--src/modules/hostname.rs27
-rw-r--r--src/modules/java.rs30
-rw-r--r--src/modules/jobs.rs44
-rw-r--r--src/modules/julia.rs37
-rw-r--r--src/modules/kubernetes.rs56
-rw-r--r--src/modules/line_break.rs11
-rw-r--r--src/modules/memory_usage.rs87
-rw-r--r--src/modules/mod.rs2
-rw-r--r--src/modules/nim.rs39
-rw-r--r--src/modules/nix_shell.rs58
-rw-r--r--src/modules/nodejs.rs37
-rw-r--r--src/modules/ocaml.rs36
-rw-r--r--src/modules/package.rs46
-rw-r--r--src/modules/php.rs34
-rw-r--r--src/modules/purescript.rs31
-rw-r--r--src/modules/python.rs51
-rw-r--r--src/modules/ruby.rs38
-rw-r--r--src/modules/rust.rs43
-rw-r--r--src/modules/singularity.rs40
-rw-r--r--src/modules/terraform.rs44
-rw-r--r--src/modules/time.rs40
-rw-r--r--src/modules/username.rs36
-rw-r--r--src/modules/zig.rs27
43 files changed, 1602 insertions, 858 deletions
diff --git a/src/modules/aws.rs b/src/modules/aws.rs
index 72df171ad..1248642d4 100644
--- a/src/modules/aws.rs
+++ b/src/modules/aws.rs
@@ -7,7 +7,8 @@ use std::str::FromStr;
use super::{Context, Module, RootModuleConfig};
-use crate::configs::aws::{AwsConfig, AwsItems};
+use crate::configs::aws::AwsConfig;
+use crate::formatter::StringFormatter;
type Profile = String;
type Region = String;
@@ -51,73 +52,64 @@ fn get_aws_profile_and_region() -> (Option<Profile>, Option<Region>) {
env::var("AWS_VAULT")
.or_else(|_| env::var("AWS_PROFILE"))
.ok(),
- env::var("AWS_REGION").ok(),
- env::var("AWS_DEFAULT_REGION").ok(),
- ) {
- (Some(p), Some(_), Some(dr)) => (Some(p), Some(dr)),
- (Some(p), Some(r), None) => (Some(p), Some(r)),
- (None, Some(r), None) => (None, Some(r)),
- (Some(p), None, Some(dr)) => (Some(p), Some(dr)),
- (Some(ref p), None, None) => (Some(p.to_owned()), get_aws_region_from_config(Some(p))),
- (None, None, Some(dr)) => (None, Some(dr)),
- (None, Some(_), Some(dr)) => (None, Some(dr)),
- (None, None, None) => (None, get_aws_region_from_config(None)),
- }
-}
-
-fn get_aws_region() -> Option<Region> {
- match (
- env::var("AWS_REGION").ok(),
- env::var("AWS_DEFAULT_REGION").ok(),
+ env::var("AWS_DEFAULT_REGION")
+ .or_else(|_| env::var("AWS_REGION"))
+ .ok(),
) {
- (Some(r), None) => Some(r),
- (None, Some(dr)) => Some(dr),
- (Some(_), Some(dr)) => Some(dr),
- (None, None) => get_aws_region_from_config(None),
+ (Some(p), Some(r)) => (Some(p), Some(r)),
+ (None, Some(r)) => (None, Some(r)),
+ (Some(ref p), None) => (Some(p.to_owned()), get_aws_region_from_config(Some(p))),
+ (None, None) => (None, get_aws_region_from_config(None)),
}
}
-fn alias_region(region: &str, aliases: &HashMap<String, &str>) -> String {
- match aliases.get(region) {
- None => region.to_string(),
+fn alias_region(region: String, aliases: &HashMap<String, &str>) -> String {
+ match aliases.get(&region) {
+ None => region,
Some(alias) => (*alias).to_string(),
}
}
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- const AWS_PREFIX: &str = "on ";
-
let mut module = context.new_module("aws");
let config: AwsConfig = AwsConfig::try_load(module.config);
- module.set_style(config.style);
-
- module.get_prefix().set_value(AWS_PREFIX);
-
- module.create_segment("symbol", &config.symbol);
- match config.displayed_items {
- AwsItems::All => {
- let (aws_profile, aws_region) = get_aws_profile_and_region();
-
- let aws_segment = match (&aws_profile, &aws_region) {
- (None, None) => return None,
- (Some(p), Some(r)) => format!("{}({})", p, alias_region(r, &config.region_aliases)),
- (Some(p), None) => p.to_string(),
- (None, Some(r)) => alias_region(r, &config.region_aliases),
- };
- module.create_segment("all", &config.region.with_value(&aws_segment));
- }
- AwsItems::Profile => {
- let aws_profile = env::var("AWS_PROFILE").ok()?;
+ let (aws_profile, aws_region) = get_aws_profile_and_region();
+ if aws_profile.is_none() && aws_region.is_none() {
+ return None;
+ }
- module.create_segment("profile", &config.profile.with_value(&aws_profile));
- }
- AwsItems::Region => {
- let aws_region = alias_region(&get_aws_region()?, &config.region_aliases);
+ let mapped_region = if let Some(aws_region) = aws_region {
+ Some(alias_region(aws_region, &config.region_aliases))
+ } else {
+ None
+ };
- module.create_segment("region", &config.region.with_value(&aws_region));
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|variable, _| match variable {
+ "symbol" => Some(config.symbol),
+ _ => None,
+ })
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "profile" => aws_profile.as_ref().map(Ok),
+ "region" => mapped_region.as_ref().map(Ok),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::error!("Error in module `aws`: \n{}", error);
+ return None;
}
- };
+ });
Some(module)
}
diff --git a/src/modules/battery.rs b/src/modules/battery.rs
index 55e248e57..0ce96d8cc 100644
--- a/src/modules/battery.rs
+++ b/src/modules/battery.rs
@@ -1,6 +1,8 @@
use super::{Context, Module, RootModuleConfig, Shell};
use crate::configs::battery::BatteryConfig;
+use crate::formatter::StringFormatter;
+
/// Creates a module for the battery percentage and charging state
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// TODO: Update when v1.0 printing refactor is implemented to only
@@ -14,60 +16,58 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let BatteryStatus { state, percentage } = battery_status;
let mut module = context.new_module("battery");
- let battery_config: BatteryConfig = BatteryConfig::try_load(module.config);
+ let config: BatteryConfig = BatteryConfig::try_load(module.config);
- // Parse config under `display`
- let display_styles = &battery_config.display;
- let display_style = display_styles
+ // Parse config under `display`.
+ // Select the first style that match the threshold,
+ // if all thresholds are lower do not display battery module.
+ let display_style = config
+ .display
.iter()
- .find(|display_style| percentage <= display_style.threshold as f32);
+ .find(|display_style| percentage <= display_style.threshold as f32)?;
- if let Some(display_style) = display_style {
- // Set style based on percentage
- module.set_style(display_style.style);
- module.get_prefix().set_value("");
+ // Parse the format string and build the module
+ match StringFormatter::new(config.format) {
+ Ok(formatter) => {
+ let formatter = formatter
+ .map_meta(|variable, _| match variable {
+ "symbol" => match state {
+ battery::State::Full => Some(config.full_symbol),
+ battery::State::Charging => Some(config.charging_symbol),
+ battery::State::Discharging => Some(config.discharging_symbol),
+ battery::State::Unknown => config.unknown_symbol,
+ battery::State::Empty => config.empty_symbol,
+ _ => {
+ log::debug!("Unhandled battery state `{}`", state);
+ None
+ }
+ },
+ _ => None,
+ })
+ .map_style(|style| match style {
+ "style" => Some(Ok(display_style.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "percentage" => Some(Ok(format!("{}{}", percentage.round(), percentage_char))),
+ _ => None,
+ });
- match state {
- battery::State::Full => {
- module.create_segment("full_symbol", &battery_config.full_symbol);
- }
- battery::State::Charging => {
- module.create_segment("charging_symbol", &battery_config.charging_symbol);
- }
- battery::State::Discharging => {
- module.create_segment("discharging_symbol", &battery_config.discharging_symbol);
- }
- battery::State::Unknown => {
- log::debug!("Unknown detected");
- if let Some(unknown_symbol) = battery_config.unknown_symbol {
- module.create_segment("unknown_symbol", &unknown_symbol);
+ match formatter.parse(None) {
+ Ok(format_string) => {
+ module.set_segments(format_string);
+ Some(module)
}
- }
- battery::State::Empty => {
- if let Some(empty_symbol) = battery_config.empty_symbol {
- module.create_segment("empty_symbol", &empty_symbol);
+ Err(e) => {
+ log::warn!("Cannot parse `battery.format`: {}", e);
+ None
}
}
- _ => {
- log::debug!("Unhandled battery state `{}`", state);
- return None;
- }
}
-
- let mut percent_string = Vec::<String>::with_capacity(2);
- // Round the percentage to a whole number
- percent_string.push(percentage.round().to_string());
- percent_string.push(percentage_char.to_string());
- module.create_segment(
- "percentage",
- &battery_config
- .percentage
- .with_value(percent_string.join("").as_ref()),
- );
-
- Some(module)
- } else {
- None
+ Err(e) => {
+ log::warn!("Cannot load `battery.format`: {}", e);
+ None
+ }
}
}
diff --git a/src/modules/character.rs b/src/modules/character.rs
index e0c0ffe9e..fc4351951 100644
--- a/src/modules/character.rs
+++ b/src/modules/character.rs
@@ -1,14 +1,15 @@
use super::{Context, Module, RootModuleConfig, Shell};
use crate::configs::character::CharacterConfig;
+use crate::formatter::StringFormatter;
/// Creates a module for the prompt character
///
-/// The character segment prints an arrow character in a color dependant on the exit-
-/// code of the last executed command:
-/// - If the exit-code was "0", the arrow will be formatted with `style_success`
-/// (green by default)
-/// - If the exit-code was anything else, the arrow will be formatted with
-/// `style_failure` (red by default)
+/// The character segment prints an arrow character in a color dependant on the
+/// exit-code of the last executed command:
+/// - If the exit-code was "0", it will be formatted with `success_symbol`
+/// (green arrow by default)
+/// - If the exit-code was anything else, it will be formatted with
+/// `error_symbol` (red arrow by default)
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
enum ShellEditMode {
Normal,
@@ -19,12 +20,11 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("character");
let config: CharacterConfig = CharacterConfig::try_load(module.config);
- module.get_prefix().set_value("");
let props = &context.properties;
- let exit_code_default = std::string::String::from("0");
+ let exit_code_default = String::from("0");
let exit_code = props.get("status_code").unwrap_or(&exit_code_default);
- let keymap_default = std::string::String::from("viins");
+ let keymap_default = String::from("viins");
let keymap = props.get("keymap").unwrap_or(&keymap_default);
let exit_success = exit_code == "0";
@@ -38,22 +38,33 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => ASSUMED_MODE,
};
- if exit_success {
- module.set_style(config.style_success);
- } else {
- module.set_style(config.style_failure);
+ let symbol = match mode {
+ ShellEditMode::Normal => config.vicmd_symbol,
+ ShellEditMode::Insert => {
+ if exit_success {
+ config.success_symbol
+ } else {
+ config.error_symbol
+ }
+ }
};
- /* If an error symbol is set in the config, use symbols to indicate
- success/failure, in addition to color */
- if config.use_symbol_for_status && !exit_success {
- module.create_segment("error_symbol", &config.error_symbol)
- } else {
- match mode {
- ShellEditMode::Normal => module.create_segment("vicmd_symbol", &config.vicmd_symbol),
- ShellEditMode::Insert => module.create_segment("symbol", &config.symbol),
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|variable, _| match variable {
+ "symbol" => Some(symbol),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::warn!("Error in module `character`:\n{}", error);
+ return None;
}
- };
+ });
Some(module)
}
diff --git a/src/modules/cmd_duration.rs b/src/modules/cmd_duration.rs
index 3555701d6..3a10f8f13 100644
--- a/src/modules/cmd_duration.rs
+++ b/src/modules/cmd_duration.rs
@@ -1,7 +1,7 @@
-use super::{Context, Module, SegmentConfig};
+use super::{Context, Module, RootModuleConfig};
-use crate::config::RootModuleConfig;
use crate::configs::cmd_duration::CmdDurationConfig;
+use crate::formatter::StringFormatter;
/// Outputs the time it took the last command to execute
///
@@ -28,19 +28,30 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
- let config_min = config.min_time as u128;
+ if elapsed < config.min_time as u128 {
+ return None;
+ }
- let module_color = match elapsed {
- time if time < config_min => return None,
- _ => config.style,
- };
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "duration" => Some(Ok(render_time(elapsed, config.show_milliseconds))),
+ _ => None,
+ })
+ .parse(None)
+ });
- module.set_style(module_color);
- module.create_segment(
- "cmd_duration",
- &SegmentConfig::new(&render_time(elapsed, config.show_milliseconds)),
- );
- module.get_prefix().set_value(config.prefix);
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::warn!("Error in module `cmd_duration`: \n{}", error);
+ return None;
+ }
+ });
Some(module)
}
diff --git a/src/modules/conda.rs b/src/modules/conda.rs
index 13c57874a..635e8f358 100644
--- a/src/modules/conda.rs
+++ b/src/modules/conda.rs
@@ -1,10 +1,10 @@
use std::env;
-use super::{Context, Module};
+use super::{Context, Module, RootModuleConfig};
use super::utils::directory::truncate;
-use crate::config::RootModuleConfig;
use crate::configs::conda::CondaConfig;
+use crate::formatter::StringFormatter;
/// Creates a module with the current Conda environment
///
@@ -17,14 +17,34 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
let mut module = context.new_module("conda");
- let config = CondaConfig::try_load(module.config);
+ let config: CondaConfig = CondaConfig::try_load(module.config);
let conda_env = truncate(conda_env, config.truncation_length);
- module.set_style(config.style);
-
- module.create_segment("symbol", &config.symbol);
- module.create_segment("environment", &config.environment.with_value(&conda_env));
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|variable, _| match variable {
+ "symbol" => Some(config.symbol),
+ _ => None,
+ })
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "environment" => Some(Ok(conda_env.as_str())),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::warn!("Error in module `conda`:\n{}", error);
+ return None;
+ }
+ });
Some(module)
}
diff --git a/src/modules/crystal.rs b/src/modules/crystal.rs
index 322631ff0..0aad994ac 100644
--- a/src/modules/crystal.rs
+++ b/src/modules/crystal.rs
@@ -1,6 +1,7 @@
-use super::{Context, Module, RootModuleConfig, SegmentConfig};
+use super::{Context, Module, RootModuleConfig};
use crate::configs::crystal::CrystalConfig;
+use crate::formatter::StringFormatter;
use crate::utils;
/// Creates a module with the current Crystal version
@@ -20,14 +21,34 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
}
let crystal_version = utils::exec_cmd("crystal", &["--version"])?.stdout;
- let formatted_version = format_crystal_version(&crystal_version)?;
let mut module = context.new_module("crystal");
let config: CrystalConfig = CrystalConfig::try_load(module.config);
- module.set_style(config.style);
- module.create_segment("symbol", &config.symbol);
- module.create_segment("version", &SegmentConfig::new(&formatted_version));
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|variable, _| match variable {
+ "symbol" => Some(config.symbol),
+ _ => None,
+ })
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ "version" => format_crystal_version(&crystal_version).map(Ok),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::warn!("Error in module `crystal`:\n{}", error);
+ return None;
+ }
+ });
Some(module)
}
diff --git a/src/modules/custom.rs b/src/modules/custom.rs
index 51a3a49a5..bb28b49af 100644
--- a/src/modules/custom.rs
+++ b/src/modules/custom.rs
@@ -1,10 +1,9 @@
-use ansi_term::Color;
use std::io::Write;
use std::process::{Command, Output, Stdio};
use super::{Context, Module, RootModuleConfig};
-use crate::{config::SegmentConfig, configs::custom::CustomConfig};
+use crate::{configs::custom::CustomConfig, formatter::StringFormatter};
/// Creates a custom module with some configuration
///
@@ -13,7 +12,7 @@ use crate::{config::SegmentConfig, configs::custom::CustomConfig};
/// command can be run -- if its result is 0, the module will be shown.
///
/// Finally, the content of the module itself is also set by a command.
-pub fn module<'a>(name: &'a str, context: &'a Context) -> Option<Module<'a>> {
+pub fn module<'a>(name: &str, context: &'a Context) -> Option<Module<'a>> {
let toml_config = context.config.get_custom_module_config(name).expect(
"modules::custom::module should only be called after ensuring that the module exists",
);
@@ -44,35 +43,42 @@ pub fn module<'a>(name: &'a str, context: &'a Context) -> Option<Module<'a>> {
}
let mut module = Module::new(name, config.description, Some(toml_config));
- let style = config.style.unwrap_or_else(|| Color::Green.bold());
- if let Some(prefix) = config.prefix {
- module.get_prefix().set_value(prefix);
- }
- if let Some(suffix) = config.suffix {
- module.get_suffix().set_value(suffix);
- }
+ let output = exec_command(config.command, &config.shell.0)?;
- if let Some(symbol) = config.symbol {
- module.create_segment("symbol", &symbol);
+ let trimmed = output.trim();
+ if trimmed.is_empty() {
+ return None;
}
- if let Some(output) = exec_command(config.command, &config.shell.0) {
- let trimmed = output.trim();
-
- if trimmed.is_empty() {
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_meta(|var, _| match var {
+ "symbol" => Some(config.symbol),
+ _ => None,
+ })
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+ })
+ .map(|variable| match variable {
+ // This may result in multiple calls to `get_module_version` when a user have
+ // multiple `$version` variables defined in `format`.
+ "output" => Some(Ok(trimmed)),
+ _ => None,
+ })
+ .parse(None)
+ });
+
+ module.set_segments(match parsed {
+ Ok(segments) => segments,
+ Err(error) => {
+ log::warn!("Error in module `custom.{}`:\n{}", name, error);
return None;
}
+ });
- module.create_segment(
- "output",
- &SegmentConfig::new(&trimmed).with_style(Some(style)),
- );
-
- Some(module)
- } else {
- None
- }
+ Some(module)
}
/// Return the invoking shell, using `shell` and fallbacking in order to STARSHIP_SHELL and "sh"
diff --git a/src/modules/directory.rs b/src/modules/directory.rs
index 795770622..31f48a2c0 100644
--- a/src/modules/directory.rs
+++ b/src/modules/directory.rs
@@ -7,8 +7,9 @@ use unicode_segmentation::UnicodeSegmentation;
use super::{Context, Module};
use super::utils::directory::truncate;
-use crate::config::{RootModuleConfig, SegmentConfig};
+use crate::config::RootModuleConfig;
use crate::configs::directory::DirectoryConfig;
+use crate::formatter::StringFormatter;
/// Creates a module with the current directory
///
@@ -29,8 +30,6 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("directory");
let config: DirectoryConfig = DirectoryConfig::try_load(module.config);
- module.set_style(config.style);
-
// Using environment PWD is the standard approach for determining logical path
// If this is None for any reason, we fall back to reading the os-provided path
let physical_current_dir = if config.use_logical_path {
@@ -80,33 +79,39 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
// Substitutions could have changed the prefix, so don't allow them and
// fish-style path contraction together
- if config.fish_style_pwd_dir_length > 0 && config.substitutions.is_empty() {
+ let fish_prefix = if config.fish_style_pwd_dir_length > 0 && config.substitutions.is_empty() {
// 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(
+ to_fish_style(
config.fish_style_pwd_dir_length as usize,
contracted_home_dir,
&truncated_dir_string,
- );
-
- module.create_segment(
- "path",
- &SegmentConfig {
- value: &fish_style_dir,
- style: None,
- },
- );
- }
-
- module.create_segment(
- "path",
- &SegmentConfig {
- value: &truncated_dir_string,
- style: None,
- },
- );
-
- module.get_prefix().set_value(config.prefix);
+ )
+ } else {
+ String::from("")
+ };
+ let final_dir_string = format!("{}{}", fish_prefix, truncated_dir_string);
+
+ let parsed = StringFormatter::new(config.format).and_then(|formatter| {
+ formatter
+ .map_style(|variable| match variable {
+ "style" => Some(Ok(config.style)),
+ _ => None,
+