diff --git a/src/indicators/git.rs b/src/indicators/git.rs index f14fd85..bef62fd 100644 --- a/src/indicators/git.rs +++ b/src/indicators/git.rs @@ -1,5 +1,6 @@ use ansi_term::ANSIGenericString; use ansi_term::Colour::RGB; +use std::path::Path; use std::process::Command; // SSH indicator symbol @@ -32,6 +33,14 @@ pub fn info() -> Option<(String, String)> { } } +pub fn repo_name(path: &str) -> String { + Path::new(path) + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("") // Default value if None + .to_string() // Convert &str to String +} + //Git branch indicator pub fn indicator(branch: Option) -> ANSIGenericString<'static, str> { match branch { diff --git a/src/indicators/pwd.rs b/src/indicators/pwd.rs index 149f460..d71e76c 100644 --- a/src/indicators/pwd.rs +++ b/src/indicators/pwd.rs @@ -1,33 +1,94 @@ +use crate::indicators::git::{repo_name, MAIN_COL}; use ansi_term::ANSIGenericString; use ansi_term::Colour::RGB; use std::env::current_dir; pub const UNKNOWN_PATH: &str = "\u{2248}"; // "≈" pub const PATH_COL: ansi_term::Colour = RGB(82, 82, 82); +pub const REPO_COL: ansi_term::Colour = RGB(55, 120, 130); fn home_dir() -> String { - std::env::var("HOME").map_or_else( - |_| "".to_string(), - |path| path.to_string(), - ) + std::env::var("HOME").map_or_else(|_| "".to_string(), |path| path.to_string()) } fn full_path() -> String { - current_dir().map_or_else( + current_dir().map_or_else( |_| UNKNOWN_PATH.to_string(), |path| path.to_string_lossy().to_string(), ) } -fn replace_home(path: String) -> String { - let homedir = home_dir(); - path.replace(&homedir, "~") +fn remove_repo(pwd_path: &str, repo_path: &str) -> String { + pwd_path.replacen(repo_path, "", 1) } -pub fn pwd(abbrev_home:bool) -> ANSIGenericString<'static, str> { - let mut path = full_path(); - if abbrev_home { - path = replace_home(path); +fn replace_home(path: &str) -> String { + let homedir = home_dir(); + path.replacen(&homedir, "~", 1) +} + +fn short(path: &str, slash_limit: u8) -> String { + let slashes = path.matches('/').count(); + if slashes <= slash_limit.into() { + 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: Vec = parts[1..parts.len() - 1] // Skip the first and last part + .iter() + .filter(|&&part| !part.is_empty()) // Avoid empty parts (like after "/") + .map(|&part| part.chars().next().unwrap().to_string()) // Take the first letter + .collect(); + + // Join the parts back together with "/" and return the shortened path + let mut shortened_path = vec![first.to_string()]; + shortened_path.extend(abbreviated_middle); + shortened_path.push(last.to_string()); + + shortened_path.join("/") } - PATH_COL.italic().paint(path) -} \ No newline at end of file +} + +pub fn pwd( + abbrev_home: bool, + shorten_path: bool, + replace_repo: bool, + git_repo: Option, +) -> ANSIGenericString<'static, str> { + let mut path = full_path(); + let slash_limit: u8 = if replace_repo { 2 } else { 3 }; + + 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 { + path = short(&path, slash_limit); + } + match path.as_str() { + "" => REPO_COL.paint(repo_name), + _ => format!( + "{}{}{}", + REPO_COL.paint(repo_name), + MAIN_COL.paint(" \u{F02A2} "), + PATH_COL.italic().paint(path) + ) + .into(), + } + } else { + PATH_COL.italic().paint(path) + } + } else if abbrev_home { + path = replace_home(&path); + if shorten_path { + path = short(&path, slash_limit); + } + PATH_COL.italic().paint(path) + } else { + PATH_COL.italic().paint(path) + } +} diff --git a/src/indicators/user.rs b/src/indicators/user.rs index 8285977..45d380a 100644 --- a/src/indicators/user.rs +++ b/src/indicators/user.rs @@ -9,8 +9,7 @@ pub const NORMIE_COL: ansi_term::Colour = RGB(0, 255, 180); // A kind of green //Root user indicator pub fn username() -> String { - var("USER") - .unwrap_or_else(|_| "UnknownUser".to_string()) + var("USER").unwrap_or_else(|_| "UnknownUser".to_string()) } pub fn indicator() -> ANSIGenericString<'static, str> { diff --git a/src/main.rs b/src/main.rs index a5ddcb7..2a8630d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,33 +14,45 @@ use crate::indicators::user; fn main() { let cmd_args: Vec = std::env::args().collect(); - let mut prompt: String = String::new(); + + let mut components: Vec = Vec::new(); let indicate_user: bool = true; let indicate_ssh: bool = true; let indicate_err: bool = true; let indicate_git_branch: bool = true; - let pwd: bool = true; - let abbrev_home:bool = true; + let show_pwd: bool = true; + let abbrev_home: bool = true; + let shorten_path: bool = true; + let replace_repo: bool = true; + let mut git_info = None; - if pwd { - prompt += &pwd::pwd(abbrev_home).to_string(); - } if indicate_ssh { - prompt += &ssh::indicator().to_string(); + components.push(ssh::indicator().to_string()); } if indicate_git_branch { - let git_info = git::info(); + git_info = git::info(); match git_info { - Some((_repo, branch)) => prompt += &git::indicator(Some(branch)).to_string(), - None => prompt += &git::indicator(None).to_string(), - }; + Some(ref info) => components.push(git::indicator(Some(info.1.clone())).to_string()), + None => components.push(git::indicator(None).to_string()), + } } if indicate_user { - prompt += &user::indicator().to_string(); + components.push(user::indicator().to_string()); } if indicate_err { - prompt += &error::indicator(cmd_args).to_string(); + components.push(error::indicator(cmd_args).to_string()); } + if show_pwd { + let repo_path = match git_info { + Some(info) => Some(info.0), // Clone to avoid ownership issues + None => None, + }; + components.insert( + 0, + pwd::pwd(abbrev_home, shorten_path, replace_repo, repo_path).to_string(), + ); + } + let prompt = components.join(""); print!("{prompt} "); } diff --git a/src/old/path.rs b/src/old/path.rs deleted file mode 100644 index ff76519..0000000 --- a/src/old/path.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::env::{args, current_dir, var_os}; - -pub fn abrev_path(path: &str) -> String { - let mut short_dir = path.to_string(); - - let slashes = path.matches('/').count(); - - if slashes > 3 { - let parts: Vec<&str> = path.split('/').collect(); - let len = parts.len() - 1; - let mut ch1: String; - - for part in &parts[0..len] { - if part.to_string() != "" { - // to avoid the 1st "/" - ch1 = part.chars().next().expect(part).to_string(); // 1st char of each part - short_dir = short_dir.replace(part, &ch1); - } - } - } - short_dir -} - -//pwd -pub fn homedir() -> String { - var_os("HOME") - .expect("UnknownDir") - .to_str() - .expect("UnknownDir") - .to_string() -}