#!/bin/bash
# list - Bash array support
set -e
######
# List helpers
# in_list() - Returns success if the item ($1) is found in the list ($@).
in_list() {
min_args 1 "$@"
local thing=$1
shift
local found=false
for i in "$@"; do
[ "$i" != "$thing" ] || found=true
done
$found
}
# list_insert() - Inserts items ($@) at the beginning of the named array ($1).
list_insert() {
min_args 1 "$@"
local _list_insert_var=$1
shift
eval "$_list_insert_var=( \"\$@\" "\${$_list_insert_var\[@\]}" )"
}
# list_append() - Appends items ($@) to the end of the named array ($1).
list_append() {
min_args 1 "$@"
local _list_append_var=$1
shift
eval "$_list_append_var=( \"\${${_list_append_var}[@]}\" \"\$@\" )"
}
# list_pop() - Removes and prints the last item from the named array ($1).
list_pop() {
has_args 1 "$@"
local _list_var=$1
shift
local _value
eval "_value=\"\${${_list_var}[-1]}\""
local length
eval "length=\${#${_list_var}[*]}"
eval "$_list_var=( \"\${${_list_var}[@]:0:$(($length - 1))}\" )"
echo "$_value"
}
# list_fpop() - Removes and prints the first item from the named array ($1).
list_fpop() {
has_args 1 "$@"
local _list_var=$1
shift
local _value
eval "_value=\"\${${_list_var}[0]}\""
eval "$_list_var=( "\${${_list_var}[@]:1}" )"
echo "$_value"
}
######
# List Iteration
# for_each() - Calls a function ($1) for each item ($@).
for_each() {
min_args 1 "$@"
local func=$1
shift
local _for_each
for _for_each in "$@"; do
$func "$_for_each"
done
}
# run_for_each() - Calls a function ($1) using ``run()`` for each item ($@).
run_for_each() {
local func=$1
shift
for_each "run $func" "$@"
}
# for_each_pair() - Calls a function ($1) for each pair of arguments ($@).
# If an odd number of arguments are given, an error will be produced.
for_each_pair() {
local func=$1
shift
[ $((${#*} % 2)) == 0 ] || error "odd number of arguments"
while [ ${#*} -gt 0 ]; do
$func "$1" "$2"
shift 2
done
}
######
# List Transformations
# list_reverse() - Reverse the order of items in the named array ($1).
list_reverse() {
min_max_args 1 2 "$@"
local __src=$1
local __dst=${2:-$1}
local -a src
eval "src=( \"\${${__src}[@]}\" )"
local i
local -a dst
for i in $(seq $((${#src[@]} - 1)) -1 0); do
dst+=( "${src[$i]}" )
done
eval "$__dst=( \"\${dst[@]}\" )"
}
# list_quote() - Quotes the items in the named list ($1).
list_quote() {
min_max_args 1 2 "$@"
list_map arg_quote "$@"
}
# list_join() - Joins arguments using the given character
# TODO: rename str_join?
# $1 - character to use for joining arguments
# $@ - strings to be joined by $1
list_join() {
local IFS=$1
shift
echo "$*"
}
# list_filter() - Runs a filter ($1) for each item in the named array
# ($2). If the filter function returns success, the item will be
# included in the output array ($3, or $2 if not given).
# $1 - Filter command
# $2 - Input list
# $3 - Output list (optional)
list_filter() {
min_max_args 2 3 "$@"
local __func=$1
local __list=$2
local __dest=${3:-$2}
local -a __out
eval "for_each _list_filter \"\${${__list}[@]}\""
eval "$__dest=( \"\${__out[@]}\" )"
}
_list_filter() {
local __item=$1
if $__func "$__item"; then
list_append __out "$__item"
fi
}
# list_filter_empty() - Removes empty items from the named array ($1) and
# saves them in the output array ($2, or $1 if not given).
# $1 - Input list
# $2 - Output list (optional)
list_filter_empty() {
min_max_args 1 2 "$@"
list_filter _list_filter_empty "$@"
}
_list_filter_empty() { [ "$1" ]; }
# list_unique() - Removes duplicate items from the named array ($1) and
# save them in the output array ($2, or $1 if not given).
# $1 - Input list
# $2 - Output list (optional)
list_unique() {
min_max_args 1 2 "$@"
local -A __found
list_filter _list_unique_check "$@"
}
_list_unique_check() {
local item=$1
if [ -z "${__found[$item]}" ]; then
__found[$item]=1
true
else
false
fi
}
# list_map() - Runs a command ($1) with each of the items in the named
# array ($2). The output of each command invocation is stored in the
# output array ($3, or $2 if not given)
# $1 - Filter command
# $2 - Input list
# $3 - Output list (optional)
list_map() {
min_max_args 2 3 "$@"
local __func=$1
local __list=$2
local __dest=${3:-$2}
local -a __in
eval "__in=( \"\${${__list}[@]}\" )"
local -a __out
for_each _list_map "${__in[@]}"
eval "$__dest=( \"\${__out[@]}\" )"
}
_list_map() {
local __item=$1
local __value
__value=$($__func "$__item")
list_append __out "$__value"
}
# list_copy_or_args - Copies arguments ($@) to output list ($1). If
# no arguments are given, copies the default list ($2) to the output list.
# $1 - name of output list
# $2 - name of default list
# $@ - optional arguments to copy to output list
list_copy_or_args() {
min_args 2 "$@"
local lcoa_dst=$1
local lcoa_src=$2
shift 2
local lcoa_var="@"
[ "$*" ] || lcoa_var="{lcoa_src[@]}"
eval "$lcoa_dst=( \"\$$lcoa_var\" )"
}
# list_from_func_or_args - Copies arguments ($@) to output list ($1). If
# no arguments are given, runs the given function ($2) to populate that list.
# $1 - name of output list
# $2 - name of function to provide defaults
# $@ - optional arguments to copy to output list
list_from_func_or_args() {
min_args 2 "$@"
local var=$1
local func=$2
shift 2
if [ "$*" ]; then
eval "$var=( \"\$@\" )"
else
eval "$var=( \$($func) )"
fi
}
Generated on Fri Jul 28 14:34:59 PDT 2017 by mcsh d14 v0.23.0.