diff --git a/commands.beta/echo-revolving-screen b/commands.beta/echo-revolving-screen new file mode 100755 index 000000000..306aa1aee --- /dev/null +++ b/commands.beta/echo-revolving-screen @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +function echo_revolving_screen() ( + source "$DOROTHY/sources/bash.bash" + + # ===================================== + # Arguments + + function help { + cat <<-EOF >/dev/stderr + ABOUT: + Continously clear the output of a command, showing only the latest output, then clearing it upon completion. + + USAGE: + (echo-lines -- 1 2; sleep 2; echo-lines -- 3 4; sleep 2) | echo-revolving-door [...options] + # outputs 2, then waits, then outputs 4, then waits, then clears + + OPTIONS: + --columns= + The number of columns to display. If not provided, the terminal's columns will be used. If the terminal's columns cannot be determined, or if <= 0, then the full line will be displayed. + EOF + if test "$#" -ne 0; then + echo-error "$@" + fi + return 22 # EINVAL 22 Invalid argument + } + + # process + local item option_lines='' option_columns='' + while test "$#" -ne 0; do + item="$1" + shift + case "$item" in + '--help' | '-h') help ;; + '--lines='*) option_lines="${item#*=}" ;; + '--columns='*) option_columns="${item#*=}" ;; + '--'*) help "An unrecognised flag was provided: $item" ;; + *) help "An unrecognised argument was provided: $item" ;; + esac + done + + # determine columns + if test -z "$option_lines" -o -z "$option_columns"; then + local terminal_size=() + mapfile -t terminal_size < <(get-terminal-lines-and-columns || :) + if test "${#terminal_size[@]}" -eq 2; then + if test -z "$option_lines"; then + option_lines="${terminal_size[0]}" + fi + if test -z "$option_columns"; then + option_columns="${terminal_size[1]}" + fi + fi + fi + + # ===================================== + # Action + + if test -z "$option_lines" -o -z "$option_columns" || test "$option_lines" -le 0 -o "$option_columns" -le 0; then + cat + else + local terminal_device_file clear_screen + terminal_device_file="$(get-terminal-device-file)" + clear_screen=$'\e[H\e[J' + + local input total_lines=0 status wrapped lines=0 + while IFS='' read -r input || test -n "$input"; do + eval_capture --statusvar=status --outputvar=wrapped \ + -- gfold --width="$option_columns" <<<"$input" + #-- echo-wrap --width="$option_columns" -- "$input" + if test "$status" -ne 0; then + echo-error "$wrapped" + return "$status" + fi + # count lines + lines="$(echo-count-lines -- "$wrapped")" + total_lines="$((total_lines + lines))" + if test "$total_lines" -ge "$option_lines"; then + if test "$lines" -ge "$option_lines"; then + # this line is very long and wraps across all lines of our screen, this is an edge case + # use a coreutil to trim the excess lines + __print_lines "${clear_screen}${wrapped}" | head -n "$option_lines" + else + # clear the screen + __print_lines "${clear_screen}${wrapped}" >"$terminal_device_file" + fi + total_lines="$lines" + else + # print the wrapped output + __print_lines "$wrapped" >"$terminal_device_file" + fi + done + # we are now done, so clear wrapped + # echo-clear-lines --count="$lines" >"$terminal_device_file" + __print_string "${clear_screen}" >"$terminal_device_file" + fi +) + +# fire if invoked standalone +if test "$0" = "${BASH_SOURCE[0]}"; then + echo_revolving_screen "$@" +fi diff --git a/commands/brew-installed b/commands/brew-installed index 548b67178..cd54d395b 100755 --- a/commands/brew-installed +++ b/commands/brew-installed @@ -3,13 +3,18 @@ function brew_installed() ( source "$DOROTHY/sources/bash.bash" + # compatibility + if ! is-brew; then + return 46 # EPFNOSUPPORT 46 Protocol family not supported + fi + # ===================================== # Arguments function help { cat <<-EOF >/dev/stderr ABOUT: - Outputs the names of the installed packages. + Outputs the names of the homebrew installed packages. USAGE: brew-installed [...options] -- [...] @@ -24,18 +29,21 @@ function brew_installed() ( --cask Output only packages that are casks. + --quiet + If provided, do not output anything, just return the exist status. + ... If provided, only get details for these packages. Fail if one of them has not yet been installed. QUIRKS: - If packages are provided, failure exit code will be returned if any are missing. + If packages are provided, failure exist status will be returned if any are missing. To check if any are present, use: - $(echo-style --code="test -n \"\$(brew-installed -- bash something-missing &>/dev/null || :)\"") + $(echo-style --code="test -n \"\$(brew-installed -- bash something-missing || :)\"") - If you just want the exit code, use: + If you just want the exist status, use: - $(echo-style --code="brew-installed -- bash something-missing &>/dev/null") + $(echo-style --code="brew-installed --quiet -- bash something-missing") EOF if test "$#" -ne 0; then echo-error "$@" @@ -44,12 +52,12 @@ function brew_installed() ( } # process - local item option_requested='no' packages=() brew_type brew_list_cmd brew_info_cmd deno_script_args - brew_type='' # empty, formula, cask + local item option_quiet='' option_requested='no' option_packages=() option_type brew_list_cmd brew_info_cmd deno_script_args + option_type='' # empty, formula, cask brew_list_cmd=( 'brew' 'list' - '--versions' # --versions is necessary to limit to installed packages, as --full-name/-1 doesn't + '--versions' # --versions is necessary to limit to installed option_packages, as --full-name/-1 doesn't ) brew_info_cmd=( 'brew' @@ -63,13 +71,19 @@ function brew_installed() ( shift case "$item" in '--help' | '-h') help ;; - '--formula' | '--formulae') brew_type='formula' ;; - '--cask' | '--casks') brew_type='cask' ;; + '--no-verbose'* | '--verbose'*) + option_quiet="$(get-flag-value --non-affirmative --fallback="$option_quiet" -- "$item")" + ;; + '--no-quiet'* | '--quiet'*) + option_quiet="$(get-flag-value --affirmative --fallback="$option_quiet" -- "$item")" + ;; + '--formula' | '--formulae') option_type='formula' ;; + '--cask' | '--casks') option_type='cask' ;; '--no-requested'* | '--requested'*) option_requested="$(get-flag-value --affirmative --fallback="$option_requested")" ;; '--') - packages+=("$@") + option_packages+=("$@") shift $# break ;; @@ -79,18 +93,18 @@ function brew_installed() ( done # add the filter - if test -n "$brew_type"; then - brew_list_cmd+=("--$brew_type") - brew_info_cmd+=("--$brew_type") - deno_script_args+=("--$brew_type") + if test -n "$option_type"; then + brew_list_cmd+=("--$option_type") + brew_info_cmd+=("--$option_type") + deno_script_args+=("--$option_type") fi # add the packages - if test "${#packages[@]}" -ne 0; then - brew_list_cmd+=("${packages[@]}") + if test "${#option_packages[@]}" -ne 0; then + brew_list_cmd+=("${option_packages[@]}") brew_info_cmd+=( '--json=v2' - "${packages[@]}" + "${option_packages[@]}" ) else brew_info_cmd+=( @@ -104,7 +118,11 @@ function brew_installed() ( function do_brew_simple { # handles only --cask and --formula, but not --requested - "${brew_list_cmd[@]}" | cut -d' ' -f1 | sort | uniq + if test "$option_quiet" = 'yes'; then + "${brew_list_cmd[@]}" &>/dev/null + else + "${brew_list_cmd[@]}" | cut -d' ' -f1 | sort | uniq + fi } function do_brew_advanced { @@ -116,15 +134,19 @@ function brew_installed() ( # run local deno_script deno_script="$(type -P 'brew-installed.ts')" - "${brew_info_cmd[@]}" | "$deno_script" "${deno_script_args[@]}" + if test "$option_quiet" = 'yes'; then + "${brew_info_cmd[@]}" | "$deno_script" "${deno_script_args[@]}" &>/dev/null + else + "${brew_info_cmd[@]}" | "$deno_script" "${deno_script_args[@]}" + fi } # get names of requested packages if test "$option_requested" = 'no'; then do_brew_simple - elif test "${#packages[@]}" -eq 0; then + elif test "${#option_packages[@]}" -eq 0; then do_brew_advanced - elif test "$(do_brew_advanced | echo-count-lines --no-inline --stdin)" -ne "${#packages[@]}"; then + elif test "$(do_brew_advanced | echo-count-lines --no-inline --stdin)" -ne "${#option_packages[@]}"; then return 1 fi ) diff --git a/commands/echo-quote b/commands/echo-quote index 1c6f7eed0..74b0a4e11 100755 --- a/commands/echo-quote +++ b/commands/echo-quote @@ -16,6 +16,12 @@ function echo_quote() ( echo-lines ... | echo-quote [...options] OPTIONS: + --double + If specified, output the as a double quoted string. + + --single + If specified, output the as a single quoted string. + $(stdinargs_options_help --) EOF if test "$#" -ne 0; then @@ -24,22 +30,41 @@ function echo_quote() ( return 22 # EINVAL 22 Invalid argument } + # process our own arguments, delegate everything else to stdinargs + local item option_quote_desired='' + while test "$#" -ne 0; do + item="$1" + shift + case "$item" in + '--help' | '-h') help ;; + '--double') option_quote_desired='double' ;; + '--single') option_quote_desired='single' ;; + # forward to stdinargs, however support mixing and matching of our options, with stdinarg options + '--') + option_args+=("$item" "$@") + shift $# + break + ;; + *) option_args+=("$item") ;; + esac + done + # ===================================== # Action # this is not the same as ${var@Q}, which handles single quotes differently function on_input { local item="$1" - if [[ $item != *"'"* ]]; then + if [[ $item != *"'"* ]] && test "$option_quote_desired" != 'double'; then # does not contain single quotes __print_lines "'$item'" - elif [[ $item != *'"'* ]]; then + elif [[ $item != *'"'* ]] && test "$option_quote_desired" != 'single'; then # does not contain double quotes __print_lines "\"$item\"" - elif [[ $item != *"\\'"* ]]; then + elif [[ $item != *"\\'"* ]] && test "$option_quote_desired" != 'double'; then # does not contain escaped single quotes __print_lines "'${item//\'/\\\'}'" - elif [[ $item != *"\\\""* ]]; then + elif [[ $item != *"\\\""* ]] && test "$option_quote_desired" != 'single'; then # does not contain escaped double quotes __print_lines "\"${item//\"/\\\"}\"" else @@ -51,7 +76,7 @@ function echo_quote() ( fi } - stdinargs "$@" + stdinargs "${option_args[@]}" ) # fire if invoked standalone diff --git a/commands/echo-revolving-door b/commands/echo-revolving-door index e9d587677..bd1f63184 100755 --- a/commands/echo-revolving-door +++ b/commands/echo-revolving-door @@ -69,33 +69,3 @@ function echo_revolving_door() ( if test "$0" = "${BASH_SOURCE[0]}"; then echo_revolving_door "$@" fi - -# if is-mac; then -# bin_gfold="$(type -P 'gfold' 2>/dev/null || :)" -# else -# # we could support these on macos, however fmt does not support -t on macos (it is something different, so we'd have to manually do that) -# bin_gfold="$(type -P 'fold' 2>/dev/null || :)" -# fi -# if test -z "$bin_gfold"; then -# use_cat='yes' -# fi - -# local input last_input='' -# function clear_last_input { -# if test -z "$last_input"; then -# : # do nothing -# elif [[ $last_input =~ $'\e\[[0-9]*[AKGFJ]' ]]; then -# printf '\e[G\e[2K' # set cursor to start of line, and clear from there -# else -# local count -# count="$(__print_string "$last_input" | echo-count-lines --stdin)" -# printf "\e[${count}A\e[G\e[J" # move cursor up count, set cursor to start of line, and delete everything from there -# fi -# } -# while IFS='' read -r input || test -n "$input"; do -# clear_last_input -# input="$(__print_string "$input" | "$bin_gfold" -w "$size_columns")" -# __print_lines "$input" -# last_input="$input" -# done -# clear_last_input diff --git a/commands/fs-rm b/commands/fs-rm index 240fcf92e..f698e93ff 100755 --- a/commands/fs-rm +++ b/commands/fs-rm @@ -93,6 +93,7 @@ function fs_rm() ( if test "$option_trash" = 'yes'; then setup-util-trash --quiet --optional --no-fallback if __command_missing -- trash; then + echo-style --dim='Moving to trash is not available, falling back to immediate deletion for: ' --code="${option_paths[*]}" >/dev/stderr option_trash='no' fi fi diff --git a/commands/setup-util b/commands/setup-util index c5ad5c389..11df6902c 100755 --- a/commands/setup-util +++ b/commands/setup-util @@ -515,32 +515,45 @@ function setup_util() ( help 'Either , , , , , must be provided.' fi + # prep terminal vars + local terminal_device_file use_alt_screen_buffer alternative_screen_buffer default_screen_buffer + terminal_device_file="$(get-terminal-device-file)" + if get-terminal-alternative-support --quiet && test "$option_quiet" != 'no'; then + use_alt_screen_buffer='yes' + alternative_screen_buffer="$(echo-style --no-trail --alternative-screen-buffer)" + default_screen_buffer="$(echo-style --no-trail --default-screen-buffer)" + else + use_alt_screen_buffer='no' + alternative_screen_buffer='' + default_screen_buffer='' + fi + # check for action (--check=yes/command would have already exited, as it would have above) if test -n "$option_app" -o -n "$option_cli" -o -n "$option_font"; then if test "$app_exists" != 'yes' -a "$cli_exists" != 'yes' -a "$font_exists" != 'yes'; then # nothing installed if test "$option_action" = 'uninstall'; then # already uninstalled, so no need to uninstall - maybe_echo_style --good3="The [$option_name] utility was not found. Already uninstalled. ✅" >/dev/stderr + maybe_echo_style --good3="The [$option_name] utility was not found. Already uninstalled. ✅" >"$terminal_device_file" # exit return 0 fi option_upgrade='no' # note that we aren't upgrading, which is used for logging # perform install - maybe_echo_style --header3="The [$option_name] utility was not found. Installing automatically... ⏲" >/dev/stderr + maybe_echo_style --header3="The [$option_name] utility was not found. Installing automatically... ⏲" >"$terminal_device_file" elif test "$option_action" = 'uninstall'; then # exists, uninstall enabled option_upgrade='no' # note that we aren't upgrading, which is used for logging # perform uninstall - maybe_echo_style --header3="The [$option_name] utility is marked for uninstall. Uninstalling... ⏲" >/dev/stderr + maybe_echo_style --header3="The [$option_name] utility is marked for uninstall. Uninstalling... ⏲" >"$terminal_device_file" elif test "$option_upgrade" = 'yes'; then # exists, upgrade enabled # perform upgrade - maybe_echo_style --header3="The [$option_name] utility is marked for upgrade. Upgrading... ⏲" >/dev/stderr + maybe_echo_style --header3="The [$option_name] utility is marked for upgrade. Upgrading... ⏲" >"$terminal_device_file" elif test "$cli_working" = 'fail'; then # exists, not working # perform reinstall - maybe_echo_style --header3="The [$option_name] utility via [$option_cli] is misbehaving. Reinstalling automatically... ⏲" >/dev/stderr + maybe_echo_style --header3="The [$option_name] utility via [$option_cli] is misbehaving. Reinstalling automatically... ⏲" >"$terminal_device_file" elif test "$option_check" = 'no'; then # exists, don't care, proceed anyway # used by setup-util-nerd-fonts to ensure we check for the correct font @@ -548,7 +561,7 @@ function setup_util() ( else # exists, no upgrade, is working # already installed, so no need to install again - maybe_echo_style --good3="The [$option_name] utility is already installed. ✅" >/dev/stderr + maybe_echo_style --good3="The [$option_name] utility is already installed. ✅" >"$terminal_device_file" return 0 fi fi @@ -668,7 +681,7 @@ function setup_util() ( # do not do this for uninstall, as we want the actual methods to handle that if test "$option_upgrade" = 'yes'; then if test -n "$option_cli"; then - rm_helper "$XDG_BIN_HOME/$option_cli" "/usr/local/bin/$option_cli" + rm_helper "$XDG_BIN_HOME/$option_cli" # "/usr/local/bin/$option_cli" fi fi @@ -1817,16 +1830,28 @@ function setup_util() ( fi # args + local brew_removal_operation='no' if test "$option_action" = 'uninstall'; then if ! __are_all_of_these_brew_packages_installed "${packages[@]}"; then return 200 # ECUSTOM 200 Not applicable for this package system fi + # uninstall + brew_removal_operation='yes' args+=( 'brew' 'uninstall' ) + # note that if this is uninstalling the version of bash that is currently running, then the script will crash with exit status 137 + elif test "$option_upgrade" = 'yes'; then + # upgrade + brew_removal_operation='yes' + args+=( + 'brew' + 'reinstall' + ) + # note that if this is reinstalling the version of bash that is currently running, then the script will crash with exit status 137 else - # install / upgrade + # install args+=( 'brew' 'install' @@ -1839,6 +1864,19 @@ function setup_util() ( args+=("${opts[@]}") fi + # note if brew will cause us to crash + if test "$brew_removal_operation" = 'yes' && is-needle bash -- "${packages[@]}" && test -x "$HOMEBREW_PREFIX/bin/bash" && test "$BASH_VERSION" = "$("$HOMEBREW_PREFIX/bin/bash" -c 'printf %s $BASH_VERSION')"; then + # moving the homebrew bash to trash, or a temp directory does not work + # as it seems bash requires the invoked bash path to exist, and if it doesn't, it crashes + # it is our own script crashing with 137 and not homebrew + # trapping 137 doesn't work either, one gets [bash: trap: 137: invalid signal specification] + # the only thing that works is invoking such a script with system bash, however there is no way to do that comprehensively, so we just warn + __print_string "$default_screen_buffer" >"$terminal_device_file" + echo-style --stderr \ + --notice1='Homebrew is about to delete the currently running bash executable, which will cause this sript to crash with exit status ' --code-notice1='137' --newline \ + --notice1='Once crashed, please manually continue by re-running the prior script that you executed.' + fi + # packages "${args[@]}" "${packages[@]}" } @@ -1881,7 +1919,8 @@ function setup_util() ( fi # opts - if test "$option_quiet" != 'no'; then + if test "$option_quiet" = 'yes'; then + # --quiet for casks is too quiet opts+=('--quiet') fi @@ -3669,14 +3708,26 @@ function setup_util() ( # So we're using our own, note that return codes can't go higher than 232 # 200 = not applicable ... - local had_success='no' had_failure='no' had_finish='no' action_log + local had_success='no' had_failure='no' had_finish='no' action_current action_past if test "$option_action" = 'uninstall'; then - action_log='uninstalled' + action_current='uninstalling' + action_past='uninstalled' elif test "$option_upgrade" = 'yes'; then - action_log='upgraded' + action_current='upgrading' + action_past='upgraded' else - action_log='installed' + action_current='installing' + action_past='installed' fi + function log_pending { + local suffix='' method="${1-}" + if test -n "$method"; then + suffix+=" via [$method]... ⏲" + else + suffix+='... ⏲' + fi + maybe_echo_style --good3="The [$option_name] utility is ${action_current}${suffix}" + } function log_success { local suffix='' method="${1-}" if test -n "$method"; then @@ -3684,7 +3735,7 @@ function setup_util() ( else suffix+='. ✅' fi - maybe_echo_style --good3="The [$option_name] utility was ${action_log}${suffix}" >/dev/stderr + maybe_echo_style --good3="The [$option_name] utility was ${action_past}${suffix}" } function log_failure { local suffix='' method="${1-}" @@ -3696,29 +3747,41 @@ function setup_util() ( suffix='. ❌' fi if test "$option_optional" = 'yes'; then - maybe_echo_style --notice3="The [$option_name] optional utility was not ${action_log}${suffix}" >/dev/stderr + maybe_echo_style --notice3="The [$option_name] optional utility was not ${action_past}${suffix}" else - echo-style --error3="The [$option_name] required utility was not ${action_log}${suffix}" >/dev/stderr + echo-style --error3="The [$option_name] required utility was not ${action_past}${suffix}" fi return 0 } function run_installer { # install/upgrade until successful, uninstall for all - local run_status method="$1" fn="$2" run_output - eval_capture --statusvar=run_status --outputvar=run_output --outputpipe=/dev/stderr -- "$fn" + local run_status method="$1" fn="$2" # run_output + + #eval_capture --statusvar=run_status -- "$fn" + + # don't always do log_pending, as that will cause all the 200 not applicable ones to be dumped + + if test "$use_alt_screen_buffer" = 'yes'; then + __print_string "$alternative_screen_buffer" "$(log_pending "$method")" $'\n' >"$terminal_device_file" + eval_capture --statusvar=run_status --outputvar=run_output --outputpipe="$terminal_device_file" -- "$fn" + __print_string "$default_screen_buffer" >"$terminal_device_file" + else + eval_capture --statusvar=run_status -- "$fn" + fi + + # eval_helper is compatible with setup-util-warp, however it becomes incredibly slow to cycle through all the installers + # eval_capture --statusvar=run_status -- eval_helper --shapeshifter --no-wrap --quiet="$option_quiet" -- "$fn" if test "$run_status" -eq 0; then - # if is to fix: [is-internet-working; setup-util-bash --quiet] from clearning extra lines - if test -n "$run_output" -a "$option_quiet" != 'no'; then - # if the output is longer than $LINES then output beyond $LINES will not be cleared, the only way around that is to use tty_start and tty_finish however that incurs a signficant performance penalty, perhaps doing [2> (echo-revolving-door > /dev/stderr)] or something akin to this would work, however it had too many artifacts with [setup-util-warp --uninstall; setup-util-warp --install] with cask usage that uses sudo - echo-clear-lines --stdin < <(__print_string "$run_output") >/dev/stderr - fi had_success='yes' - log_success "$method" + log_success "$method" >"$terminal_device_file" if test "$option_action" != 'uninstall'; then had_finish='yes' fi elif test "$run_status" -ne 200; then - log_failure "$method" + if test "$use_alt_screen_buffer" = 'yes'; then + __print_lines "$run_output" >/dev/stderr # needs to be print lines + fi + log_failure "$method" >/dev/stderr if test "$option_action" = 'uninstall'; then had_failure='yes' # an uninstall failed fi @@ -3765,19 +3828,19 @@ function setup_util() ( if test "$option_action" = 'uninstall'; then # @todo detect if cli is still present, if so, perhaps prompt the user what to do if test "$had_failure" = 'no'; then - log_success + log_success >"$terminal_device_file" else # still some that aren't uninstalled - log_failure + log_failure >/dev/stderr if test "$option_optional" != 'yes'; then return 1 fi fi elif test "$had_success" = 'yes'; then # at least one installed - log_success + log_success >"$terminal_device_file" else - log_failure + log_failure >/dev/stderr if test "$option_optional" != 'yes'; then return 1 fi diff --git a/commands/setup-util-bash b/commands/setup-util-bash index d70885ac0..5406448aa 100755 --- a/commands/setup-util-bash +++ b/commands/setup-util-bash @@ -3,14 +3,6 @@ # https://repology.org/project/bash/versions -# @note that if they have installed bash via homebrew, and that is what is invoking this script, and then that is what is being uninstalled, the script will crash once bash has been removed. Other methods shouldn't have this issue, as they move the bash executable to a 'trash' equiavlent directory, which allows the invoked script to continue. This is such an edge case, it's not worth doing more on, unless a user actually reports a valid need for a warning or workaround. A workaround being ensuring this script invokes with the system bash instead of the installed bash. - -# @todo instead of compiling from source with DOWNLOAD, consider using homebrew bottles -# can use [get-macos-release-name] to figure it out programatically -# https://github.com/Homebrew/homebrew-core/pkgs/container/core%2Fbash -# > brew info --json bash | jq -r ".[].bottle.stable.files" -# ^ this command above is how you find the bottle url for the current system - function setup_util_bash() ( source "$DOROTHY/sources/bash.bash" # imports: @@ -18,18 +10,37 @@ function setup_util_bash() ( # BASH_VERSION_CURRENT # BASH_VERSION_LATEST + # check if we are macos, in which we need special handling + if test "${RELOADED_IN_SYSTEM_BASH-}" != 'yes'; then + if is-needle --upgrade -- "$@" || is-needle --uninstall -- "$@"; then + # upgrading or uninstalling + if is-mac && test -x /bin/bash && brew-installed --formula --quiet -- bash; then + # reload in system bash to pevent brew's upgrade/uninstall from crashing us + env RELOADED_IN_SYSTEM_BASH=yes /bin/bash "${BASH_SOURCE[0]}" "$@" + return + fi + else + # not upgrading or uninstalling + if test "$IS_BASH_VERSION_OUTDATED" = 'yes'; then + # bash is terrible outdated + if is-mac && test -x /bin/bash; then + # run in system bash to prevent possible upgrade crash + env RELOADED_IN_SYSTEM_BASH=yes /bin/bash "${BASH_SOURCE[0]}" --upgrade "$@" + return + else + # run ourself again with upgrade + env RELOADED_IN_SYSTEM_BASH=yes "${BASH_SOURCE[0]}" --upgrade "$@" + return + fi + fi + fi + fi + # enable DOWNLOAD_BUILD_INSTALL source "$(type -P setup-util)" - # if outdated bash, then enable upgrade option - local extras=() - if test "$IS_BASH_VERSION_OUTDATED" = 'yes'; then - extras+=('--upgrade') - fi - # setup bash local bottle_url='' macos_release arch options=( - "${extras[@]}" --cli='bash' "$@" APK='bash' # ALPINE @@ -108,7 +119,8 @@ function setup_util_bash() ( fi setup_util "${options[@]}" - # check if still outdated, if so, install via building instead + # check if the updated bash outdated, if so, install via building instead + # this works as it is new invocation so has refreshed env vars inside it if is-bash-version-outdated --quiet; then options+=( --upgrade @@ -147,10 +159,10 @@ function setup_util_bash() ( login_shell_version="$("$login_shell" -c -- 'echo $BASH_VERSION')" bash_shell_version="$("$bash_shell" -c -- 'echo $BASH_VERSION')" if test "$login_shell_version" != "$bash_shell_version"; then - echo-style --header2="Your login shell is an outdated version of bash." - echo-style --header2="You will now be prompted now to change it to a more modern shell." + echo-style --header2='Your login shell is an outdated version of bash.' + echo-style --header2='You will now be prompted now to change it to a more modern shell.' setup-shell - echo-style --header2="Close this terminal, open a new one, then run the command you ran again." + echo-style --header2='Close this terminal, open a new one, then run the command you ran again.' return 0 fi fi diff --git a/config/styles.bash b/config/styles.bash index a19b78d3e..6a950196d 100644 --- a/config/styles.bash +++ b/config/styles.bash @@ -22,9 +22,9 @@ ALTERNNATIVE_SCREEN_BUFFER_SUPPORTED="$(get-terminal-alternative-support)" # ANSI STYLES ######################### # terminal -style__clear_line=$'\e[G\e[2K' # move cursor to beginning of current line and erase/clear/overwrite-with-whitespace the line, $'\e[G\e[J' is equivalent -style__delete_line=$'\e[F\e[J' # move cursor to beginning of the prior line and erase/clear/overwrite-with-whitespace all lines from there -style__clear_screen=$'\e[H\e[2J' # move cursor to the beginning of the screen buffer and erase/clear/overwrite-with-whitespace from there - note that non-visible lines are not altered +style__clear_line=$'\e[G\e[2K' # move cursor to beginning of current line and erase/clear/overwrite-with-whitespace the line, $'\e[G\e[J' is equivalent +style__delete_line=$'\e[F\e[J' # move cursor to beginning of the prior line and erase/clear/overwrite-with-whitespace all lines from there + style__enable_cursor_blinking=$'\e[?12h' style__disable_cursor_blinking=$'\e[?12l' style__show_cursor=$'\e[?25h' @@ -39,6 +39,7 @@ style__cursor_steady_bar=$'\e[6 q' if test "$ALTERNNATIVE_SCREEN_BUFFER_SUPPORTED" = 'yes'; then style__alternative_screen_buffer=$'\e[?1049h' # switch-to/enable/open alternative screen buffer (of which there is only one) style__default_screen_buffer=$'\e[?1049l' # restore/enable/open/switch-to the default/primary/main/normal screen buffer + style__clear_screen=$'\e[H\e[J' # # \e[H\e[J moves cursor to the top and erases the screen (so no effect to the scroll buffer), unfortunately \e[2J moves the cursor to the bottom, then prints a screen worth of blank lines, then moves the cursor to the top (keeping what was on the screen in the scroll buffer, padded then by a screen of white space); tldr \e[H\e[J wipes the screen, \e[2J pads the screen else # if unable to tap into alterantive screen buffer, then output a newline (in case clear screen isn't supported) and clear the screen (which GitHub CI doesn't support, but it does not output the ansi escape code) - without this change, then following output will incorrectly be on the same line as the previous output # https://github.com/bevry/dorothy/actions/runs/11358242517/job/31592464176#step:2:3754 @@ -47,7 +48,7 @@ else style__alternative_screen_buffer="$style__clear_screen" style__default_screen_buffer=$'\n'"$style__clear_screen" # ensure clears are also moved to next line: https://github.com/bevry/dorothy/actions/runs/11358588333/job/31593337760#step:2:2449 - style__clear_screen=$'\n'$'\e[H\e[2J' + style__clear_screen=$'\n'$'\e[H\e[J' fi style__bell=$'\a'