123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #
- # output.bash
- # -----------
- #
- # Private functions implementing output formatting. Used by public
- # helper functions.
- #
- # Print a message to the standard error. When no parameters are
- # specified, the message is read from the standard input.
- #
- # Globals:
- # none
- # Arguments:
- # $@ - [=STDIN] message
- # Returns:
- # none
- # Inputs:
- # STDIN - [=$@] message
- # Outputs:
- # STDERR - message
- batslib_err() {
- { if (( $# > 0 )); then
- echo "$@"
- else
- cat -
- fi
- } >&2
- }
- # Count the number of lines in the given string.
- #
- # TODO(ztombol): Fix tests and remove this note after #93 is resolved!
- # NOTE: Due to a bug in Bats, `batslib_count_lines "$output"' does not
- # give the same result as `${#lines[@]}' when the output contains
- # empty lines.
- # See PR #93 (https://github.com/sstephenson/bats/pull/93).
- #
- # Globals:
- # none
- # Arguments:
- # $1 - string
- # Returns:
- # none
- # Outputs:
- # STDOUT - number of lines
- batslib_count_lines() {
- local -i n_lines=0
- local line
- while IFS='' read -r line || [[ -n $line ]]; do
- (( ++n_lines ))
- done < <(printf '%s' "$1")
- echo "$n_lines"
- }
- # Determine whether all strings are single-line.
- #
- # Globals:
- # none
- # Arguments:
- # $@ - strings
- # Returns:
- # 0 - all strings are single-line
- # 1 - otherwise
- batslib_is_single_line() {
- for string in "$@"; do
- (( $(batslib_count_lines "$string") > 1 )) && return 1
- done
- return 0
- }
- # Determine the length of the longest key that has a single-line value.
- #
- # This function is useful in determining the correct width of the key
- # column in two-column format when some keys may have multi-line values
- # and thus should be excluded.
- #
- # Globals:
- # none
- # Arguments:
- # $odd - key
- # $even - value of the previous key
- # Returns:
- # none
- # Outputs:
- # STDOUT - length of longest key
- batslib_get_max_single_line_key_width() {
- local -i max_len=-1
- while (( $# != 0 )); do
- local -i key_len="${#1}"
- batslib_is_single_line "$2" && (( key_len > max_len )) && max_len="$key_len"
- shift 2
- done
- echo "$max_len"
- }
- # Print key-value pairs in two-column format.
- #
- # Keys are displayed in the first column, and their corresponding values
- # in the second. To evenly line up values, the key column is fixed-width
- # and its width is specified with the first parameter (possibly computed
- # using `batslib_get_max_single_line_key_width').
- #
- # Globals:
- # none
- # Arguments:
- # $1 - width of key column
- # $even - key
- # $odd - value of the previous key
- # Returns:
- # none
- # Outputs:
- # STDOUT - formatted key-value pairs
- batslib_print_kv_single() {
- local -ir col_width="$1"; shift
- while (( $# != 0 )); do
- printf '%-*s : %s\n' "$col_width" "$1" "$2"
- shift 2
- done
- }
- # Print key-value pairs in multi-line format.
- #
- # The key is displayed first with the number of lines of its
- # corresponding value in parenthesis. Next, starting on the next line,
- # the value is displayed. For better readability, it is recommended to
- # indent values using `batslib_prefix'.
- #
- # Globals:
- # none
- # Arguments:
- # $odd - key
- # $even - value of the previous key
- # Returns:
- # none
- # Outputs:
- # STDOUT - formatted key-value pairs
- batslib_print_kv_multi() {
- while (( $# != 0 )); do
- printf '%s (%d lines):\n' "$1" "$( batslib_count_lines "$2" )"
- printf '%s\n' "$2"
- shift 2
- done
- }
- # Print all key-value pairs in either two-column or multi-line format
- # depending on whether all values are single-line.
- #
- # If all values are single-line, print all pairs in two-column format
- # with the specified key column width (identical to using
- # `batslib_print_kv_single').
- #
- # Otherwise, print all pairs in multi-line format after indenting values
- # with two spaces for readability (identical to using `batslib_prefix'
- # and `batslib_print_kv_multi')
- #
- # Globals:
- # none
- # Arguments:
- # $1 - width of key column (for two-column format)
- # $even - key
- # $odd - value of the previous key
- # Returns:
- # none
- # Outputs:
- # STDOUT - formatted key-value pairs
- batslib_print_kv_single_or_multi() {
- local -ir width="$1"; shift
- local -a pairs=( "$@" )
- local -a values=()
- local -i i
- for (( i=1; i < ${#pairs[@]}; i+=2 )); do
- values+=( "${pairs[$i]}" )
- done
- if batslib_is_single_line "${values[@]}"; then
- batslib_print_kv_single "$width" "${pairs[@]}"
- else
- local -i i
- for (( i=1; i < ${#pairs[@]}; i+=2 )); do
- pairs[$i]="$( batslib_prefix < <(printf '%s' "${pairs[$i]}") )"
- done
- batslib_print_kv_multi "${pairs[@]}"
- fi
- }
- # Prefix each line read from the standard input with the given string.
- #
- # Globals:
- # none
- # Arguments:
- # $1 - [= ] prefix string
- # Returns:
- # none
- # Inputs:
- # STDIN - lines
- # Outputs:
- # STDOUT - prefixed lines
- batslib_prefix() {
- local -r prefix="${1:- }"
- local line
- while IFS='' read -r line || [[ -n $line ]]; do
- printf '%s%s\n' "$prefix" "$line"
- done
- }
- # Mark select lines of the text read from the standard input by
- # overwriting their beginning with the given string.
- #
- # Usually the input is indented by a few spaces using `batslib_prefix'
- # first.
- #
- # Globals:
- # none
- # Arguments:
- # $1 - marking string
- # $@ - indices (zero-based) of lines to mark
- # Returns:
- # none
- # Inputs:
- # STDIN - lines
- # Outputs:
- # STDOUT - lines after marking
- batslib_mark() {
- local -r symbol="$1"; shift
- # Sort line numbers.
- set -- $( sort -nu <<< "$( printf '%d\n' "$@" )" )
- local line
- local -i idx=0
- while IFS='' read -r line || [[ -n $line ]]; do
- if (( ${1:--1} == idx )); then
- printf '%s\n' "${symbol}${line:${#symbol}}"
- shift
- else
- printf '%s\n' "$line"
- fi
- (( ++idx ))
- done
- }
- # Enclose the input text in header and footer lines.
- #
- # The header contains the given string as title. The output is preceded
- # and followed by an additional newline to make it stand out more.
- #
- # Globals:
- # none
- # Arguments:
- # $1 - title
- # Returns:
- # none
- # Inputs:
- # STDIN - text
- # Outputs:
- # STDOUT - decorated text
- batslib_decorate() {
- echo
- echo "-- $1 --"
- cat -
- echo '--'
- echo
- }
|