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.
This commit is contained in:
Kevin Song 2021-10-05 18:19:55 -05:00 committed by GitHub
parent 4c4cd340dd
commit 190743e4e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 6 deletions

View File

@ -114,10 +114,12 @@ impl<'a> Context<'a> {
.map(|(a, b)| (*a, b.vals.first().cloned().unwrap().into_string().unwrap())) .map(|(a, b)| (*a, b.vals.first().cloned().unwrap().into_string().unwrap()))
.collect(); .collect();
// Pipestatus is an arguments list
let pipestatus = arguments let pipestatus = arguments
.values_of("pipestatus") .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. // Canonicalize the current path to resolve symlinks, etc.
// NOTE: On Windows this converts the path to extended-path syntax. // NOTE: On Windows this converts the path to extended-path syntax.
@ -196,6 +198,26 @@ impl<'a> Context<'a> {
dir dir
} }
/// Reads and appropriately flattens multiple args for pipestatus
pub fn get_and_flatten_pipestatus(args: clap::Values) -> Option<Vec<String>> {
// 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<String>
let parsed_vals = args
.into_iter()
.map(|x| x.split_ascii_whitespace())
.flatten()
.map(|x| x.to_string())
.collect::<Vec<String>>();
// 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 /// Create a new module
pub fn new_module(&self, name: &str) -> Module { pub fn new_module(&self, name: &str) -> Module {
let config = self.config.get_module_config(name); let config = self.config.get_module_config(name);

View File

@ -49,10 +49,10 @@ starship_precmd() {
if [[ $STARSHIP_START_TIME ]]; then if [[ $STARSHIP_START_TIME ]]; then
STARSHIP_END_TIME=$(::STARSHIP:: time) STARSHIP_END_TIME=$(::STARSHIP:: time)
STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_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 unset STARSHIP_START_TIME
else 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 fi
STARSHIP_PREEXEC_READY=true # Signal that we can safely restart the timer STARSHIP_PREEXEC_READY=true # Signal that we can safely restart the timer
} }

View File

@ -91,5 +91,5 @@ export STARSHIP_SESSION_KEY=${STARSHIP_SESSION_KEY:0:16}; # Trim to 16-digits if
VIRTUAL_ENV_DISABLE_PROMPT=1 VIRTUAL_ENV_DISABLE_PROMPT=1
setopt promptsubst setopt promptsubst
PROMPT='$(::STARSHIP:: prompt --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")' RPROMPT='$(::STARSHIP:: prompt --right --keymap="$KEYMAP" --status="$STARSHIP_CMD_STATUS" --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --cmd-duration="$STARSHIP_DURATION" --jobs="$STARSHIP_JOBS_COUNT")'