use crate::indicators::git::{MAIN_COL, repo_name}; use nu_ansi_term::AnsiGenericString; use nu_ansi_term::Color::Rgb; use std::env::current_dir; pub const UNKNOWN_PATH: &str = "\u{2248}"; // "≈" pub const PATH_COL: nu_ansi_term::Color = Rgb(82, 82, 82); pub const REPO_COL: nu_ansi_term::Color = Rgb(55, 120, 130); /// Find the current user's home directory. fn home_dir() -> Option { // Try `passwd` file first unsafe { let pw = libc::getpwuid(libc::geteuid()); if !pw.is_null() { let dir = std::ffi::CStr::from_ptr((*pw).pw_dir); if let Ok(s) = dir.to_str() { return Some(s.to_owned()); } } } // Fallback: `$HOME` env var std::env::var("HOME").ok() } /// Returns the full path of the current directory as a string. fn full_path() -> String { current_dir().map_or_else( |_| UNKNOWN_PATH.to_string(), |path| path.display().to_string(), ) } /// Remove the path of the repo's root from the path, to replace it with the repo's name. fn remove_repo(pwd_path: &str, repo_path: &str) -> String { pwd_path.replacen(repo_path, "", 1) } /// Replace the 'home directory' part of the path with a the '~' symbol fn replace_home(path: &str) -> String { if let Some(home) = home_dir() { if path.starts_with(&home) { return path.replacen(&home, "~", 1); } } path.to_owned() } fn short(path: &str, slash_limit: u8) -> String { let slashes = path.matches('/').count(); // Get the number of slashes if slashes <= slash_limit.into() { return path.to_string(); // Short path, return without changes } // Else: Long path, shorten it let parts: Vec<&str> = path.split('/').collect(); // Split the path into parts let first = if path.starts_with('~') { "~" } else { "" }; // Determine the first part correctly let last = parts[parts.len() - 1]; // The last part // Abbreviate middle parts (take the first character of each) let abbreviated_middle = parts[1..parts.len() - 1] // Skip the first and last part .iter() .filter(|&&part| !part.is_empty()) // Avoid empty parts (like "//") .map(|&part| part.chars().next().unwrap().to_string()) // Take the first letter .collect::>() // Collect the parts as a Vec .join("/"); // Join them with a "/" separator format!("{first}/{abbreviated_middle}/{last}") // Final } pub fn pwd( abbrev_home: bool, shorten_path: bool, replace_repo: bool, git_repo: Option, ) -> AnsiGenericString<'static, str> { let mut slash_limit: u8 = 3; // Max number of slashes let mut path = full_path(); // Get the full path of he current directory // Replace a git repo root path with the repo's name if replace_repo && git_repo.is_some() { if let Some(repo_path) = git_repo { path = remove_repo(&path, &repo_path); let repo_name = repo_name(&repo_path); if shorten_path { slash_limit = 2; // Max number of slashes path = short(&path, slash_limit); } return if path.is_empty() { REPO_COL.paint(repo_name) // In the root dir of the repo } else { // In a subdir inside the repo /*format!( "{}{}{}", REPO_COL.paint(repo_name), // Repo name MAIN_COL.paint(" \u{F02A2} "), // Separator PATH_COL.italic().paint(path) // Sub-directory )*/ format!( "\x1b[38;2;55;120;130m{}\ \x1b[38;2;178;98;44m \u{F02A2} \ \x1b[3;38;2;82;82;82m{}\ \x1b[39;23m", repo_name, path ) .into() }; } } // Replace the home directory path with the 'home symbol': ~ if abbrev_home { path = replace_home(&path); } if shorten_path { path = short(&path, slash_limit); } PATH_COL.italic().paint(path) }