1use std::{
2 env, fs,
3 path::{Path, PathBuf},
4};
5
6use anyhow::Context;
7
8use crate::SHELL_NAME;
9
10pub fn get_pwd() -> anyhow::Result<PathBuf> {
11 std::env::current_dir().context("could not retrieve current working directory")
12}
13
14pub fn get_prompt() -> String {
15 let curr_dir = env::current_dir()
16 .ok()
17 .and_then(|path| path.file_name().map(|s| s.to_string_lossy().into_owned()))
18 .unwrap_or_else(|| "".to_string());
19
20 let git_branch = current_git_branch().unwrap_or_default();
21 let branch_part = if git_branch.is_empty() {
22 String::new()
23 } else {
24 format!(" ({git_branch})")
25 };
26
27 format!(
28 "\x1b[32m{}\x1b[0m [{}{}] \x1b[1m>\x1b[0m ",
29 SHELL_NAME, curr_dir, branch_part
30 )
31}
32
33fn current_git_branch() -> Option<String> {
34 let cwd = env::current_dir().ok()?;
35 let git_dir = find_git_dir(&cwd)?;
36 let head_path = git_dir.join("HEAD");
37 let head_contents = fs::read_to_string(head_path).ok()?;
38
39 if let Some(rest) = head_contents.trim().strip_prefix("ref:") {
40 let ref_path = rest.trim();
41 return Path::new(ref_path)
42 .file_name()
43 .and_then(|s| Some(s.to_string_lossy().into_owned()));
44 }
45
46 let sha = head_contents.trim();
48 if sha.is_empty() {
49 None
50 } else {
51 Some(sha.chars().take(7).collect())
52 }
53}
54
55fn find_git_dir(start: &Path) -> Option<PathBuf> {
56 let mut dir = Some(start);
57
58 while let Some(current) = dir {
59 let candidate = current.join(".git");
60 if candidate.is_dir() {
61 return Some(candidate);
62 }
63 dir = current.parent();
64 }
65
66 None
67}