#!/usr/bin/env bash
. "${0%/*}"/../lib/common.bashlib || exit 1 #C#
init
include atomf
usage <<-EOU
	Usage: ${0##*/} [format] <atom(s)...>

	Format <atom> based on [format], or return 9 elements separated by
	spaces if a single atom with no format specified.

	atom can be in dependency-format, or tree-style .ebuild format, e.g.
	 *  !!>=cat/name-1.2.3-r1:*/0=[use] ([use] will be discarded)
	 *  cat/name/name-1.2.3-r1.ebuild (.ebuild must be present)

	atom can be incomplete, but will return 1 if single elements are seen as
	invalid per the Package Manager Specification (PMS) -- not that this
	should be considered a full atom validator.

	Options:
	  -x, --expand        Ignore format and expand multiple atoms to elements
	  -s, --unset=STR     When expanding, show STR if unset (default: '?')

	  -M, --allow-missing If %c/%n or -%v is specified but atom is missing one
	                      of these components, do not exit with error.

	  -v, --versplit      Split a version string into elements instead
	                      (no characters are dropped for versions)

	      --confdir=PATH  Configuration dir to use instead of defaults
	                      (@confdir@ + ${XDG_CONFIG_HOME:-~/.config}/@package@)
	      --dumpconfig    Display config and exit (> ${0##*/}.conf)

	  -h, --help          Display usage information and exit
	      --version       Display version information and exit

	*Format*
	 0.  %! Blocker indicator (!, !!, or none)
	 1.  %o Version range operator (>=, >, etc... or none)
	 2.  %c Category (ending with / if set)
	 3.  %n Name
	 4.  %v Version (starting with - if set)
	 5.  %r Revision (as -rN, or none)
	 6.  %s Slot (as :0, or none)
	 7.  %u Subslot (as /0, or none)
	 8.  %b Binding operator (= or none)
	 -.  %% Literal %
	e.g. "%c%n%v%r" = category/name-1.0-r1

	 -.  %p Equivalent to %c%n (category/pn)
	 -.  %e Equivalent to %v%r (pvr)
	 -.  %f Equivalent to %c%n%v%r (category/pf)

	%R,%S,%U alternatively display %r,%s,%u without prefixes, and as 0 if unset.
	%C,%V similarly strip the / and -, and still empty if unset.

	If one of %c, %n, or %v (or equivalent) is requested, but is missing from the
	atom, will report error for that atom and later exit with return status 2
	unless --allow-missing.

	*Notes*
	If need to use this in a bash script extensively, it is recommended to source
	@datadir@/atomf.bashlib directly rather than call this.
	Its atoma() also allows for, e.g. \${atom[version]}, and atomset() for \${PV}.
EOU
optauto args "${@}" <<-EOO
	x|expand=bool:false
	s|unset=str:?
	M|allow-missing=bool:false
	v|versplit=bool:false
EOO
set -- "${args[@]}"; unset args

(( ${#} )) || die "no format/atom specified, see \`${0##*/} --help\`"

${O[allow-missing]} && miss=(-M) || miss=()

exiterrno=
if ${O[versplit]}; then
	while (( ${#} )); do
		if pversp ver "${1}"; then
			echo "${ver[*]}"
		else
			: "${exiterrno:=${?}}"
			err "'${1}' is an invalid version string"
		fi
		shift
	done
elif (( ${#} > 1 )) && ! ${O[expand]}; then
	format=${1}
	shift

	while (( ${#} )); do
		atomf "${miss[@]}" "${format}" "${1}" || {
			errno=${?}
			: "${exiterrno:=${errno}}"
			case ${errno} in
				3) die "'${format}' has unrecognized %format, see \`${0##*/} --help\`";;
				2) err "'${1}' is missing components";;
				*) err "'${1}' is an invalid atom";;
			esac
		}
		shift
	done
else
	while (( ${#} )); do
		if atomsp "${miss[@]}" atom "${1}"; then
			merge=
			for ((i=0; i<${#atom[@]}; i++)); do
				: "${atom[i]:=${O[unset]}}"
				merge+=${atom[i]:+ ${atom[i]}}
			done
			echo "${merge# }"
		else
			: "${exiterrno:=${?}}"
			err "'${1}' is an invalid atom"
		fi
		shift
	done
fi

exit "${exiterrno:-0}"

# vim: ts=4
