diff --git a/docs/config/README.md b/docs/config/README.md index 579467e94..7739d1b61 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -3319,6 +3319,19 @@ If you have an interesting example not covered there, feel free to share it ther ::: +::: warning Command output is printed unescaped to the prompt + +Whatever output the command generates is printed unmodified in the prompt. This means if the output +contains special sequences that are interpreted by your shell they will be expanded when displayed. +These special sequences are shell specific, e.g. you can write a command module that writes bash sequences, +e.g. `\h`, but this module will not work in a fish or zsh shell. + +Format strings can also contain shell specific prompt sequences, e.g. +[Bash](https://www.gnu.org/software/bash/manual/html_node/Controlling-the-Prompt.html), +[Zsh](https://zsh.sourceforge.io/Doc/Release/Prompt-Expansion.html). + +::: + ### Options | Option | Default | Description | diff --git a/src/formatter/string_formatter.rs b/src/formatter/string_formatter.rs index 7778bb6ad..fb890b29f 100644 --- a/src/formatter/string_formatter.rs +++ b/src/formatter/string_formatter.rs @@ -7,6 +7,7 @@ use std::error::Error; use std::fmt; use crate::config::parse_style_string; +use crate::context::{Context, Shell}; use crate::segment::Segment; use super::model::*; @@ -15,6 +16,7 @@ use super::parser::{parse, Rule}; #[derive(Clone)] enum VariableValue<'a> { Plain(Cow<'a, str>), + NoEscapingPlain(Cow<'a, str>), Styled(Vec), Meta(Vec>), } @@ -123,6 +125,27 @@ impl<'a> StringFormatter<'a> { self } + /// Maps variable name into a value which is wrapped to prevent escaping later + /// + /// This should be used for variables that should not be escaped before inclusion in the prompt + /// + /// See `StringFormatter::map` for description on the parameters. + /// + pub fn map_no_escaping(mut self, mapper: M) -> Self + where + T: Into>, + M: Fn(&str) -> Option> + Sync, + { + self.variables + .par_iter_mut() + .filter(|(_, value)| value.is_none()) + .for_each(|(key, value)| { + *value = mapper(key) + .map(|var| var.map(|var| VariableValue::NoEscapingPlain(var.into()))); + }); + self + } + /// Maps a meta-variable to a format string containing other variables. /// /// This function should be called **before** other map methods so that variables found in @@ -206,11 +229,16 @@ impl<'a> StringFormatter<'a> { /// /// - Format string in meta variables fails to parse /// - Variable mapper returns an error. - pub fn parse(self, default_style: Option