From 5ead13d6aa6303c85c562f1b940048cc539667cd Mon Sep 17 00:00:00 2001 From: Rashil Gandhi <46838874+rashil2000@users.noreply.github.com> Date: Sun, 21 Jan 2024 18:25:52 +0530 Subject: [PATCH] feat(bash): Support right prompt and transience (#4902) * Support right prompt in bash * Docs for transience in bash * Apply suggestions from review * Simplify conditional * Use ble.sh hooks, if available * Properly quote args * Use BLE_PIPESTATUS * Update starship.bash * Update src/init/starship.bash Co-authored-by: Koichi Murase --------- Co-authored-by: Koichi Murase --- docs/advanced-config/README.md | 39 +++++++++++++++++++++++++++++++++- src/init/starship.bash | 20 +++++++++++++---- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/advanced-config/README.md b/docs/advanced-config/README.md index 13f30c0c..b728a632 100644 --- a/docs/advanced-config/README.md +++ b/docs/advanced-config/README.md @@ -106,6 +106,41 @@ starship init fish | source enable_transience ``` +## TransientPrompt and TransientRightPrompt in Bash + +The [Ble.sh](https://github.com/akinomyoga/ble.sh) framework allows you to replace +the previous-printed prompt with custom strings. This is useful in cases where all +the prompt information is not always needed. To enable this, put this in `~/.bashrc` +`bleopt prompt_ps1_transient=`: + +The \ here is a colon-separated list of `always`, `same-dir` and `trim`. +When `prompt_ps1_final` is empty and this option has a non-empty value, +the prompt specified by `PS1` is erased on leaving the current command line. +If the value contains a field `trim`, only the last line of multiline `PS1` is +preserved and the other lines are erased. Otherwise, the command line will be +redrawn as if `PS1=` is specified. When a field `same-dir` is contained in the +value and the current working directory is different from the final directory of +the previous command line, this option `prompt_ps1_transient` is ignored. + +Make the following changes to your `~/.bashrc` to customize what gets displayed on +the left and on the right: + +- To customize what the left side of input gets replaced with, configure the + `prompt_ps1_final` Ble.sh option. For example, to display Starship's `character` + module here, you would do + +```bash +bleopt prompt_ps1_final="$(starship module character)" +``` + +- To customize what the right side of input gets replaced with, configure the + `prompt_rps1_final` Ble.sh option. For example, to display + the time at which the last command was started here, you would do + +```bash +bleopt prompt_rps1_final="$(starship module time)" +``` + ## Custom pre-prompt and pre-execution Commands in Cmd Clink provides extremely flexible APIs to run pre-prompt and pre-exec commands @@ -261,7 +296,9 @@ not explicitly used in either `format` or `right_format`. Note: The right prompt is a single line following the input location. To right align modules above the input line in a multi-line prompt, see the [`fill` module](/config/#fill). -`right_format` is currently supported for the following shells: elvish, fish, zsh, xonsh, cmd, nushell. +`right_format` is currently supported for the following shells: elvish, fish, zsh, xonsh, cmd, nushell, bash. + +Note: The [Ble.sh](https://github.com/akinomyoga/ble.sh) framework should be installed in order to use right prompt in bash. ### Example diff --git a/src/init/starship.bash b/src/init/starship.bash index b7f7cb0e..5a62be85 100644 --- a/src/init/starship.bash +++ b/src/init/starship.bash @@ -33,6 +33,9 @@ starship_preexec() { starship_precmd() { # Save the status, because commands in this pipeline will change $? STARSHIP_CMD_STATUS=$? STARSHIP_PIPE_STATUS=(${PIPESTATUS[@]}) + if [[ ${BLE_ATTACHED-} && ${#BLE_PIPESTATUS[@]} -gt 0 ]]; then + STARSHIP_PIPE_STATUS=("${BLE_PIPESTATUS[@]}") + fi if [[ "${#BP_PIPESTATUS[@]}" -gt "${#STARSHIP_PIPE_STATUS[@]}" ]]; then STARSHIP_PIPE_STATUS=(${BP_PIPESTATUS[@]}) fi @@ -64,21 +67,30 @@ starship_precmd() { eval "$_PRESERVED_PROMPT_COMMAND" + local -a ARGS=(--terminal-width="${COLUMNS}" --status="${STARSHIP_CMD_STATUS}" --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --jobs="${NUM_JOBS}") # Prepare the timer data, if needed. if [[ $STARSHIP_START_TIME ]]; then STARSHIP_END_TIME=$(::STARSHIP:: time) STARSHIP_DURATION=$((STARSHIP_END_TIME - STARSHIP_START_TIME)) - PS1="$(::STARSHIP:: prompt --terminal-width="$COLUMNS" --status=$STARSHIP_CMD_STATUS --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --jobs="$NUM_JOBS" --cmd-duration=$STARSHIP_DURATION)" + ARGS+=( --cmd-duration="${STARSHIP_DURATION}") unset STARSHIP_START_TIME - else - PS1="$(::STARSHIP:: prompt --terminal-width="$COLUMNS" --status=$STARSHIP_CMD_STATUS --pipestatus="${STARSHIP_PIPE_STATUS[*]}" --jobs="$NUM_JOBS")" + fi + PS1="$(::STARSHIP:: prompt "${ARGS[@]}")" + if [[ ${BLE_ATTACHED-} ]]; then + local nlns=${PS1//[!$'\n']} + bleopt prompt_rps1="$nlns$(::STARSHIP:: prompt --right "${ARGS[@]}")" fi STARSHIP_PREEXEC_READY=true # Signal that we can safely restart the timer } +# If the user appears to be using https://github.com/akinomyoga/ble.sh, +# then hook our functions into their framework. +if [[ ${BLE_VERSION-} && _ble_version -ge 400 ]]; then + blehook PREEXEC!='starship_preexec "$_"' + blehook PRECMD!='starship_precmd' # If the user appears to be using https://github.com/rcaloras/bash-preexec, # then hook our functions into their framework. -if [[ "${__bp_imported:-}" == "defined" || $preexec_functions || $precmd_functions ]]; then +elif [[ "${__bp_imported:-}" == "defined" || $preexec_functions || $precmd_functions ]]; then # bash-preexec needs a single function--wrap the args into a closure and pass starship_preexec_all(){ starship_preexec "$_"; } preexec_functions+=(starship_preexec_all)