summaryrefslogtreecommitdiffstats
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/aws.rs29
-rw-r--r--src/modules/battery.rs137
-rw-r--r--src/modules/character.rs69
-rw-r--r--src/modules/cmd_duration.rs101
-rw-r--r--src/modules/directory.rs312
-rw-r--r--src/modules/env_var.rs43
-rw-r--r--src/modules/git_branch.rs65
-rw-r--r--src/modules/git_state.rs162
-rw-r--r--src/modules/git_status.rs196
-rw-r--r--src/modules/golang.rs82
-rw-r--r--src/modules/hostname.rs41
-rw-r--r--src/modules/java.rs105
-rw-r--r--src/modules/jobs.rs34
-rw-r--r--src/modules/line_break.rs15
-rw-r--r--src/modules/memory_usage.rs91
-rw-r--r--src/modules/mod.rs63
-rw-r--r--src/modules/nix_shell.rs56
-rw-r--r--src/modules/nodejs.rs49
-rw-r--r--src/modules/package.rs166
-rw-r--r--src/modules/python.rs122
-rw-r--r--src/modules/ruby.rs61
-rw-r--r--src/modules/rust.rs291
-rw-r--r--src/modules/time.rs105
-rw-r--r--src/modules/username.rs53
24 files changed, 0 insertions, 2448 deletions
diff --git a/src/modules/aws.rs b/src/modules/aws.rs
deleted file mode 100644
index 65ca05142..000000000
--- a/src/modules/aws.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-use std::env;
-
-use ansi_term::Color;
-
-use super::{Context, Module};
-
-pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- const AWS_CHAR: &str = "☁️ ";
- const AWS_PREFIX: &str = "on ";
-
- let aws_profile = env::var("AWS_PROFILE").ok()?;
- if aws_profile.is_empty() {
- return None;
- }
-
- let mut module = context.new_module("aws");
-
- let module_style = module
- .config_value_style("style")
- .unwrap_or_else(|| Color::Yellow.bold());
- module.set_style(module_style);
-
- module.get_prefix().set_value(AWS_PREFIX);
-
- module.new_segment("symbol", AWS_CHAR);
- module.new_segment("profile", &aws_profile);
-
- Some(module)
-}
diff --git a/src/modules/battery.rs b/src/modules/battery.rs
deleted file mode 100644
index 04b5a2d8a..000000000
--- a/src/modules/battery.rs
+++ /dev/null
@@ -1,137 +0,0 @@
-use ansi_term::{Color, Style};
-
-use super::{Context, Module};
-use crate::config::Config;
-
-/// Creates a module for the battery percentage and charging state
-pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- const BATTERY_FULL: &str = "•";
- const BATTERY_CHARGING: &str = "⇡";
- const BATTERY_DISCHARGING: &str = "⇣";
- // TODO: Update when v1.0 printing refactor is implemented to only
- // print escapes in a prompt context.
- let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
- let percentage_char = match shell.as_str() {
- "zsh" => "%%", // % is an escape in zsh, see PROMPT in `man zshmisc`
- _ => "%",
- };
-
- let battery_status = get_battery_status()?;
- let BatteryStatus { state, percentage } = battery_status;
-
- let mut module = context.new_module("battery");
-
- // Parse config under `display`
- let display_styles = get_display_styles(&module);
- 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("");
-
- match state {
- battery::State::Full => {
- module.new_segment("full_symbol", BATTERY_FULL);
- }
- battery::State::Charging => {
- module.new_segment("charging_symbol", BATTERY_CHARGING);
- }
- battery::State::Discharging => {
- module.new_segment("discharging_symbol", BATTERY_DISCHARGING);
- }
- battery::State::Unknown => {
- log::debug!("Unknown detected");
- module.new_segment_if_config_exists("unknown_symbol")?;
- }
- battery::State::Empty => {
- module.new_segment_if_config_exists("empty_symbol")?;
- }
- _ => {
- 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.new_segment("percentage", percent_string.join("").as_ref());
-
- 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> {
- let battery_manager = battery::Manager::new().ok()?;
- match battery_manager.batteries().ok()?.next() {
- Some(Ok(battery)) => {
- log::debug!("Battery found: {:?}", battery);
- let battery_status = BatteryStatus {
- percentage: battery.state_of_charge().value * 100.0,
- state: battery.state(),
- };
-
- Some(battery_status)
- }
- Some(Err(e)) => {
- log::debug!("Unable to access battery information:\n{}", &e);
- None
- }
- None => {
- log::debug!("No batteries found");
- None
- }
- }
-}
-
-struct BatteryStatus {
- percentage: f32,
- 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 })
- }
-}
diff --git a/src/modules/character.rs b/src/modules/character.rs
deleted file mode 100644
index 9385e53c9..000000000
--- a/src/modules/character.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-use super::{Context, Module};
-use ansi_term::Color;
-
-/// 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)
-pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- const SUCCESS_CHAR: &str = "❯";
- const FAILURE_CHAR: &str = "✖";
- const VICMD_CHAR: &str = "❮";
- enum ShellEditMode {
- Normal,
- Insert,
- };
- const ASSUMED_MODE: ShellEditMode = ShellEditMode::Insert;
- // TODO: extend config to more modes
-
- let mut module = context.new_module("character");
- module.get_prefix().set_value("");
-
- let style_success = module
- .config_value_style("style_success")
- .unwrap_or_else(|| Color::Green.bold());
- let style_failure = module
- .config_value_style("style_failure")
- .unwrap_or_else(|| Color::Red.bold());
-
- let arguments = &context.arguments;
- let use_symbol = module
- .config_value_bool("use_symbol_for_status")
- .unwrap_or(false);
- let exit_success = arguments.value_of("status_code").unwrap_or("0") == "0";
- let shell = std::env::var("STARSHIP_SHELL").unwrap_or_default();
- let keymap = arguments.value_of("keymap").unwrap_or("viins");
-
- // Match shell "keymap" names to normalized vi modes
- // NOTE: in vi mode, fish reports normal mode as "default".
- // Unfortunately, this is also the name of the non-vi default mode.
- // We do some environment detection in src/init.rs to translate.
- // The result: in non-vi fish, keymap is always reported as "insert"
- let mode = match (shell.as_str(), keymap) {
- ("fish", "default") | ("zsh", "vicmd") => ShellEditMode::Normal,
- _ => ASSUMED_MODE,
- };
-
- /* If an error symbol is set in the config, use symbols to indicate
- success/failure, in addition to color */
- let symbol = if use_symbol && !exit_success {
- module.new_segment("error_symbol", FAILURE_CHAR)
- } else {
- match mode {
- ShellEditMode::Normal => module.new_segment("vicmd_symbol", VICMD_CHAR),
- ShellEditMode::Insert => module.new_segment("symbol", SUCCESS_CHAR),
- }
- };
-
- if exit_success {
- symbol.set_style(style_success);
- } else {
- symbol.set_style(style_failure);
- };
-
- Some(module)
-}
diff --git a/src/modules/cmd_duration.rs b/src/modules/cmd_duration.rs
deleted file mode 100644
index 8d4816392..000000000
--- a/src/modules/cmd_duration.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-use ansi_term::Color;
-
-use super::{Context, Module};
-
-/// 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 arguments = &context.arguments;
- let elapsed = arguments
- .value_of("cmd_duration")
- .unwrap_or("invalid_time")
- .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 {
- log::debug!(
- "[WARN]: min_time in [cmd_duration] ({}) was less than zero",
- signed_config_min
- );
- return None;
- }
-
- let config_min = signed_config_min 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()),
- };
-
- module.set_style(module_color);
- module.new_segment(
- "cmd_duration",
- &format!("{}{}", prefix, render_time(elapsed)),
- );
- module.get_prefix().set_value("");
-
- Some(module)
-}
-
-// Render the time into a nice human-readable string
-fn render_time(raw_seconds: u64) -> String {
- // Calculate a simple breakdown into days/hours/minutes/seconds
- let (seconds, raw_minutes) = (raw_seconds % 60, raw_seconds / 60);
- let (minutes, raw_hours) = (raw_minutes % 60, raw_minutes / 60);
- let (hours, days) = (raw_hours % 24, raw_hours / 24);
-
- let components = [days, hours, minutes, seconds];
- let suffixes = ["d", "h", "m", "s"];
-
- let rendered_components: Vec<String> = components
- .iter()
- .zip(&suffixes)
- .map(render_time_component)
- .collect();
- rendered_components.join("")
-}
-
-/// Render a single component of the time string, giving an empty string if component is zero
-fn render_time_component((component, suffix): (&u64, &&str)) -> String {
- match component {
- 0 => String::new(),
- n => format!("{}{}", n, suffix),
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_10s() {
- assert_eq!(render_time(10 as u64), "10s")
- }
- #[test]
- fn test_90s() {
- assert_eq!(render_time(90 as u64), "1m30s")
- }
- #[test]
- fn test_10110s() {
- assert_eq!(render_time(10110 as u64), "2h48m30s")
- }
- #[test]
- fn test_1d() {
- assert_eq!(render_time(86400 as u64), "1d")
- }
-}
diff --git a/src/modules/directory.rs b/src/modules/directory.rs
deleted file mode 100644
index 4bab47c71..000000000
--- a/src/modules/directory.rs
+++ /dev/null
@@ -1,312 +0,0 @@
-use ansi_term::Color;
-use path_slash::PathExt;
-use std::path::Path;
-
-use super::{Context, Module};
-
-/// Creates a module with the current directory
-///
-/// Will perform path contraction and truncation.
-/// **Contraction**
-/// - Paths beginning with the home directory or with a git repo right
-/// inside the home directory will be contracted to `~`
-/// - Paths containing a git repo will contract to begin at the repo root
-///
-/// **Truncation**
-/// 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 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);
-
- // 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 {
- match std::env::var("PWD") {
- Ok(x) => Some(x),
- Err(_) => {
- log::debug!("Asked for logical path, but PWD was invalid.");
- None
- }
- }
- } else {
- None
- };
- let current_dir = logical_current_dir
- .as_ref()
- .map(|d| Path::new(d))
- .unwrap_or_else(|| context.current_dir.as_ref());
-
- let home_dir = dirs::home_dir().unwrap();
- log::debug!("Current directory: {:?}", current_dir);
-
- let repo = &context.get_repo().ok()?;
-
- let dir_string = match &repo.root {
- Some(repo_root) if 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
- contract_path(current_dir, repo_root, repo_folder_name)
- }
- // Contract the path to the home directory
- _ => contract_path(current_dir, &home_dir, HOME_SYMBOL),
- };
-
- // Truncate the dir string to the maximum number of path components
- let truncated_dir_string = truncate(dir_string, truncation_length as usize);
-
- if 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,
- contracted_home_dir,
- &truncated_dir_string,
- );
-
- module.new_segment("path", &fish_style_dir);
- }
-
- module.new_segment("path", &truncated_dir_string);
-
- module.get_prefix().set_value("in ");
-
- Some(module)
-}
-
-/// Contract the root component of a path
-///
-/// Replaces the `top_level_path` in a given `full_path` with the provided
-/// `top_level_replacement`.
-fn contract_path(full_path: &Path, top_level_path: &Path, top_level_replacement: &str) -> String {
- if !full_path.starts_with(top_level_path) {
- return replace_c_dir(full_path.to_slash().unwrap());
- }
-
- if full_path == top_level_path {
- return replace_c_dir(top_level_replacement.to_string());
- }
-
- format!(
- "{replacement}{separator}{path}",
- replacement = top_level_replacement,
- separator = "/",
- path = replace_c_dir(
- full_path
- .strip_prefix(top_level_path)
- .unwrap()
- .to_slash()
- .unwrap()
- )
- )
-}
-
-/// Replaces "C://" with "/c/" within a Windows path
-///
-/// On non-Windows OS, does nothing
-#[cfg(target_os = "windows")]
-fn replace_c_dir(path: String) -> String {
- return path.replace("C:/", "/c");
-}
-
-/// Replaces "C://" with "/c/" within a Windows path
-///
-/// On non-Windows OS, does nothing
-#[cfg(not(target_os = "windows"))]
-const fn replace_c_dir(path: String) -> String {
- path
-}
-
-/// Truncate a path to only have a set number of path components
-///
-/// Will truncate a path to only show the last `length` components in a path.
-/// If a length of `0` is provided, the path will not be truncated.
-fn truncate(dir_string: String, length: usize) -> String {
- if length == 0 {
- return dir_string;
- }
-
- let components = dir_string.split('/').collect::<Vec<&str>>();
- if components.len() <= length {
- return dir_string;
- }
-
- let truncated_components = &components[components.len() - length..];
- truncated_components.join("/")
-}
-
-/// Takes part before contracted path and replaces it with fish style path
-///
-/// Will take the first letter of each directory before the contracted path and
-/// use that in the path instead. See the following example.
-///
-/// Absolute Path: `/Users/Bob/Projects/work/a_repo`
-/// Contracted Path: `a_repo`
-/// With Fish Style: `~/P/w/a_repo`
-///
-/// Absolute Path: `/some/Path/not/in_a/repo/but_nested`
-/// Contracted Path: `in_a/repo/but_nested`
-/// With Fish Style: `/s/P/n/in_a/repo/but_nested`
-fn to_fish_style(pwd_dir_length: usize, dir_string: String, truncated_dir_string: &str) -> String {
- let replaced_dir_string = dir_string.trim_end_matches(truncated_dir_string).to_owned();
- let components = replaced_dir_string.split('/').collect::<Vec<&str>>();
-
- if components.is_empty() {
- return replaced_dir_string;
- }
-
- components
- .into_iter()
- .map(|word| match word {
- "" => "",
- _ if word.len() <= pwd_dir_length => word,
- _ if word.starts_with('.') => &word[..=pwd_dir_length],
- _ => &word[..pwd_dir_length],
- })
- .collect::<Vec<_>>()
- .join("/")
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn contract_home_directory() {
- let full_path = Path::new("/Users/astronaut/schematics/rocket");
- let home = Path::new("/Users/astronaut");
-
- let output = contract_path(full_path, home, "~");
- assert_eq!(output, "~/schematics/rocket");
- }
-
- #[test]
- fn contract_repo_directory() {
- let full_path = Path::new("/Users/astronaut/dev/rocket-controls/src");
- let repo_root = Path::new("/Users/astronaut/dev/rocket-controls");
-
- let output = contract_path(full_path, repo_root, "rocket-controls");
- assert_eq!(output, "rocket-controls/src");
- }
-
- #[test]
- #[cfg(target_os = "windows")]
- fn contract_windows_style_home_directory() {
- let full_path = Path::new("C:\\Users\\astronaut\\schematics\\rocket");
- let home = Path::new("C:\\Users\\astronaut");
-
- let output = contract_path(full_path, home, "~");
- assert_eq!(output, "~/schematics/rocket");
- }
-
- #[test]
- #[cfg(target_os = "windows")]
- fn contract_windows_style_repo_directory() {
- let full_path = Path::new("C:\\Users\\astronaut\\dev\\rocket-controls\\src");
- let repo_root = Path::new("C:\\Users\\astronaut\\dev\\rocket-controls");
-
- let output = contract_path(full_path, repo_root, "rocket-controls");
- assert_eq!(output, "rocket-controls/src");
- }
-
- #[test]
- #[cfg(target_os = "windows")]
- fn contract_windows_style_no_top_level_directory() {
- let full_path = Path::new("C:\\Some\\Other\\Path");
- let top_level_path = Path::new("C:\\Users\\astronaut");
-
- let output = contract_path(full_path, top_level_path, "~");
- assert_eq!(output, "/c/Some/Other/Path");
- }
-
- #[test]
- #[cfg(target_os = "windows")]
- fn contract_windows_style_root_directory() {
- let full_path = Path::new("C:\\");
- let top_level_path = Path::new("C:\\Users\\astronaut");
-
- let output = contract_path(full_path, top_level_path, "~");
- assert_eq!(output, "/c");
- }
-
- #[test]
- fn truncate_smaller_path_than_provided_length() {
- let path = "~/starship";
- let output = truncate(path.to_string(), 3);
- assert_eq!(output, "~/starship")
- }
-
- #[test]
- fn truncate_same_path_as_provided_length() {
- let path = "~/starship/engines";
- let output = truncate(path.to_string(), 3);
- assert_eq!(output, "~/starship/engines")
- }
-
- #[test]
- fn truncate_slightly_larger_path_than_provided_length() {
- let path = "~/starship/engines/booster";
- let output = truncate(path.to_string(), 3);
- assert_eq!(output, "starship/engines/booster")
- }
-
- #[test]
- fn truncate_larger_path_than_provided_length() {
- let path = "~/starship/engines/booster/rocket";
- let output = truncate(path.to_string(), 3);
- assert_eq!(output, "engines/booster/rocket")
- }
-
- #[test]
- fn fish_style_with_user_home_contracted_path() {
- let path = "~/starship/engines/booster/rocket";
- let output = to_fish_style(1, path.to_string(), "engines/booster/rocket");
- assert_eq!(output, "~/s/");
- }
-
- #[test]
- fn fish_style_with_user_home_contracted_path_and_dot_dir() {
- let path = "~/.starship/engines/booster/rocket";
- let output = to_fish_style(1, path.to_string(), "engines/booster/rocket");
- assert_eq!(output, "~/.s/");
- }
-
- #[test]
- fn fish_style_with_no_contracted_path() {
- // `truncatation_length = 2`
- let path = "/absolute/Path/not/in_a/repo/but_nested";
- let output = to_fish_style(1, path.to_string(), "repo/but_nested");
- assert_eq!(output, "/a/P/n/i/");
- }
-
- #[test]
- fn fish_style_with_pwd_dir_len_no_contracted_path() {
- // `truncatation_length = 2`
- let path = "/absolute/Path/not/in_a/repo/but_nested";
- let output = to_fish_style(2, path.to_string(), "repo/but_nested");
- assert_eq!(output, "/ab/Pa/no/in/");
- }
-
- #[test]
- fn fish_style_with_duplicate_directories() {
- let path = "~/starship/tmp/C++/C++/C++";
- let output = to_fish_style(1, path.to_string(), "C++");
- assert_eq!(output, "~/s/t/C/C/");
- }
-}
diff --git a/src/modules/env_var.rs b/src/modules/env_var.rs
deleted file mode 100644
index bb46456a1..000000000
--- a/src/modules/env_var.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use ansi_term::Color;
-use std::env;
-
-use super::{Context, Module};
-
-/// 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:
-/// - env_var.disabled is absent or false
-/// - 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>> {
- let mut module = context.new_module("env_var");
- let module_style = module
- .config_value_style("style")
- .unwrap_or_else(|| Color::Black.bold().dimmed());
-
- let env_name = module.config_value_str("variable")?;
-
- 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.get_prefix().set_value("with ");
- module.new_segment_if_config_exists("symbol");
- module.new_segment("env_var", &format!("{}{}{}", prefix, env_value, suffix));
-
- Some(module)
-}
-
-fn get_env_value(name: &str, default: Option<&str>) -> Option<String> {
- match env::var_os(name) {
- Some(os_value) => match os_value.into_string() {
- Ok(value) => Some(value),
- Err(_error) => None,
- },
- None => default.map(|value| value.to_owned()),
- }
-}
diff --git a/src/modules/git_branch.rs b/src/modules/git_branch.rs
deleted file mode 100644
index 6d07e8905..000000000
--- a/src/modules/git_branch.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-use ansi_term::Color;
-use unicode_segmentation::UnicodeSegmentation;
-
-use super::{Context, Module};
-
-/// Creates a module with the Git branch in the current directory
-///
-/// Will display the branch name if the current directory is a git repo
-pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- const GIT_BRANCH_CHAR: &str = " ";
-
- let mut module = context.new_module("git_branch");
-
- let segment_color = module
- .config_value_style("style")
- .unwrap_or_else(|| Color::Purple.bold());
- module.set_style(segment_color);
- module.get_prefix().set_value("on ");
-
- let unsafe_truncation_length = module
- .config_value_i64("truncation_length")
- .unwrap_or(std::i64::MAX);
- let truncation_symbol = get_graphemes(
- module.config_value_str("truncation_symbol").unwrap_or("…"),
- 1,
- );
-
- module.new_segment("symbol", GIT_BRANCH_CHAR);
-
- // TODO: Once error handling is implemented, warn the user if their config
- // truncation length is nonsensical
- let len = if unsafe_truncation_length <= 0 {
- log::debug!(
- "[WARN]: \"truncation_length\" should be a positive value, found {}",
- unsafe_truncation_length
- );
- std::usize::MAX
- } else {
- unsafe_truncation_length as usize
- };
- let repo = context.get_repo().ok()?;
- let branch_name = repo.branch.as_ref()?;
- let truncated_graphemes = get_graphemes(&branch_name, len);
- // The truncation symbol should only be added if we truncated
- let truncated_and_symbol = if len < graphemes_len(&branch_name) {
- truncated_graphemes + &truncation_symbol
- } else {
- truncated_graphemes
- };
-
- module.new_segment("name", &truncated_and_symbol);
-
- Some(module)
-}
-
-fn get_graphemes(text: &str, length: usize) -> String {
- UnicodeSegmentation::graphemes(text, true)
- .take(length)
- .collect::<Vec<&str>>()
- .concat()
-}
-
-fn graphemes_len(text: &str) -> usize {
- UnicodeSegmentation::graphemes(&text[..], true).count()
-}
diff --git a/src/modules/git_state.rs b/src/modules/git_state.rs
deleted file mode 100644
index c26a6007b..000000000
--- a/src/modules/git_state.rs
+++ /dev/null
@@ -1,162 +0,0 @@
-use ansi_term::Color;
-use git2::RepositoryState;
-use std::path::{Path, PathBuf};
-
-use super::{Context, Module};
-
-/// Creates a module with the state of the git repository at the current directory
-///
-/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
-/// If the progress information is available (e.g. rebasing 3/10), it will show that too.
-pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
- let mut module = context.new_module("git_state");
-
- let repo = context.get_repo().ok()?;
- let repo_root = repo.root.as_ref()?;
- let repo_state = repo.state?;
- let state_description = get_state_description(repo_state, repo_root);
-
- if let StateDescription::Clean = state_description {
- return None;
- }
-
- let module_style = module
- .config_value_style("style")
- .unwrap_or_else(|| Color::Yellow.bold());
- module.set_style(module_style);
- module.get_prefix().set_value("(");
- module.get_suffix().set_value(") ");
-
- let label = match state_description {
- StateDescription::Label(label) => label,
- StateDescription::LabelAndProgress(label, _) => label,
- // Should only be possible if you've added a new variant to StateDescription
- _ => panic!("Expected to have a label at this point in the control flow."),
- };
-
- module.new_segment(label.segment_name, label.message_default);
-
- if let StateDescription::LabelAndProgress(_, progress) = state_description {
- module.new_segment("progress_current", &format!(" {}", progress.current));
- module.new_segment("progress_divider", "/");
- module.new_segment("progress_total", &format!("{}", progress.total));
- }
-
- Some(module)
-}
-
-static MERGE_LABEL: StateLabel = StateLabel {
- segment_name: "merge",
- message_default: "MERGING",
-};
-
-static REVERT_LABEL: StateLabel = StateLabel {
- segment_name: "revert",
- message_default: "REVERTING",
-};
-
-static CHERRY_LABEL: StateLabel = StateLabel {
- segment_name: "cherry_pick",
- message_default: "CHERRY-PICKING",
-};
-
-static BISECT_LABEL: StateLabel = StateLabel {
- segment_name: "bisect",
- message_default: "BISECTING",
-};
-
-static AM_LABEL: StateLabel = StateLabel {
- segment_name: "am",
- message_default: "AM",
-};
-
-static REBASE_LABEL: StateLabel = StateLabel {
- segment_name: "rebase",
- message_default: "REBASING",
-};
-
-static AM_OR_REBASE_LABEL: StateLabel = StateLabel {
- segment_name: "am_or_rebase",
- message_default: "AM/REBASE",
-};
-
-/// Returns the state of the current repository
-///
-/// During a git operation it will show: REBASING, BISECTING, MERGING, etc.
-fn get_state_description(state: RepositoryState, root: &Path