diff --git a/README.md b/README.md index f94335c..595b329 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,13 @@ The prompt string supports escape sequences for dynamic content: | `\t`, `\T` | Last command runtime (milliseconds / human-readable) | | `\s` | Shell name | | `\e[...` | ANSI escape sequences for colors and styling | -| `\!name` | Execute a shell function and embed its output | +| `\@name` | Execute a shell function and embed its output | -The `\!` escape is particularly useful. It lets you embed the output of any shell function directly in your prompt. Define a function that prints something, then reference it in your prompt string: +The `\@` escape is particularly useful. It lets you embed the output of any shell function directly in your prompt. Define a function that prints something, then reference it in your prompt string: ```sh gitbranch() { git branch --show-current 2>/dev/null; } -export PS1='\u@\h \W \!gitbranch \$ ' +export PS1='\u@\h \W \@gitbranch \$ ' ``` Additionally, `echo` now has a `-p` flag that expands prompt escape sequences, similar to how the `-e` flag expands conventional escape sequences. diff --git a/src/expand.rs b/src/expand.rs index 49d7bda..7e76a29 100644 --- a/src/expand.rs +++ b/src/expand.rs @@ -1033,7 +1033,7 @@ pub fn unescape_str(raw: &str) -> String { '\\' => { if let Some(next_ch) = chars.next() { match next_ch { - '"' | '\\' | '`' | '$' => { + '"' | '\\' | '`' | '$' | '!' => { // discard the backslash } _ => { @@ -2037,7 +2037,7 @@ fn tokenize_prompt(raw: &str) -> Vec { '\'' => tokens.push(PromptTk::Text("'".into())), '(' => tokens.push(PromptTk::VisGroupOpen), ')' => tokens.push(PromptTk::VisGroupClose), - '!' => { + '@' => { let mut func_name = String::new(); let is_braced = chars.peek() == Some(&'{'); let mut handled = false; @@ -2056,14 +2056,14 @@ fn tokenize_prompt(raw: &str) -> Vec { handled = true; if is_braced { // Invalid character in braced function name - tokens.push(PromptTk::Text(format!("\\!{{{func_name}"))); + tokens.push(PromptTk::Text(format!("\\@{{{func_name}"))); } else { // End of unbraced function name let func_exists = read_logic(|l| l.get_func(&func_name).is_some()); if func_exists { tokens.push(PromptTk::Function(func_name.clone())); } else { - tokens.push(PromptTk::Text(format!("\\!{func_name}"))); + tokens.push(PromptTk::Text(format!("\\@{func_name}"))); } } break; @@ -2076,7 +2076,7 @@ fn tokenize_prompt(raw: &str) -> Vec { if func_exists { tokens.push(PromptTk::Function(func_name)); } else { - tokens.push(PromptTk::Text(format!("\\!{func_name}"))); + tokens.push(PromptTk::Text(format!("\\@{func_name}"))); } } }