From c1f2d345aac0b0241ea1b6d99977fea20fa3f5bb Mon Sep 17 00:00:00 2001 From: Fred Cox Date: Mon, 1 Nov 2021 14:18:45 -0700 Subject: [PATCH] fix(escaping): move escaping to individual variables (#3107) --- docs/config/README.md | 13 +++ src/formatter/string_formatter.rs | 154 +++++++++++++++++++++++++----- src/formatter/version.rs | 2 +- src/modules/aws.rs | 2 +- src/modules/battery.rs | 2 +- src/modules/character.rs | 2 +- src/modules/cmake.rs | 2 +- src/modules/cmd_duration.rs | 2 +- src/modules/cobol.rs | 2 +- src/modules/conda.rs | 2 +- src/modules/crystal.rs | 2 +- src/modules/custom.rs | 4 +- src/modules/dart.rs | 2 +- src/modules/deno.rs | 2 +- src/modules/directory.rs | 2 +- src/modules/docker_context.rs | 2 +- src/modules/dotnet.rs | 2 +- src/modules/elixir.rs | 2 +- src/modules/elm.rs | 2 +- src/modules/env_var.rs | 2 +- src/modules/erlang.rs | 2 +- src/modules/gcloud.rs | 2 +- src/modules/git_branch.rs | 2 +- src/modules/git_commit.rs | 2 +- src/modules/git_metrics.rs | 2 +- src/modules/git_state.rs | 2 +- src/modules/git_status.rs | 70 +++++++++----- src/modules/golang.rs | 2 +- src/modules/helm.rs | 2 +- src/modules/hg_branch.rs | 2 +- src/modules/hostname.rs | 2 +- src/modules/java.rs | 2 +- src/modules/jobs.rs | 2 +- src/modules/julia.rs | 2 +- src/modules/kotlin.rs | 2 +- src/modules/kubernetes.rs | 2 +- src/modules/lua.rs | 2 +- src/modules/memory_usage.rs | 2 +- src/modules/nim.rs | 2 +- src/modules/nix_shell.rs | 2 +- src/modules/nodejs.rs | 2 +- src/modules/ocaml.rs | 2 +- src/modules/openstack.rs | 2 +- src/modules/package.rs | 2 +- src/modules/perl.rs | 2 +- src/modules/php.rs | 2 +- src/modules/pulumi.rs | 2 +- src/modules/purescript.rs | 2 +- src/modules/python.rs | 2 +- src/modules/red.rs | 2 +- src/modules/rlang.rs | 2 +- src/modules/ruby.rs | 2 +- src/modules/rust.rs | 2 +- src/modules/scala.rs | 2 +- src/modules/shell.rs | 2 +- src/modules/shlvl.rs | 2 +- src/modules/singularity.rs | 2 +- src/modules/status.rs | 7 +- src/modules/swift.rs | 2 +- src/modules/terraform.rs | 2 +- src/modules/time.rs | 2 +- src/modules/username.rs | 2 +- src/modules/vagrant.rs | 2 +- src/modules/vcsh.rs | 2 +- src/modules/vlang.rs | 2 +- src/modules/zig.rs | 2 +- src/print.rs | 2 +- src/utils.rs | 62 +----------- 68 files changed, 259 insertions(+), 175 deletions(-) diff --git a/docs/config/README.md b/docs/config/README.md index 579467e9..7739d1b6 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 7778bb6a..fb890b29 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