diff --git a/functions/utilities.zsh b/functions/utilities.zsh index df022f2c..079e675a 100644 --- a/functions/utilities.zsh +++ b/functions/utilities.zsh @@ -134,3 +134,52 @@ print_deprecation_warning() { fi done } + +# A helper function to determine if a segment should be +# joined or promoted to a full one. +# Takes three arguments: +# * $1: The array index of the current segment +# * $2: The array index of the last printed segment +# * $3: The array of segments of the left or right prompt +function segmentShouldBeJoined() { + local current_index=$1 + local last_segment_index=$2 + # Explicitly split the elements by whitespace. + local -a elements + elements=${=3} + + local current_segment=${elements[$current_index]} + local joined=false + if [[ ${current_segment[-7,-1]} == '_joined' ]]; then + joined=true + # promote segment to a full one, if the predecessing full segment + # was conditional. So this can only be the case for segments that + # are not our direct predecessor. + if (( $(($current_index - $last_segment_index)) > 1)); then + # Now we have to examine every previous segment, until we reach + # the last printed one (found by its index). This is relevant if + # all previous segments are joined. Then we want to join our + # segment as well. + local examined_index=$((current_index - 1)) + while (( $examined_index > $last_segment_index )); do + local previous_segment=${elements[$examined_index]} + # If one of the examined segments is not joined, then we know + # that the current segment should not be joined, as the target + # segment is the wrong one. + if [[ ${previous_segment[-7,-1]} != '_joined' ]]; then + joined=false + break + fi + examined_index=$((examined_index - 1)) + done + fi + fi + + # Return 1 means error; return 0 means no error. So we have + # to invert $joined + if [[ "$joined" == "true" ]]; then + return 0 + else + return 1 + fi +} diff --git a/powerlevel9k.zsh-theme b/powerlevel9k.zsh-theme index 7e9783d7..4207629a 100755 --- a/powerlevel9k.zsh-theme +++ b/powerlevel9k.zsh-theme @@ -123,14 +123,20 @@ CURRENT_BG='NONE' # Takes four arguments: # * $1: Name of the function that was orginally invoked (mandatory). # Necessary, to make the dynamic color-overwrite mechanism work. -# * $2: A flag if the segment should be joined with the previous one. +# * $2: The array index of the current segment # * $3: Background color # * $4: Foreground color # * $5: The segment content # * $6: An identifying icon (must be a key of the icons array) # The latter three can be omitted, +set_default last_left_element_index 1 set_default POWERLEVEL9K_WHITESPACE_BETWEEN_LEFT_SEGMENTS " " left_prompt_segment() { + local current_index=$2 + # Check if the segment should be joined with the previous one + local joined + segmentShouldBeJoined $current_index $last_left_element_index "$POWERLEVEL9K_LEFT_PROMPT_ELEMENTS" && joined=true || joined=false + # Overwrite given background-color by user defined variable for this segment. local BACKGROUND_USER_VARIABLE=POWERLEVEL9K_${(U)1#prompt_}_BACKGROUND local BG_COLOR_MODIFIER=${(P)BACKGROUND_USER_VARIABLE} @@ -145,7 +151,6 @@ left_prompt_segment() { [[ -n "$3" ]] && bg="%K{$3}" || bg="%k" [[ -n "$4" ]] && fg="%F{$4}" || fg="%f" - local joined=$2 if [[ $CURRENT_BG != 'NONE' ]] && ! isSameColor "$3" "$CURRENT_BG"; then echo -n "$bg%F{$CURRENT_BG}" if [[ $joined == false ]]; then @@ -188,6 +193,7 @@ left_prompt_segment() { echo -n "${POWERLEVEL9K_WHITESPACE_BETWEEN_LEFT_SEGMENTS}" CURRENT_BG=$3 + last_left_element_index=$current_index } # End the left prompt, closes the final segment. @@ -207,14 +213,21 @@ CURRENT_RIGHT_BG='NONE' # Takes four arguments: # * $1: Name of the function that was orginally invoked (mandatory). # Necessary, to make the dynamic color-overwrite mechanism work. -# * $2: A flag if the segment should be joined with the previous one. +# * $2: The array index of the current segment # * $3: Background color # * $4: Foreground color # * $5: The segment content # * $6: An identifying icon (must be a key of the icons array) # No ending for the right prompt segment is needed (unlike the left prompt, above). +set_default last_right_element_index 1 set_default POWERLEVEL9K_WHITESPACE_BETWEEN_RIGHT_SEGMENTS " " right_prompt_segment() { + local current_index=$2 + + # Check if the segment should be joined with the previous one + local joined + segmentShouldBeJoined $current_index $last_right_element_index "$POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS" && joined=true || joined=false + # Overwrite given background-color by user defined variable for this segment. local BACKGROUND_USER_VARIABLE=POWERLEVEL9K_${(U)1#prompt_}_BACKGROUND local BG_COLOR_MODIFIER=${(P)BACKGROUND_USER_VARIABLE} @@ -229,7 +242,6 @@ right_prompt_segment() { [[ -n "$3" ]] && bg="%K{$3}" || bg="%k" [[ -n "$4" ]] && fg="%F{$4}" || fg="%f" - local joined=$2 # If CURRENT_RIGHT_BG is "NONE", we are the first right segment. if [[ $joined == false ]] || [[ "$CURRENT_RIGHT_BG" == "NONE" ]]; then if isSameColor "$CURRENT_RIGHT_BG" "$3"; then @@ -269,6 +281,7 @@ right_prompt_segment() { echo -n "${visual_identifier}${POWERLEVEL9K_WHITESPACE_BETWEEN_RIGHT_SEGMENTS}%f" CURRENT_RIGHT_BG=$3 + last_right_element_index=$current_index } ################################################################ @@ -286,8 +299,6 @@ prompt_aws() { if [[ -n "$aws_profile" ]]; then "$1_prompt_segment" "$0" "$2" red white "$aws_profile" 'AWS_ICON' - else - last_had_output=false fi } @@ -393,8 +404,6 @@ prompt_battery() { # Draw the prompt_segment if [[ -n $bat_percent ]]; then "$1_prompt_segment" "${0}_${current_state}" "$2" "$DEFAULT_COLOR" "${battery_states[$current_state]}" "$message" 'BATTERY_ICON' - else - last_had_output=false fi } @@ -408,8 +417,6 @@ prompt_context() { else "$1_prompt_segment" "$0_DEFAULT" "$2" "$DEFAULT_COLOR" "011" "$USER@%m" fi - else - last_had_output=false fi } @@ -459,8 +466,6 @@ prompt_go_version() { if [[ -n "$go_version" ]]; then "$1_prompt_segment" "$0" "$2" "green" "255" "$go_version" - else - last_had_output=false fi } @@ -628,8 +633,6 @@ prompt_rbenv() { prompt_root_indicator() { if [[ "$UID" -eq 0 ]]; then "$1_prompt_segment" "$0" "$2" "$DEFAULT_COLOR" "yellow" "" 'ROOT_ICON' - else - last_had_output=false fi } @@ -640,8 +643,6 @@ prompt_rust_version() { if [[ -n "$rust_version" ]]; then "$1_prompt_segment" "$0" "$2" "208" "$DEFAULT_COLOR" "Rust $rust_version" - else - last_had_output=false fi } # RSpec test ratio @@ -679,8 +680,6 @@ prompt_status() { else if [[ "$RETVAL" -ne 0 ]]; then "$1_prompt_segment" "$0_ERROR" "$2" "$DEFAULT_COLOR" "red" "" 'FAIL_ICON' - else - last_had_ouput=false fi fi } @@ -829,30 +828,20 @@ prompt_virtualenv() { build_left_prompt() { defined POWERLEVEL9K_LEFT_PROMPT_ELEMENTS || POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context dir rbenv vcs) - # Global variable to check if the last segment had output. - typeset -g last_had_output=true - + local index=1 for element in "${POWERLEVEL9K_LEFT_PROMPT_ELEMENTS[@]}"; do - # Check if the segment should be joined with the previous one - local joined=false - if [[ ${element[-7,-1]} == '_joined' ]]; then - element="${element[0,-8]}" - if [[ "$last_had_output" == false ]]; then - joined=false + # Remove joined information in direct calls + element=${element%_joined} - # Reset variable - last_had_ouput=true - else - joined=true - fi - fi # Check if it is a custom command, otherwise interpet it as # a prompt. if [[ $element[0,7] =~ "custom_" ]]; then - "prompt_custom" "left" "$joined" $element[8,-1] + "prompt_custom" "left" "$index" $element[8,-1] else - "prompt_$element" "left" "$joined" + "prompt_$element" "left" "$index" fi + + index=$((index + 1)) done left_prompt_end @@ -862,20 +851,20 @@ build_left_prompt() { build_right_prompt() { defined POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS || POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs history time) + local index=1 for element in "${POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS[@]}"; do - # Check if the segment should be joined with the previous one - local joined=false - if [[ ${element[-7,-1]} == '_joined' ]]; then - element="${element[0,-8]}" - joined=true - fi + # Remove joined information in direct calls + element=${element%_joined} + # Check if it is a custom command, otherwise interpet it as # a prompt. if [[ $element[0,7] =~ "custom_" ]]; then - "prompt_custom" "right" "$joined" $element[8,-1] + "prompt_custom" "right" "$index" $element[8,-1] else - "prompt_$element" "right" "$joined" + "prompt_$element" "right" "$index" fi + + index=$((index + 1)) done }