From 190743e4e0cab479cb10e183d86b1ed3bc5884b8 Mon Sep 17 00:00:00 2001 From: Kevin Song <4605384+chipbuster@users.noreply.github.com> Date: Tue, 5 Oct 2021 18:19:55 -0500 Subject: [PATCH] fix: pipestatus quoting on Zsh/Bash (#3088) Changes the parsing for pipestatus to allow for multiple arguments, a single argument of space-separated values, or any mix of the two. All inputs are flattened into a single array where no elements have spaces in them. Changes the initscripts to no longer fail when an empty pipestatus is passed as an argument by quoting and changing expansions. --- src/context.rs | 26 ++++++++++++++++++++++++-- src/init/starship.bash | 4 ++-- src/init/starship.zsh | 4 ++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/context.rs b/src/context.rs index a808aaa5..630c0875 100644 --- a/src/context.rs +++ b/src/context.rs @@ -114,10 +114,12 @@ impl<'a> Context<'a> { .map(|(a, b)| (*a, b.vals.first().cloned().unwrap().into_string().unwrap())) .collect(); - // Pipestatus is an arguments list let pipestatus = arguments .values_of("pipestatus") - .map(|args| args.into_iter().map(String::from).collect()); + .map(Context::get_and_flatten_pipestatus) + .flatten(); + + log::trace!("Received completed pipestatus of {:?}", pipestatus); // Canonicalize the current path to resolve symlinks, etc. // NOTE: On Windows this converts the path to extended-path syntax. @@ -196,6 +198,26 @@ impl<'a> Context<'a> { dir } + /// Reads and appropriately flattens multiple args for pipestatus + pub fn get_and_flatten_pipestatus(args: clap::Values) -> Option> { + // Due to shell differences, we can potentially receive individual or space + // separated inputs, e.g. "0","1","2","0" is the same as "0 1 2 0" and + // "0 1", "2 0". We need to accept all these formats and return a Vec + let parsed_vals = args + .into_iter() + .map(|x| x.split_ascii_whitespace()) + .flatten() + .map(|x| x.to_string()) + .collect::>(); + // If the vector is zero-length, we should pretend that we didn't get a + // pipestatus at all (since this is the input `--pipestatus=""`) + if parsed_vals.is_empty() { + None + } else { + Some(parsed_vals) + } + } + /// Create a new module pub fn new_module(&self, name: &str) -> Module { let config = self.config.get_module_config(name); diff --git a/src/init/starship.bash b/src/init/starship.bash index cefafd19..8d88657b 100644 --- a/src/init/starship.bash +++ b/src/init/starship.bash @@ -49,10 +49,10 @@ starship_precmd() { if [[ $STARSHIP_START_TIME ]]; then STARSHIP_END_TIME=$(::STARSHIP:: time) STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME)) - PS1="$(::STARSHIP:: prompt --status=$STARSHIP_CMD_STATUS --pipestatus ${STARSHIP_PIPE_STATUS[@]} --jobs="$NUM_JOBS" --cmd-duration=$STARSHIP_DURATION)" + PS1="$(::STARSHIP:: prompt --status=$STARSHIP_CMD_STATUS --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --jobs="$NUM_JOBS" --cmd-duration=$STARSHIP_DURATION)" unset STARSHIP_START_TIME else - PS1="$(::STARSHIP:: prompt --status=$STARSHIP_CMD_STATUS --pipestatus ${STARSHIP_PIPE_STATUS[@]} --jobs="$NUM_JOBS")" + PS1="$(::STARSHIP:: prompt --status=$STARSHIP_CMD_STATUS --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --jobs="$NUM_JOBS")" fi STARSHIP_PREEXEC_READY=true # Signal that we can safely restart the timer } diff --git a/src/init/starship.zsh b/src/init/starship.zsh index 3148e68e..0de2b989 100644 --- a/src/init/starship.zsh +++ b/src/init/starship.zsh @@ -91,5 +91,5 @@ export STARSHIP_SESSION_KEY=${STARSHIP_SESSION_KEY:0:16}; # Trim to 16-digits if VIRTUAL_ENV_DISABLE_PROMPT=1 setopt promptsubst -PROMPT='$(::STARSHIP:: prompt --keymap="$KEYMAP" --status="$STARSHIP_CMD_STATUS" --pipestatus ${STARSHIP_PIPE_STATUS[@]} --cmd-duration="$STARSHIP_DURATION" --jobs="$STARSHIP_JOBS_COUNT")' -RPROMPT='$(::STARSHIP:: prompt --right --keymap="$KEYMAP" --status="$STARSHIP_CMD_STATUS" --pipestatus ${STARSHIP_PIPE_STATUS[@]} --cmd-duration="$STARSHIP_DURATION" --jobs="$STARSHIP_JOBS_COUNT")' +PROMPT='$(::STARSHIP:: prompt --keymap="$KEYMAP" --status="$STARSHIP_CMD_STATUS" --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --cmd-duration="$STARSHIP_DURATION" --jobs="$STARSHIP_JOBS_COUNT")' +RPROMPT='$(::STARSHIP:: prompt --right --keymap="$KEYMAP" --status="$STARSHIP_CMD_STATUS" --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --cmd-duration="$STARSHIP_DURATION" --jobs="$STARSHIP_JOBS_COUNT")'