use crate::extensions::p10k::config::{p9k_global, p9k_param};
use crate::ported::params::getsparam;
use std::path::Path;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TransientMode {
Always,
SameDir,
}
fn parse_mode(value: &str) -> Option<TransientMode> {
match value {
"always" => Some(TransientMode::Always),
"same-dir" => Some(TransientMode::SameDir),
_ => None, }
}
pub fn transient_enabled() -> Option<TransientMode> {
if !crate::p10k::engine_active() {
return None;
}
parse_mode(&p9k_global("TRANSIENT_PROMPT", "off"))
}
pub fn should_condense(pwd_at_accept: &Path, pwd_now: &Path, mode: TransientMode) -> bool {
match mode {
TransientMode::Always => true,
TransientMode::SameDir => pwd_at_accept == pwd_now,
}
}
fn translate_color_min(c: &str) -> String {
crate::extensions::p10k::render::translate_color(c)
}
fn transient_char(state: &str, default_fg: &str) -> String {
let fg = translate_color_min(&p9k_param(
"prompt_char",
Some(state),
"FOREGROUND",
default_fg,
));
let fg_seq = if fg.is_empty() {
"%f".to_string()
} else {
format!("%F{{{fg}}}")
};
let glyph = crate::p10k::expansion::apply_content_expansion(
"prompt_char",
Some(state),
"\u{276F}",
);
format!("{fg_seq}{glyph}")
}
pub fn render_transient() -> (String, String) {
let mut left = String::from("%b%k%s%u");
if crate::p10k::last_status() == 0 {
left.push_str(&transient_char("OK_VIINS", "76")); } else {
left.push_str(&transient_char("ERROR_VIINS", "196")); }
left.push_str("%b%k%f%s%u ");
let shell_integration = p9k_global("TERM_SHELL_INTEGRATION", "") == "true"
|| getsparam("ITERM_SHELL_INTEGRATION_INSTALLED").as_deref() == Some("Yes");
if shell_integration {
left = format!("%{{\u{1b}]133;A\u{7}%}}{left}%{{\u{1b}]133;B\u{7}%}}");
}
(left, String::new())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mode_parsing_exact_strings_only() {
assert_eq!(parse_mode("always"), Some(TransientMode::Always));
assert_eq!(parse_mode("same-dir"), Some(TransientMode::SameDir));
assert_eq!(parse_mode("off"), None);
assert_eq!(parse_mode(""), None);
assert_eq!(parse_mode("Always"), None); assert_eq!(parse_mode("same_dir"), None);
assert_eq!(parse_mode("true"), None);
}
#[test]
fn always_condenses_everywhere() {
assert!(should_condense(
Path::new("/a"),
Path::new("/b"),
TransientMode::Always
));
assert!(should_condense(
Path::new(""),
Path::new("/b"),
TransientMode::Always
));
}
#[test]
fn same_dir_requires_pwd_match() {
assert!(should_condense(
Path::new("/home/u/proj"),
Path::new("/home/u/proj"),
TransientMode::SameDir
));
assert!(!should_condense(
Path::new("/home/u/proj"),
Path::new("/home/u/other"),
TransientMode::SameDir
));
assert!(!should_condense(
Path::new(""),
Path::new("/home/u/proj"),
TransientMode::SameDir
));
}
#[test]
fn translate_color_min_forms() {
assert_eq!(translate_color_min("76"), "076");
assert_eq!(translate_color_min("196"), "196");
assert_eq!(translate_color_min("#FFAA00"), "#ffaa00");
assert_eq!(translate_color_min("green"), "002");
assert_eq!(translate_color_min(""), "");
}
}
static LAST_PROMPT_PWD: std::sync::Mutex<String> = std::sync::Mutex::new(String::new());
pub fn transient_swap_for_accept() -> Option<(String, String)> {
if !crate::p10k::engine_active() {
return None;
}
crate::p10k::run_post_prompt_hook(); crate::p10k::mark_line_finished(); if let Some(mode) = transient_enabled() {
let cwd = std::path::PathBuf::from(getsparam("PWD").filter(|p| !p.is_empty()).unwrap_or_else(|| {
std::env::current_dir()
.map(|p| p.to_string_lossy().into_owned())
.unwrap_or_default()
}));
let mut slot = LAST_PROMPT_PWD.lock().unwrap();
if should_condense(Path::new(slot.as_str()), &cwd, mode) {
return Some(render_transient());
}
*slot = cwd.to_string_lossy().into_owned();
}
if p9k_global("TIME_UPDATE_ON_COMMAND", "") == "true" {
crate::p10k::preprompt_render();
return Some((
getsparam("PROMPT").unwrap_or_default(),
getsparam("RPROMPT").unwrap_or_default(),
));
}
None
}