use crate::{Prompt, PromptEditMode, PromptHistorySearch, PromptHistorySearchStatus, PromptViMode};
use {
chrono::Local,
std::{borrow::Cow, env},
};
pub static DEFAULT_PROMPT_INDICATOR: &str = "〉";
pub static DEFAULT_VI_INSERT_PROMPT_INDICATOR: &str = ": ";
pub static DEFAULT_VI_NORMAL_PROMPT_INDICATOR: &str = "〉";
pub static DEFAULT_MULTILINE_INDICATOR: &str = "::: ";
#[derive(Clone)]
pub struct DefaultPrompt {
pub left_prompt: DefaultPromptSegment,
pub right_prompt: DefaultPromptSegment,
}
#[derive(Clone)]
pub enum DefaultPromptSegment {
Basic(String),
WorkingDirectory,
CurrentDateTime,
Empty,
}
fn render_prompt_segment(prompt: &DefaultPromptSegment) -> Cow<str> {
match &prompt {
DefaultPromptSegment::Basic(s) => Cow::Borrowed(s),
DefaultPromptSegment::WorkingDirectory => {
let prompt = get_working_dir().unwrap_or_else(|_| String::from("no path"));
Cow::Owned(prompt)
}
DefaultPromptSegment::CurrentDateTime => Cow::Owned(get_now()),
DefaultPromptSegment::Empty => Cow::Borrowed(""),
}
}
impl Prompt for DefaultPrompt {
fn render_prompt_left(&self) -> Cow<str> {
render_prompt_segment(&self.left_prompt)
}
fn render_prompt_right(&self) -> Cow<str> {
render_prompt_segment(&self.right_prompt)
}
fn render_prompt_indicator(&self, edit_mode: PromptEditMode) -> Cow<str> {
match edit_mode {
PromptEditMode::Default | PromptEditMode::Emacs => DEFAULT_PROMPT_INDICATOR.into(),
PromptEditMode::Vi(vi_mode) => match vi_mode {
PromptViMode::Normal => DEFAULT_VI_NORMAL_PROMPT_INDICATOR.into(),
PromptViMode::Insert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(),
},
PromptEditMode::Custom(str) => format!("({str})").into(),
}
}
fn render_prompt_multiline_indicator(&self) -> Cow<str> {
Cow::Borrowed(DEFAULT_MULTILINE_INDICATOR)
}
fn render_prompt_history_search_indicator(
&self,
history_search: PromptHistorySearch,
) -> Cow<str> {
let prefix = match history_search.status {
PromptHistorySearchStatus::Passing => "",
PromptHistorySearchStatus::Failing => "failing ",
};
Cow::Owned(format!(
"({}reverse-search: {}) ",
prefix, history_search.term
))
}
}
impl Default for DefaultPrompt {
fn default() -> Self {
DefaultPrompt {
left_prompt: DefaultPromptSegment::WorkingDirectory,
right_prompt: DefaultPromptSegment::CurrentDateTime,
}
}
}
impl DefaultPrompt {
pub const fn new(
left_prompt: DefaultPromptSegment,
right_prompt: DefaultPromptSegment,
) -> DefaultPrompt {
DefaultPrompt {
left_prompt,
right_prompt,
}
}
}
fn get_working_dir() -> Result<String, std::io::Error> {
let path = env::current_dir()?;
let path_str = path.display().to_string();
let homedir: String = match env::var("USERPROFILE") {
Ok(win_home) => win_home,
Err(_) => match env::var("HOME") {
Ok(maclin_home) => maclin_home,
Err(_) => path_str.clone(),
},
};
let new_path = if path_str != homedir {
path_str.replace(&homedir, "~")
} else {
path_str
};
Ok(new_path)
}
fn get_now() -> String {
let now = Local::now();
format!("{:>}", now.format("%m/%d/%Y %I:%M:%S %p"))
}