Skip to main content

ase_shell/
utils.rs

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  // Detached HEAD: show short SHA
47  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}