#!/bin/bash
#  list - Bash array support

set -e


######
# List helpers

in_list() {
	min_args 1 "$@"
	local thing=$1
	shift
	local found=false
	for i in "$@"; do
		[ "$i" != "$thing" ] || found=true
	done
	$found
}

list_insert() {
	min_args 1 "$@"
	local _list_insert_var=$1
	shift
	eval "$_list_insert_var=( \"\$@\" "\${$_list_insert_var\[@\]}" )"
}

list_append() {
	min_args 1 "$@"
	local _list_append_var=$1
	shift
	eval "$_list_append_var=( \"\${${_list_append_var}[@]}\" \"\$@\" )"
}

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() {
	has_args 1 "$@"
	local _list_var=$1
	shift
	local _value
	eval "_value=\"\${${_list_var}[0]}\""
	eval "$_list_var=( "\${${_list_var}[@]:1}" )"
	echo "$_value"
}


######
# Iteration

for_each() {
	min_args 1 "$@"
	local func=$1
	shift
	for i in "$@"; do
		$func "$i"
	done
}
run_for_each() {
	local func=$1
	shift
	for_each "run $func" "$@"
}

for_each_pair() {
	local func=$1
	$func "$2" "$3"
	shift 3
	for_each_pair "$func" "$@"
}


######
# Transformations

list_reverse() {
	has_args 1 "$@"
	local var=$1
	local -a out
	eval "for_each 'list_insert out' \"\${${var}[@]}\""
	eval "$var=( \"\${out[@]}\" )"
}

# list_quote - quotes all arguments
list_quote() {
	has_args 1 "$@"
	list_map arg_quote "$1"
}

# list_join - Joins arguments using the given character
#  $1 - character to use for joining arguments
#  $@ - strings to be joined by $1
list_join() {
	local IFS=$1
	shift
	echo "$*"
}

list_filter() {
	has_args 2 "$@"
	local __func=$1
	local __list=$2
	local -a __out
	eval "for_each _list_filter \"\${${__list}[@]}\""
	eval "$__list=( \"\${__out[@]}\" )"
}
_list_filter() {
	local __item=$1
	if $__func "$__item"; then
		list_append __out "$__item"
	fi
}

list_filter_empty() { has_args 1 "$@"; list_filter _list_filter_empty $1; }
_list_filter_empty() { [ "$1" ]; }

list_unique() {
	has_args 1 "$@"
	local __list=$1
	local -A __found
	list_filter _list_unique_check $__list
}
_list_unique_check() {
	local item=$1
	if [ -z "${__found[$item]}" ]; then
		__found[$item]=1
		true
	else
		false
	fi
}

list_map() {
	has_args 2 "$@"
	local __func=$1
	local __list=$2
	local -a __out
	eval "for_each _list_map \"\${${__list}[@]}\""
	eval "$__list=( \"\${__out[@]}\" )"
}
_list_map() {
	local __item=$1
	local __value
	__value=$($__func "$__item")
	list_append __out "$__value"
}

# list_copy_or_args - Copies list or args to another list.
# $1 - name of output list
# $2 - name of default list to copy to $1 (if $# == 2)
# $3--$# - optional arguments to copy to $1
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() {
	min_args 2 "$@"
	local var=$1
	local func=$2
	shift 2
	if [ "$*" ]; then
		eval "$var=( \"\$@\" )"
	else
		eval "$var=( \$($func) )"
	fi
}

View the Script Reference Index


Generated on Tue Apr 25 21:20:11 PDT 2017 by mcsh i7 v0.18.0.