From 8aaac0e4d6ec558cd827040fe0baf46f48022536 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 11:06:03 -0700 Subject: [PATCH 1/7] prompt: add extra newlines to simplify code management --- mozilla_aws_cli/role_picker.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index b94f57a..ab6fc2c 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -11,7 +11,8 @@ logger = logging.getLogger(__name__) -PROMPT_BASH_CODE = r'''function maws_profile { +PROMPT_BASH_CODE = r''' +function maws_profile { if [ -n "${MAWS_PROMPT}" ]; then if [ -n "${AWS_SESSION_EXPIRATION}" ] && [ $(date +%s) -gt ${AWS_SESSION_EXPIRATION} ]; then echo " (maws keys expired)" @@ -30,7 +31,8 @@ else PS1="${PS1}\$(maws_profile) " fi -fi''' +fi +''' def output_set_env_vars(var_map, message=None): From 42abad5cfaf0311d92cb16e2d48e54775c0a2822 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 13:07:51 -0700 Subject: [PATCH 2/7] prompt: switch to bash-native conditionals --- CHANGELOG.md | 3 +++ mozilla_aws_cli/role_picker.py | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4a8968..29ecf11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +* Convert conditionals to bash-native to simplify maintenance and readability + ## [1.2.3] - 2021-04-27 ### Fixed diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index ab6fc2c..492f771 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -13,8 +13,8 @@ PROMPT_BASH_CODE = r''' function maws_profile { - if [ -n "${MAWS_PROMPT}" ]; then - if [ -n "${AWS_SESSION_EXPIRATION}" ] && [ $(date +%s) -gt ${AWS_SESSION_EXPIRATION} ]; then + if [[ -n $MAWS_PROMPT ]]; then + if [[ -n $AWS_SESSION_EXPIRATION && "$(date +%s)" -gt $AWS_SESSION_EXPIRATION ]]; then echo " (maws keys expired)" else echo " (${MAWS_PROMPT})" @@ -22,11 +22,11 @@ fi } -if test "${PS1#*\$\(maws_profile\)}" = "$PS1"; then +if [[ $PS1 != *'$(maws_profile)' ]]; then # maws_profile is missing from PS1 - if [ "${PS1%\$ }" != "${PS1}" ]; then + if [[ $PS1 == *'\$ ' ]]; then PS1="${PS1%\$ }\$(maws_profile)\$ " - elif [ "${PS1% }" != "${PS1}" ]; then + elif [[ $PS1 == *' ' ]]; then PS1="${PS1% }\$(maws_profile) " else PS1="${PS1}\$(maws_profile) " From c7e4ce5bbf08070f5eb8f4e9c39ff52c22bc10c7 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 12:21:54 -0700 Subject: [PATCH 3/7] prompt: enable modifying prefix/suffix whitespace --- CHANGELOG.md | 1 + mozilla_aws_cli/role_picker.py | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29ecf11..04a6794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed * Convert conditionals to bash-native to simplify maintenance and readability +* Add internal logic to allow more complex prefix/suffix whitespace logic ## [1.2.3] - 2021-04-27 diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index 492f771..1e2b899 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -14,15 +14,25 @@ PROMPT_BASH_CODE = r''' function maws_profile { if [[ -n $MAWS_PROMPT ]]; then + # either a whitespace character or blank, depending on what + # was selected by the prompt injection routine below. + echo -n "$MAWS_PROMPT_PREFIX" if [[ -n $AWS_SESSION_EXPIRATION && "$(date +%s)" -gt $AWS_SESSION_EXPIRATION ]]; then - echo " (maws keys expired)" + echo -n "(maws keys expired)" else - echo " (${MAWS_PROMPT})" + echo -n "(${MAWS_PROMPT})" fi + # either a whitespace character or blank, depending on what + # followed the maws substitution point in the original prompt + echo -n "$MAWS_PROMPT_SUFFIX" fi } if [[ $PS1 != *'$(maws_profile)' ]]; then + # the original behavior is to always prefix and never suffix, + # so we maintain that here for now while expanding capability. + MAWS_PROMPT_PREFIX=" " + MAWS_PROMPT_SUFFIX="" # maws_profile is missing from PS1 if [[ $PS1 == *'\$ ' ]]; then PS1="${PS1%\$ }\$(maws_profile)\$ " From 908bffba29e4eddae8226b91fc0d25fa7bdccfe0 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 09:48:09 -0700 Subject: [PATCH 4/7] prompt: enable dynamic prompt evaluation for zsh --- CHANGELOG.md | 3 +++ mozilla_aws_cli/role_picker.py | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04a6794..9c951ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +* Enable zsh dynamic prompts for users who don't already have them enabled. + ### Changed * Convert conditionals to bash-native to simplify maintenance and readability * Add internal logic to allow more complex prefix/suffix whitespace logic diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index 1e2b899..36f9a7b 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -28,6 +28,9 @@ fi } +# zsh requires this in order to evaluate the prompt dynamically like bash +[[ -n "$ZSH_VERSION" ]] && setopt prompt_subst + if [[ $PS1 != *'$(maws_profile)' ]]; then # the original behavior is to always prefix and never suffix, # so we maintain that here for now while expanding capability. @@ -35,7 +38,15 @@ MAWS_PROMPT_SUFFIX="" # maws_profile is missing from PS1 if [[ $PS1 == *'\$ ' ]]; then + # prompt ends with hard-coded '$ ' PS1="${PS1%\$ }\$(maws_profile)\$ " + elif [[ $PS1 == *' %# ' ]]; then + # prompt ends with dynamic ' %# '; remove one space character prior + # to the substitution to prevent double-whitespace issues + PS1="${PS1% \%# }\$(maws_profile)%# " + elif [[ $PS1 == *'%# ' ]]; then + # prompt ends with dynamic '%# ' + PS1="${PS1%\%# }\$(maws_profile)%# " elif [[ $PS1 == *' ' ]]; then PS1="${PS1% }\$(maws_profile) " else From be6dad0bc38c8b40f8d518ad3ee90dd226d4856b Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 12:32:26 -0700 Subject: [PATCH 5/7] prompt: add MAWS_PROMPT_DISABLE to skip injection --- CHANGELOG.md | 5 +++++ mozilla_aws_cli/role_picker.py | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c951ff..7268c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Convert conditionals to bash-native to simplify maintenance and readability * Add internal logic to allow more complex prefix/suffix whitespace logic +### Added +* Allow users to disable prompt modification with `MAWS_PROMPT_DISABLE=1`. + (This also lets users implement their own custom prompts without forking, + as long as they define `function maws_profile () { }` in bashrc/zshrc.) + ## [1.2.3] - 2021-04-27 ### Fixed diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index 36f9a7b..f4a6e70 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -31,7 +31,9 @@ # zsh requires this in order to evaluate the prompt dynamically like bash [[ -n "$ZSH_VERSION" ]] && setopt prompt_subst -if [[ $PS1 != *'$(maws_profile)' ]]; then +# if the user hasn't disabled prompt injection, +# and we aren't already injecting maws_profile: +if [[ -z $MAWS_PROMPT_DISABLE && $PS1 != *'$(maws_profile)' ]]; then # the original behavior is to always prefix and never suffix, # so we maintain that here for now while expanding capability. MAWS_PROMPT_PREFIX=" " From c5db7dbe7e8e2d7ec8acd1335d7293b3521139c7 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 12:55:52 -0700 Subject: [PATCH 6/7] prompt: fix double-whitespace characters in certain prompts --- CHANGELOG.md | 1 + mozilla_aws_cli/role_picker.py | 59 ++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7268c33..84e757b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * Enable zsh dynamic prompts for users who don't already have them enabled. +* Fix issues with double-whitespace when injecting into space-separated prompts ### Changed * Convert conditionals to bash-native to simplify maintenance and readability diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index f4a6e70..ec5bd01 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -35,23 +35,68 @@ # and we aren't already injecting maws_profile: if [[ -z $MAWS_PROMPT_DISABLE && $PS1 != *'$(maws_profile)' ]]; then # the original behavior is to always prefix and never suffix, - # so we maintain that here for now while expanding capability. + # so we default to that before overriding it in specific cases. MAWS_PROMPT_PREFIX=" " MAWS_PROMPT_SUFFIX="" # maws_profile is missing from PS1 if [[ $PS1 == *'\$ ' ]]; then + # prompt ends with dynamic '\$ ' + if [[ $PS1 == *' \$ ' ]]; then + # the original prompt surrounds the final '\$' with whitespace, + # so we surround the substitution with whitespace to maintain that. + MAWS_PROMPT_PREFIX="" + MAWS_PROMPT_SUFFIX=" " + else + # the original prompt doesn't have whitespace before the final '\$', + # so we only prefix but not suffix with whitespace to maintain that. + MAWS_PROMPT_PREFIX=" " + MAWS_PROMPT_SUFFIX="" + fi + # inject our substitution before the original '$ ' + PS1="${PS1%\\$ }\$(maws_profile)\\$ " + elif [[ $PS1 == *'$ ' ]]; then # prompt ends with hard-coded '$ ' + if [[ $PS1 == *' $ ' ]]; then + # the original prompt surrounds the final '$' with whitespace, + # so we surround the substitution with whitespace to maintain that. + MAWS_PROMPT_PREFIX="" + MAWS_PROMPT_SUFFIX=" " + else + # the original prompt doesn't have whitespace before the final '$ ', + # so we only prefix but not suffix with whitespace to maintain that. + MAWS_PROMPT_PREFIX=" " + MAWS_PROMPT_SUFFIX="" + fi + # inject our substitution before the original '$ ' PS1="${PS1%\$ }\$(maws_profile)\$ " - elif [[ $PS1 == *' %# ' ]]; then - # prompt ends with dynamic ' %# '; remove one space character prior - # to the substitution to prevent double-whitespace issues - PS1="${PS1% \%# }\$(maws_profile)%# " elif [[ $PS1 == *'%# ' ]]; then # prompt ends with dynamic '%# ' + if [[ $PS1 == *' %# ' ]]; then + # the original prompt surrounds the final '$' with whitespace, + # so we only suffix bot not prefix with whitespace to maintain that. + MAWS_PROMPT_PREFIX="" + MAWS_PROMPT_SUFFIX=" " + else + # the original prompt doesn't have whitespace before the final '$ ', + # so we only prefix but not suffix with whitespace to maintain that. + MAWS_PROMPT_PREFIX=" " + MAWS_PROMPT_SUFFIX="" + fi + # inject our substitution before the original '%# ' PS1="${PS1%\%# }\$(maws_profile)%# " - elif [[ $PS1 == *' ' ]]; then - PS1="${PS1% }\$(maws_profile) " else + # we're the last entry in the prompt, so we don't need extra whitespace. + MAWS_PROMPT_SUFFIX="" + if [[ $PS1 == *' ' ]]; then + # the original prompt ends with whitespace, + # so we don't need to prefix whitespace ourselves. + MAWS_PROMPT_PREFIX="" + else + # the original prompt doesn't end with whitespace, + # so we prefix whitespace ourselves. + MAWS_PROMPT_PREFIX=" " + fi + # inject our substitution before the original '%# ' PS1="${PS1}\$(maws_profile) " fi fi From 236b5e0b3d3c0466e1f9dc49023c237a6d56aa45 Mon Sep 17 00:00:00 2001 From: floatingatoll Date: Tue, 15 Jun 2021 14:39:31 -0700 Subject: [PATCH 7/7] prompt: remove default-duplicating conditions --- mozilla_aws_cli/role_picker.py | 62 ++++++++-------------------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/mozilla_aws_cli/role_picker.py b/mozilla_aws_cli/role_picker.py index ec5bd01..ce8c7a2 100644 --- a/mozilla_aws_cli/role_picker.py +++ b/mozilla_aws_cli/role_picker.py @@ -34,68 +34,36 @@ # if the user hasn't disabled prompt injection, # and we aren't already injecting maws_profile: if [[ -z $MAWS_PROMPT_DISABLE && $PS1 != *'$(maws_profile)' ]]; then - # the original behavior is to always prefix and never suffix, - # so we default to that before overriding it in specific cases. - MAWS_PROMPT_PREFIX=" " - MAWS_PROMPT_SUFFIX="" + # by default, we prefix but not suffix; good for example '\w\$', + # but has to be overridden below for various whitespace cases. + MAWS_PROMPT_PREFIX=" " MAWS_PROMPT_SUFFIX="" # maws_profile is missing from PS1 if [[ $PS1 == *'\$ ' ]]; then # prompt ends with dynamic '\$ ' - if [[ $PS1 == *' \$ ' ]]; then - # the original prompt surrounds the final '\$' with whitespace, - # so we surround the substitution with whitespace to maintain that. - MAWS_PROMPT_PREFIX="" - MAWS_PROMPT_SUFFIX=" " - else - # the original prompt doesn't have whitespace before the final '\$', - # so we only prefix but not suffix with whitespace to maintain that. - MAWS_PROMPT_PREFIX=" " - MAWS_PROMPT_SUFFIX="" - fi + # if the original prompt surrounds the final '\$' with whitespace, + # we surround the substitution with whitespace to maintain that. + [[ $PS1 == *' \$ ' ]] && MAWS_PROMPT_PREFIX="" MAWS_PROMPT_SUFFIX=" " # inject our substitution before the original '$ ' PS1="${PS1%\\$ }\$(maws_profile)\\$ " elif [[ $PS1 == *'$ ' ]]; then # prompt ends with hard-coded '$ ' - if [[ $PS1 == *' $ ' ]]; then - # the original prompt surrounds the final '$' with whitespace, - # so we surround the substitution with whitespace to maintain that. - MAWS_PROMPT_PREFIX="" - MAWS_PROMPT_SUFFIX=" " - else - # the original prompt doesn't have whitespace before the final '$ ', - # so we only prefix but not suffix with whitespace to maintain that. - MAWS_PROMPT_PREFIX=" " - MAWS_PROMPT_SUFFIX="" - fi + # if the original prompt surrounds the final '$' with whitespace, + # we surround the substitution with whitespace to maintain that. + [[ $PS1 == *' $ ' ]] && MAWS_PROMPT_PREFIX="" MAWS_PROMPT_SUFFIX=" " # inject our substitution before the original '$ ' PS1="${PS1%\$ }\$(maws_profile)\$ " elif [[ $PS1 == *'%# ' ]]; then # prompt ends with dynamic '%# ' - if [[ $PS1 == *' %# ' ]]; then - # the original prompt surrounds the final '$' with whitespace, - # so we only suffix bot not prefix with whitespace to maintain that. - MAWS_PROMPT_PREFIX="" - MAWS_PROMPT_SUFFIX=" " - else - # the original prompt doesn't have whitespace before the final '$ ', - # so we only prefix but not suffix with whitespace to maintain that. - MAWS_PROMPT_PREFIX=" " - MAWS_PROMPT_SUFFIX="" - fi + # if the original prompt surrounds the final '$' with whitespace, + # we only suffix bot not prefix with whitespace to maintain that. + [[ $PS1 == *' %# ' ]] && MAWS_PROMPT_PREFIX="" MAWS_PROMPT_SUFFIX=" " # inject our substitution before the original '%# ' PS1="${PS1%\%# }\$(maws_profile)%# " else # we're the last entry in the prompt, so we don't need extra whitespace. - MAWS_PROMPT_SUFFIX="" - if [[ $PS1 == *' ' ]]; then - # the original prompt ends with whitespace, - # so we don't need to prefix whitespace ourselves. - MAWS_PROMPT_PREFIX="" - else - # the original prompt doesn't end with whitespace, - # so we prefix whitespace ourselves. - MAWS_PROMPT_PREFIX=" " - fi + # if the original prompt ends with whitespace, + # we don't need to prefix whitespace ourselves. + [[ $PS1 == *' ' ]] && MAWS_PROMPT_PREFIX="" # inject our substitution before the original '%# ' PS1="${PS1}\$(maws_profile) " fi