diff --git a/.github/workflows/dorothy-workflow.yml b/.github/workflows/dorothy-workflow.yml index 72bf297a1..b8b12f5ca 100644 --- a/.github/workflows/dorothy-workflow.yml +++ b/.github/workflows/dorothy-workflow.yml @@ -83,7 +83,6 @@ jobs: setup-util-ksh setup-util-carapace dorothy --slug=${{ github.event.pull_request.head.repo.full_name || github.repository }} install - # nu -c 'echo $nu.loginshell-path' - name: 'Dorothy Login Shell: bash' shell: bash -leo pipefail {0} run: | @@ -140,7 +139,7 @@ jobs: # commit changes, if any cd "$DOROTHY" if git diff --quiet &>/dev/null; then - echo 'Already formatted.' + printf '%s\n' 'Already formatted.' else git config --global user.name 'Continuous Integration' git config --global user.email 'bot@bevry.me' diff --git a/commands.beta/echo-eval b/commands.beta/echo-eval index 8d1e53e5b..850717e1d 100755 --- a/commands.beta/echo-eval +++ b/commands.beta/echo-eval @@ -1,5 +1,9 @@ #!/usr/bin/env bash +# [Stack Exchange: How to apply shell command to each line of a command output?](https://stackoverflow.com/a/68310927/130638) +# `ls -1 | xargs -I %s -- echo %s` +# ^ xargs is too complicated, hence why this now exists + function echo_eval() ( source "$DOROTHY/sources/stdinargs.bash" diff --git a/commands.beta/echo-nonflags b/commands.beta/echo-nonflags index 1033d689e..bfc6cf9d5 100755 --- a/commands.beta/echo-nonflags +++ b/commands.beta/echo-nonflags @@ -33,7 +33,7 @@ function echo_nonflags() ( [edit --dry | echo-nonflags --stdin] will output [code -w -n] because of the following: - echo 'code -a --b c' | echo-nonflags --stdin + printf '%s\n' 'code -a --b c' | echo-nonflags --stdin code -a --b c # exit status: 0 diff --git a/commands.beta/echo-nothing-or-fail b/commands.beta/echo-nothing-or-fail index beba5a10e..e80f869f9 100755 --- a/commands.beta/echo-nothing-or-fail +++ b/commands.beta/echo-nothing-or-fail @@ -25,7 +25,7 @@ function echo_nothing_or_fail() ( echo-nothing-or-fail '' echo-nothing-or-fail -- '' echo-nothing-or-fail -- 'sup' - echo 'sup' | echo-nothing-or-fail --stdin + printf '%s\n' 'sup' | echo-nothing-or-fail --stdin # exit status: 1 diff --git a/commands.beta/eval-on-empty-stdin b/commands.beta/eval-on-empty-stdin index ba94aa116..85a55d96b 100755 --- a/commands.beta/eval-on-empty-stdin +++ b/commands.beta/eval-on-empty-stdin @@ -51,9 +51,9 @@ function eval_on_empty_stdin() ( # Action # test cases: - # echo sup | ( eval-on-empty-stdin echo no ) - # true | ( eval-on-empty-stdin echo no ) - # true | ( eval-on-empty-stdin cat ) + # printf '%s\n' sup | ( eval-on-empty-stdin -- printf '%s\n' no ) + # true | ( eval-on-empty-stdin -- printf '%s\n' no ) + # true | ( eval-on-empty-stdin -- cat ) # doesn't work: read -r # doesn't work: [[ -t 0 ]] diff --git a/commands.beta/eval-on-not-empty-stdin b/commands.beta/eval-on-not-empty-stdin index f84f8cd27..92ab54ea0 100755 --- a/commands.beta/eval-on-not-empty-stdin +++ b/commands.beta/eval-on-not-empty-stdin @@ -51,8 +51,8 @@ function eval_on_not_empty_stdin() ( # Action # test cases: - # echo-lines -- 1 2 | ( eval-on-not-empty-stdin cat ) - # true | ( eval-on-not-empty-stdin echo sup ) + # echo-lines -- 1 2 | ( eval-on-not-empty-stdin -- cat ) + # true | ( eval-on-not-empty-stdin -- printf '%s\n' sup ) # doesn't work: grep --regexp='^' | "${option_cmd[@]}" # eval diff --git a/commands.beta/researchgate-rename b/commands.beta/researchgate-rename index 0f9a0beb5..41dcff50b 100755 --- a/commands.beta/researchgate-rename +++ b/commands.beta/researchgate-rename @@ -51,7 +51,6 @@ function researchgate_rename() ( f="$(mktemp)" pdftotext -layout -eol unix "$file" "$f" while read -r line; do - # echo $line if [[ -z $id ]]; then # find id id="$(__print_lines "$line" | echo-regexp -on "$regex" '$1')" diff --git a/commands/ask b/commands/ask index 77f11ef58..95c8c0224 100755 --- a/commands/ask +++ b/commands/ask @@ -396,7 +396,7 @@ function ask_() ( if [[ $ASKED == 'no' ]]; then # do we want to confirm the default value # adding a [&& -t 0] will cause stdin input to always be respected, which is inconsistent with expectations, e.g. - # echo 'overwrite' | { ask --linger --default='d1' --skip-default --question='q1'; ask --linger --default='d2' --skip-default --question='q2' ) + # __print_lines 'overwrite' | { ask --linger --default='d1' --skip-default --question='q1'; ask --linger --default='d2' --skip-default --question='q2' ) # should output 'd1' and 'overwrite', not 'overwrite' and 'd2', as the goal of skip-default is to use the default preference for performance and intuition reasons if [[ $option_confirm_default == 'no' ]] && is-value -- "$RESULT"; then return 0 diff --git a/commands/dorothy-config b/commands/dorothy-config index 6b783d6cb..bee825db4 100755 --- a/commands/dorothy-config +++ b/commands/dorothy-config @@ -232,7 +232,7 @@ function dorothy_config() ( if [[ -n $default_filepath ]]; then # start with the header of the default configuration file echo-lines-before --needle='' --stdin <"$default_filepath" >"$temp_filepath" - echo >>"$temp_filepath" + __print_line >>"$temp_filepath" # inject the sourcing of the default configuration file if [[ $extension == 'nu' ]]; then diff --git a/commands/echo-clear-lines b/commands/echo-clear-lines index 9bf75e74a..de34bf891 100755 --- a/commands/echo-clear-lines +++ b/commands/echo-clear-lines @@ -26,26 +26,26 @@ function echo_clear_lines() ( EXAMPLE: - echo 'sup' + printf '%s\n' 'sup' printf 'a\nb\nc' echo-clear-lines -- $'a\nb\nc' # ^ retains: sup # ^ Note that the argument technique should be discouraged, as can cause [Argument list too long] error: # https://github.com/bevry/dorothy/actions/runs/7622089094/job/20759535555#step:4:3259 - echo 'sup' + printf '%s\n' 'sup' printf 'a\nb\nc' echo-clear-lines --stdin < <(printf 'a\nb\nc') # ^ retains: sup # ^ Use this instead of the arguments option, and do not use <<< as it prints a trailing newline, which would erase 'sup'. - echo 'sup' + printf '%s\n' 'sup' printf 'a\nb\nc' printf 'a\nb\nc' | echo-clear-lines # ^ retains: sup file="\$(mktemp)" - echo 'sup' + printf '%s\n' 'sup' printf 'a\nb\nc' | tee -- "\$file echo-clear-lines < "\$file" # ^ retains: sup diff --git a/commands/echo-escape-bash b/commands/echo-escape-bash index 1b2d1d9ac..4152ae430 100755 --- a/commands/echo-escape-bash +++ b/commands/echo-escape-bash @@ -28,9 +28,9 @@ function echo_escape_bash() ( # bash-5.2$ printf '%q\n' " a'" # \ a\' # bash-5.2$ b=\ a\' - # bash-5.2$ echo "[$b]" + # bash-5.2$ printf '%s\n' "[$b]" # [ a'] - # bash-5.2$ echo "${b@Q}" + # bash-5.2$ printf '%s\n' "${b@Q}" # ' a'\''' function on_input { diff --git a/commands/echo-or-fail b/commands/echo-or-fail index 23a18e31c..f5b7631e6 100755 --- a/commands/echo-or-fail +++ b/commands/echo-or-fail @@ -23,7 +23,7 @@ function echo_or_fail() ( # success cases echo-or-fail -- 'sup' - echo 'sup' | echo-or-fail --stdin + printf '%s\n' 'sup' | echo-or-fail --stdin sup # exit status: 0 diff --git a/commands/echo-style b/commands/echo-style index 81c9ef264..810b58d78 100755 --- a/commands/echo-style +++ b/commands/echo-style @@ -50,10 +50,10 @@ function echo_style() ( Use [--nocolor=] to indicate the value should only be outputted if colors are not. - value="\$(echo-style --bold='first' --nocolor=' ' --color+dim=' → ' --bold='second')"; echo "\$value" + value="\$(echo-style --bold='first' --nocolor=' ' --color+dim=' → ' --bold='second')"; printf '%s\n' "\$value" # outputs with colors: first → second - value="\$(env NO_COLOR=yes echo-style --bold='first' --nocolor=' ' --color+dim=' → ' --bold='second')"; echo "\$value" + value="\$(env NO_COLOR=yes echo-style --bold='first' --nocolor=' ' --color+dim=' → ' --bold='second')"; printf '%s\n' "\$value" # outputs without colors: first second EXPLANATION: diff --git a/commands/fs-realpath b/commands/fs-realpath index c9233b7a8..e5d983be9 100755 --- a/commands/fs-realpath +++ b/commands/fs-realpath @@ -295,7 +295,7 @@ function fs_realpath() ( fi } function __fish_capable { - __command_exists -- fish && [[ "$(version-compare "$(fish -c 'echo $FISH_VERSION')" 3.3.0)" -ge 0 ]] + __command_exists -- fish && [[ "$(version-compare "$(fish -c "printf '%s\n' \$FISH_VERSION")" 3.3.0)" -ge 0 ]] return # explicit return with [[ required for bash v3 } function do_fish_realpath { diff --git a/commands/get-terminal-theme b/commands/get-terminal-theme index 75fdf3738..025b70323 100755 --- a/commands/get-terminal-theme +++ b/commands/get-terminal-theme @@ -129,10 +129,10 @@ function get_terminal_theme() ( # as terminal theme is really only important for TTY use cases, detecting TTY support solves vscode unable to ssh session into a machine if get-terminal-tty-support --quiet; then # /dev/tty as -s flag prevents output): - # echo 'book' | { + # __print_lines 'book' | { # IFS=: read -s -t 1 -d $'\a' -p $'\e]11;?\a' _ color @@ -63,12 +63,12 @@ function secret_() ( For example: - secret env MY_SECRET -- echo 'my secret is: \$MY_SECRET' + secret env MY_SECRET -- printf '%s\n' 'my secret is: \$MY_SECRET' - Will get the value of MY_SECRET, and provide it to the echo command's environment + Will get the value of MY_SECRET, and provide it to the printf command's environment such that when it is interpolated into - echo my secret is: \$MY_SECRET + printf '%s\n' "my secret is: \$MY_SECRET" \$MY_SECRET will be exist in that environment, and be outputted accordingly. @@ -208,7 +208,7 @@ function secret_() ( } if ! sudo-helper --reason="$sudo_reason" -- is-file.bash -- "$database"; then fs-rm --quiet --no-confirm -- "$database" - __print_lines '{}' | sudo tee -- "$database" &>/dev/null + __print_lines '{}' | echo-wait --sudo -- "$database" fi # move old state location to new state location @@ -604,26 +604,26 @@ function secret_() ( return 1 fi if [[ -z $website ]]; then - echo-style --dim="[$item] no urls" + echo-style --dim="[$item] no url to upgrade" >/dev/stderr return 0 fi # upgrade result="$(get-url-upgrade "$website" 2>/dev/null || :)" if [[ -z $result ]]; then - # echo to stdout, as is actionable for user if they are piping + # log echo-style --warning="[$item] [$website] unresponsive, consider archiving" >/dev/stderr return 1 fi # check if changed if [[ $result == "$website" ]]; then - echo-style --dim="[$item] [$website] already upgraded" + echo-style --dim="[$item] [$website] already upgraded" >/dev/stderr return 0 fi - # echo to stdout, as is actionable for user if they are piping - echo-style --success="[$item] [$website] => [$result]" + # log + echo-style --success="[$item] [$website] => [$result]" >/dev/stderr # apply if [[ $op_version -eq 2 ]]; then @@ -667,7 +667,7 @@ function secret_() ( last='' else # continue skipping - echo-style --dim="[$item] skipping" >"$terminal_device_file" + echo-style --dim="[$item] skipping" >/dev/stderr continue fi fi @@ -680,11 +680,11 @@ function secret_() ( # wait for completed jobs, then note completion while [[ "$(get_job_count)" -ne 0 ]]; do - __print_lines "Waiting on [$(get_job_count)] jobs..." >"$terminal_device_file" + echo-style --notice="Waiting on [$(get_job_count)] jobs..." >"$terminal_device_file" sleep 3 jobs &>/dev/null # for some reason, this seems necessary to prevent hung jobs done - __print_lines 'All done.' >"$terminal_device_file" + echo-style --success='All done.' >/dev/stderr } function secret_fetch { @@ -711,10 +711,10 @@ function secret_() ( --arg field "$field" \ '.[$secret] = [$vault, $item, $field]' \ "$database")" - __print_lines "$result" | sudo tee -- "$database" &>/dev/null + __print_lines "$result" | echo-wait --sudo -- "$database" __print_lines \ "Successfully updated [$database] so that [$secret] fetches [$vault].[$item].[$field]" \ - "Fetching [$secret]..." >"$terminal_device_file" + "Fetching [$secret]..." >/dev/stderr cache_delete "$secret" secret_get "$secret" } @@ -726,14 +726,13 @@ function secret_() ( --question='What environment variable (secret) name do you wish to unmap?' \ --default="${1-}" )" - __print_lines 'Enter your sudo password to update the database with the correct permissions...' >"$terminal_device_file" result="$(jq -r \ --arg secret "$secret" \ 'del(.[$secret])' \ "$database")" - __print_lines "$result" | sudo tee -- "$database" + __print_lines "$result" | echo-wait --sudo -- "$database" cache_delete "$secret" - __print_lines "Successfully unmapped [$secret]" >"$terminal_device_file" + __print_lines "Successfully unmapped [$secret]" >/dev/stderr } function secret_env { @@ -762,11 +761,13 @@ function secret_() ( keys=("${before[@]}") args=("${after[@]}") else - __print_lines "found = $found" - __print_lines 'before =' - echo-verbose -- "${before[@]}" - __print_lines 'after =' - echo-verbose -- "${after[@]}" + { + __print_lines "found = $found" + __print_lines 'before =' + echo-verbose -- "${before[@]}" + __print_lines 'after =' + echo-verbose -- "${after[@]}" + } >/dev/stderr help "env action requires [--] separator" fi diff --git a/commands/setup-util-gum b/commands/setup-util-gum index 387e164a8..fdbb26161 100755 --- a/commands/setup-util-gum +++ b/commands/setup-util-gum @@ -38,7 +38,7 @@ # gum_0.11.0_x86_64.apk # rpm repo support requires the following, which isn't important as they provide .rpm files anyway -# echo '[charm] +# printf '%s\n' '[charm] # name=Charm # baseurl=https://repo.charm.sh/yum/ # enabled=1 diff --git a/commands/setup-util-vscode b/commands/setup-util-vscode index ffc8361a0..5ac034026 100755 --- a/commands/setup-util-vscode +++ b/commands/setup-util-vscode @@ -58,8 +58,8 @@ function setup_util_vscode() ( if is-linux; then # https://docs.microsoft.com/en-us/visualstudio/liveshare/reference/linux#install-linux-prerequisites # optional as currently not completely supported on ubuntu 22.04 - # `echo |` to skip the `Press enter to dismiss this message' prompt - echo | setup-util --name='Visual Studio Code: Linux Dependencies' --optional "$@" \ + # `__print_line |` to skip the `Press enter to dismiss this message' prompt + __print_line | setup-util --name='Visual Studio Code: Linux Dependencies' --optional "$@" \ INSTALLER='https://aka.ms/vsls-linux-prereq-script' fi diff --git a/docs/bash/arrays.md b/docs/bash/arrays.md index d530f4035..6d9ea3934 100644 --- a/docs/bash/arrays.md +++ b/docs/bash/arrays.md @@ -22,26 +22,26 @@ a+=( ) for r in "${a[@]}"; do - echo "[$r]" + printf '%s\n' "[$r]" done # args length -echo "$#" +printf '%s\n' "$#" # array length -echo "${#a[@]}" +printf '%s\n' "${#a[@]}" # ^ this is usually okay, but has a gotcha with `mapfile ... <<< ...` usage, see the later chapter about array lengths # contains if is-needle --needle=' ' -- "${a[@]}"; then - echo 'with [ ]' + printf '%s\n' 'with [ ]' else - echo 'without [ ]' + printf '%s\n' 'without [ ]' fi if is-needle --needle='c d' -- "${a[@]}"; then - echo 'with [c d]' + printf '%s\n' 'with [c d]' else - echo 'without [c d]' + printf '%s\n' 'without [c d]' fi # subsets @@ -74,19 +74,19 @@ source "$DOROTHY/sources/bash.bash" # don't do this mapfile -t a <<< "$(failure-because-this-method-does-not-exist | echo-or-fail --stdin)" -echo $? # 0 -- success exit code, despite failure -echo "${#a[@]}" # 1 +printf '%s\n' $? # 0 -- success exit code, despite failure +printf '%s\n' "${#a[@]}" # 1 echo-verbose "${a[@]}" # [0] = [] -- the <<< "$(...)" usage always provides a string to mapfile, so here the empty string becomes an array item # do this instead mapfile -t a < <(failure-because-this-method-does-not-exist | echo-or-fail --stdin) -echo $? # 0 -- success exit code, despite failure -echo "${#a[@]}" # 0 +printf '%s\n' $? # 0 -- success exit code, despite failure +printf '%s\n' "${#a[@]}" # 0 echo-verbose "${a[@]}" # [ nothing provided ] -- the < <(...) usage successfully provides mapfile with zero input, creating an array with zero length # you can use this to ensure that the array is not empty if is-array-empty -- "${a[@]}"; then - echo 'failure' > /dev/stderr + printf '%s\n' 'failure' > /dev/stderr exit 1 fi @@ -262,7 +262,7 @@ If you don't meed the result as an array via `mapfile -t lines` which you would # for newlines list=('a b' $'c\nd' 'e f') echo-lines -- "${list[@]}" | while read -r line; do - echo "[$line]" + printf '%s\n' "[$line]" done # output correct by arguments: # [a b] @@ -273,7 +273,7 @@ done # for custom deliminator list=('a b' $'c\nd' 'e f') echo-split ' ' -- "${list[@]}" | while read -r line; do - echo "[$line]" + printf '%s\n' "[$line]" done # output correct by newline: # [a] diff --git a/docs/bash/errors.md b/docs/bash/errors.md index c9bfbbf06..f5c185238 100644 --- a/docs/bash/errors.md +++ b/docs/bash/errors.md @@ -386,12 +386,12 @@ It causes the following unexpected behaviour: # our standard failure functions, these will be used by our examples function a_function_which_failure_IS_NOT_the_last_command { - echo 'before failure' + printf '%s\n' 'before failure' false # emit an error to this function, as this returns a non-zero exit status - echo 'after failure' + printf '%s\n' 'after failure' } function a_function_which_failure_IS_the_last_command { - echo 'before failure without after' + printf '%s\n' 'before failure without after' false # emit an error to this function, as this returns a non-zero exit status } @@ -418,14 +418,14 @@ case "$example" in 3) set -e ! a_function_which_failure_IS_NOT_the_last_command - echo 'failure' + printf '%s\n' 'failure' # outputs: # before failure # after failure ;; 4) set -e - a_function_which_failure_IS_NOT_the_last_command && echo 'success' + a_function_which_failure_IS_NOT_the_last_command && printf '%s\n' 'success' # outputs: # before failure # after failure @@ -433,7 +433,7 @@ case "$example" in ;; 5) set -e - a_function_which_failure_IS_NOT_the_last_command || echo 'failure' + a_function_which_failure_IS_NOT_the_last_command || printf '%s\n' 'failure' # outputs: # before failure # after failure @@ -441,9 +441,9 @@ case "$example" in 6) set -e if a_function_which_failure_IS_NOT_the_last_command; then - echo 'success' + printf '%s\n' 'success' else - echo 'failure' + printf '%s\n' 'failure' fi # outputs: # before failure @@ -453,9 +453,9 @@ case "$example" in 7) set -e if ! a_function_which_failure_IS_NOT_the_last_command; then - echo 'failure' + printf '%s\n' 'failure' else - echo 'success' + printf '%s\n' 'success' fi # outputs: # before failure @@ -466,8 +466,8 @@ case "$example" in # if the failure is the last command, then such works as expected, as the exit status of any function is always the exit status of the last executed command, regardless of errexit 8) set -e - a_function_which_failure_IS_the_last_command && echo 'success' || echo 'failure' - echo 'ok' + a_function_which_failure_IS_the_last_command && printf '%s\n' 'success' || printf '%s\n' 'failure' + printf '%s\n' 'ok' # outputs: # before failure without after # failure @@ -479,13 +479,13 @@ case "$example" in # without errexit set +e a_function_which_failure_IS_NOT_the_last_command - echo "status=$?" + printf '%s\n' "status=$?" # outputs: # before failure # after failure # status=0 a_function_which_failure_IS_the_last_command - echo "status=$?" + printf '%s\n' "status=$?" # outputs: # before failure without after # status=1 @@ -494,13 +494,13 @@ case "$example" in # with errexit set -e status=0 && a_function_which_failure_IS_NOT_the_last_command || status=$? - echo "status=$status" + printf '%s\n' "status=$status" # outputs: # before failure # after failure # status=0 status=0 && a_function_which_failure_IS_the_last_command || status=$? - echo "status=$status" + printf '%s\n' "status=$status" # outputs: # before failure without after # status=1 diff --git a/docs/bash/foreach-line.md b/docs/bash/foreach-line.md deleted file mode 100644 index 95f89a34d..000000000 --- a/docs/bash/foreach-line.md +++ /dev/null @@ -1,11 +0,0 @@ -# Run a Command for Each Line in Bash - -Sources: - -- [Stack Exchange: How to apply shell command to each line of a command output?](https://stackoverflow.com/a/68310927/130638) - -Advice: - -```bash -ls -1 | xargs -I %s -- echo %s -``` diff --git a/docs/bash/parameter-expansions.md b/docs/bash/parameter-expansions.md index f4b79ac6c..ee1894ba6 100644 --- a/docs/bash/parameter-expansions.md +++ b/docs/bash/parameter-expansions.md @@ -58,29 +58,29 @@ Advice: ```bash # get first line, via pipe, tried and tested -echo -e 'a\nb' | echo-first-line +printf '%s\n' $'a\nb' | echo-first-line # get first line, via variable -var=$'one\ntwo'; echo "${var%$'\n'*}" # one +var=$'one\ntwo'; printf '%s\n' "${var%$'\n'*}" # one # get everything before the first X -var="aXbXc"; echo "${var%%X*}" # a +var="aXbXc"; printf '%s\n' "${var%%X*}" # a # get everything after the first X -var="aXbXc"; echo "${var#*X}" # bXc +var="aXbXc"; printf '%s\n' "${var#*X}" # bXc # get everything before the last X -var="aXbXc"; echo "${var%X*}" # aXb +var="aXbXc"; printf '%s\n' "${var%X*}" # aXb # get everything after the last X -var="aXbXc"; echo "${var##*X}" # c +var="aXbXc"; printf '%s\n' "${var##*X}" # c # replace first o with O -echo "${var/o/O}" +printf '%s\n' "${var/o/O}" # replace all o with O -echo "${var//o/O}" +printf '%s\n' "${var//o/O}" ``` ## get backslash escapes diff --git a/docs/bash/replace-inline.md b/docs/bash/replace-inline.md index 6dc6b5382..53e713efd 100644 --- a/docs/bash/replace-inline.md +++ b/docs/bash/replace-inline.md @@ -9,7 +9,7 @@ if rg --multiline --quiet "$pattern" "$file"; then else # it wasn't found, so add manually if it's not empty if [[ -n "$replace" ]]; then - echo "$replace" >>"$file" + printf '%s\n' "$replace" >>"$file" fi fi ``` @@ -20,7 +20,7 @@ is the same as: if ! rg --multiline --passthru --regexp="$pattern" --replace="$replace" "$file" | echo-wait -- "$file"; then # it wasn't found, so add manually if it's not empty if [[ -n "$replace" ]]; then - echo "$replace" >>"$file" + printf '%s\n' "$replace" >>"$file" fi fi ``` diff --git a/docs/bash/trailing-lines.md b/docs/bash/trailing-lines.md index e30fce230..1eef59d59 100644 --- a/docs/bash/trailing-lines.md +++ b/docs/bash/trailing-lines.md @@ -9,14 +9,14 @@ Advice: ```bash # fails to output trailing line: printf $'a\nb\nc' | while read -r line; do - echo "[$line]" + printf '%s\n' "[$line]" done # [a] # [b] # outputs correctly, including the trailing line: printf $'a\nb\nc' | while read -r line || [[ -n "$line" ]]; do - echo "[$line]" + printf '%s\n' "[$line]" done # [a] # [b] @@ -24,7 +24,7 @@ done # note that <<< works as expected while read -r line; do - echo "[$line]" + printf '%s\n' "[$line]" done <<< $'a\nb\nc' # [a] # [b] @@ -32,7 +32,7 @@ done <<< $'a\nb\nc' # but < <( does not while read -r line; do - echo "[$line]" + printf '%s\n' "[$line]" done < <(printf $'a\nb\nc') # [a] # [b] diff --git a/docs/dorothy/private-configuration.md b/docs/dorothy/private-configuration.md index 3a9e64e8d..92f3b84c3 100644 --- a/docs/dorothy/private-configuration.md +++ b/docs/dorothy/private-configuration.md @@ -40,7 +40,7 @@ setup-util-strongbox strongbox -git-config # add the .local directories to your user repository's .gitattributes file -echo '*.local/* filter=strongbox diff=strongbox' >> .gitattributes +printf '%s\n' '*.local/* filter=strongbox diff=strongbox' >> .gitattributes # generate your strongbox key strongbox -gen-key 'username/repository' diff --git a/docs/scripting/conventions.md b/docs/scripting/conventions.md index 68deb2009..24c3cd6a3 100644 --- a/docs/scripting/conventions.md +++ b/docs/scripting/conventions.md @@ -83,7 +83,7 @@ if [[ "$0" = "${BASH_SOURCE[0]}" ]]; then fi ``` -Variables can use the name of a function or command, e.g. `local source=...; echo "$source"` as variables do not conflict with functions/commands due to them requiring the `$` prefix. +Variables can use the name of a function or command, e.g. `local source=...; printf '%s\n' "$source"` as variables do not conflict with functions/commands due to them requiring the `$` prefix. As bash is a case-sensitive language, we are open to adopting `camelCase` and `CamelCase` if there is well reasoned grounds for it. @@ -108,7 +108,7 @@ Use single-quotes `'` if there is no need for interpolation, use double-quotes ` If doing value substitution, always use double-quotes `"` as single-quotes will be outputted: ```bash -echo "${missing:-'bad'} ${missing:-"good"}" +printf '%s\n' "${missing:-'bad'} ${missing:-"good"}" # outputs: # 'bad' good ``` @@ -137,10 +137,10 @@ Prefer `$var` rather than `${var}` for simple interpolations, for advanced inter ```bash # recommended local indent=' ' world='Earth' -echo "$world" # good -echo "${world}" # bad, unnecessary complexity -echo "${indent}Hello, $world." # fine -echo "${indent}Hello, ${world}." # also fine +printf '%s\n' "$world" # good +printf '%s\n' "${world}" # bad, unnecessary complexity +printf '%s\n' "${indent}Hello, $world." # fine +printf '%s\n' "${indent}Hello, ${world}." # also fine ``` Always use `"$HOME"` instead of `~`, as `~` doesn't work if it is inside a string, which becomes a common mistake when refactoring. @@ -151,26 +151,26 @@ Sometimes you may need to use special characters, such as newlines, here are som ```bash # this is good -echo $'hello\nworld' +printf '%s\n' $'hello\nworld' # but it is too simple for most use cases # a more involved use case would be variable interpolation name='dorothy' -echo $'hello\n$name' +printf '%s\n' $'hello\n$name' # which outputs: # hello # $name # which is not what we desire # let's try this: -echo $"hello\n$name" +printf '%s\n' $"hello\n$name" # which outputs: # hello\ndorothy # which is is still not desire # so let's use this, which is the right technique for the right bits -echo 'hello'$'\n'"$name" # fine -echo $'hello\n'"$name" # also fine +printf '%s\n' 'hello'$'\n'"$name" # fine +printf '%s\n' $'hello\n'"$name" # also fine # which outputs: # hello # dorothy diff --git a/sources/bash.bash b/sources/bash.bash index ad4e74f2f..15c44b820 100644 --- a/sources/bash.bash +++ b/sources/bash.bash @@ -264,7 +264,7 @@ function __sudo_mkdirp { } # bash < 4.2 doesn't support negative lengths, bash >= 4.2 supports negative start indexes however it requires a preceding space or wrapped parenthesis if done directly: ${var: -1} or ${var:(-1)} -# the bash >= 4.2 behaviour returns empty string if negative start index is out of bounds, rather than the entire string, which is unintuitive: v=12345; s=-6; echo "${v:s}" +# the bash >= 4.2 behaviour returns empty string if negative start index is out of bounds, rather than the entire string, which is unintuitive: v=12345; s=-6; __print_lines "${v:s}" # function __substr_native { # local string="$1" start="${2:-0}" length="${3-}" # if [[ -n "$length" ]]; then diff --git a/sources/config.nu b/sources/config.nu index f83c53877..0d8dd5459 100644 --- a/sources/config.nu +++ b/sources/config.nu @@ -6,7 +6,7 @@ # https://www.nushell.sh/commands/docs/source-env.html#frontmatter-title-for-core # nushell does not support dynamic sourcing, also anything it sources must exist prior to execution, as such -# if ( echo 'path' | path exists ) { +# if ( printf '%s\n' 'path' | path exists ) { # source 'path' # } # is useless, as if [path] doesn't exist, [source 'path'] will still fail diff --git a/sources/env.bash b/sources/env.bash index b83dd9745..7f7fd7055 100644 --- a/sources/env.bash +++ b/sources/env.bash @@ -21,7 +21,7 @@ while read -r line; do done done < <(env) -# final scanning of environment, and echo results +# final scanning of environment, and output results function on_env_finish { # ignore failure conditions local last_status=$? @@ -29,7 +29,7 @@ function on_env_finish { return "$last_status" fi - # success condition, echo var actions + # success condition, output var actions local name value i items_array items_string item item_last_index item_index item_existing split_char is_path while read -r line; do # parse line @@ -105,12 +105,12 @@ function on_env_finish { fi done - # echo the variable action based on type + # output the variable action based on type # if [[ "$shell" = 'fish' ]]; then - # echo "set --universal --erase $name;" + # output "set --universal --erase $name;" # fi if [[ -z $value ]]; then - # echo var action: delete + # output var action: delete if [[ $shell == 'fish' ]]; then printf '%s\n' "set --universal --erase $name;" elif [[ $shell == 'nu' ]]; then @@ -124,7 +124,7 @@ function on_env_finish { printf '%s\n' "unset -v $name;" fi elif [[ $is_path == 'yes' ]]; then - # echo var action: set path + # output var action: set path if [[ $shell == 'fish' ]]; then printf '%s\n' "set --export --path $name '$value';" elif [[ $shell == 'nu' ]]; then @@ -138,7 +138,7 @@ function on_env_finish { printf '%s\n' "export $name='$value';" fi else - # echo var action: set + # output var action: set if [[ $shell == 'fish' ]]; then printf '%s\n' "set --export $name '$value';" elif [[ $shell == 'nu' ]]; then diff --git a/sources/environment.fish b/sources/environment.fish index ece124a87..01a3fdaf1 100644 --- a/sources/environment.fish +++ b/sources/environment.fish @@ -2,6 +2,6 @@ # set the environment variables eval ("$DOROTHY/commands/setup-environment-commands" fish || begin - echo "DOROTHY FAILED TO SETUP ENVIRONMENT, RUN THIS TO DEBUG: bash -x '$DOROTHY/commands/setup-environment-commands' fish" >/dev/stderr + printf '%s\n' "DOROTHY FAILED TO SETUP ENVIRONMENT, RUN THIS TO DEBUG: bash -x '$DOROTHY/commands/setup-environment-commands' fish" >/dev/stderr return 1 end) diff --git a/sources/environment.sh b/sources/environment.sh index 4bbb67343..4ea3b0cb2 100644 --- a/sources/environment.sh +++ b/sources/environment.sh @@ -17,6 +17,6 @@ fi # set the environment variables eval "$("$DOROTHY/commands/setup-environment-commands" "$ACTIVE_POSIX_SHELL" || { - echo "DOROTHY FAILED TO SETUP ENVIRONMENT, RUN THIS TO DEBUG: bash -x '$DOROTHY/commands/setup-environment-commands' '$ACTIVE_POSIX_SHELL'" >/dev/stderr + printf '%s\n' "DOROTHY FAILED TO SETUP ENVIRONMENT, RUN THIS TO DEBUG: bash -x '$DOROTHY/commands/setup-environment-commands' '$ACTIVE_POSIX_SHELL'" >/dev/stderr return 1 })" diff --git a/sources/history.fish b/sources/history.fish index 37370737d..fe576a842 100644 --- a/sources/history.fish +++ b/sources/history.fish @@ -4,22 +4,22 @@ function secure_history set action (choose --question='What do you want to delete?' --default=$argv[1] --label -- 'some' 'delete only the known risks' 'all' 'erase your entire history') if test "$action" = 'all'; then history -c - echo 'Erased everything.' + printf '%s\n' 'Erased everything.' else - echo 'all' | history delete --contains 'auth' - echo 'all' | history delete --contains 'cookie' - echo 'all' | history delete --contains 'env' - echo 'all' | history delete --contains 'http -f POST' - echo 'all' | history delete --contains 'http POST' - echo 'all' | history delete --contains 'key' - echo 'all' | history delete --contains 'op ' - echo 'all' | history delete --contains 'secret' - echo 'all' | history delete --contains 'session' - echo 'all' | history delete --contains 'token' - echo 'all' | history delete --contains 'twurl' - echo 'all' | history delete --contains 'vault' - echo 'all' | history delete --contains 'youtube-dl' - echo 'all' | history delete --contains 'coda register' - echo 'Erased known risks.' + printf '%s\n' 'all' | history delete --contains 'auth' + printf '%s\n' 'all' | history delete --contains 'cookie' + printf '%s\n' 'all' | history delete --contains 'env' + printf '%s\n' 'all' | history delete --contains 'http -f POST' + printf '%s\n' 'all' | history delete --contains 'http POST' + printf '%s\n' 'all' | history delete --contains 'key' + printf '%s\n' 'all' | history delete --contains 'op ' + printf '%s\n' 'all' | history delete --contains 'secret' + printf '%s\n' 'all' | history delete --contains 'session' + printf '%s\n' 'all' | history delete --contains 'token' + printf '%s\n' 'all' | history delete --contains 'twurl' + printf '%s\n' 'all' | history delete --contains 'vault' + printf '%s\n' 'all' | history delete --contains 'youtube-dl' + printf '%s\n' 'all' | history delete --contains 'coda register' + printf '%s\n' 'Erased known risks.' end end diff --git a/sources/history.nu b/sources/history.nu index a5f01e3ae..c945170db 100644 --- a/sources/history.nu +++ b/sources/history.nu @@ -2,5 +2,5 @@ def secure_history [] { history -c - echo 'Erased everything.' + printf '%s\n' 'Erased everything.' } diff --git a/sources/history.sh b/sources/history.sh index 506d02302..f857ddfc5 100644 --- a/sources/history.sh +++ b/sources/history.sh @@ -9,9 +9,9 @@ secure_history() { )" if [ "$action" = 'erase your entire history' ]; then history -c - echo 'Erased everything.' + printf '%s\n' 'Erased everything.' else - echo 'Erasing only known risks is not supported in shells that are not Fish.' >/dev/stderr + printf '%s\n' 'Erasing only known risks is not supported in shells that are not Fish.' >/dev/stderr return 1 fi } diff --git a/sources/ssh.sh b/sources/ssh.sh index d184f4407..a4e3a06de 100644 --- a/sources/ssh.sh +++ b/sources/ssh.sh @@ -10,7 +10,7 @@ # fatal: failed to write commit object # you can test it is working via: # setup-git -# echo 'test' | gpg --clearsign +# printf '%s\n' 'test' | gpg --clearsign # if you are still getting those errors, check via `gpg-helper list` that your key has not expired # if it has, then run `gpg-helper extend` if command-exists -- gpg; then diff --git a/themes/oz.fish b/themes/oz.fish index 527c43e72..15d782bc2 100644 --- a/themes/oz.fish +++ b/themes/oz.fish @@ -3,7 +3,7 @@ function fish_prompt set last_command_exit_status "$status" if test ! -d "$DOROTHY" - echo 'DOROTHY has been moved, please re-open your shell' + printf '%s\n' 'DOROTHY has been moved, please re-open your shell' >/dev/stderr return 1 end "$DOROTHY/themes/oz" fish "$last_command_exit_status"