/*-------------------------------------------------------------------------------
  regexunab.ado: a replacement for Stata's -unab-, but dealing with regular expressions

    Copyright (C) 2016  Daniel Bela (daniel.bela@lifbi.de)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

-------------------------------------------------------------------------------*/
*! version 1.0 08 July - initial release
*! regexunab.ado: a replacement for Stata's -unab-, but dealing with regular expressions
*! Daniel Bela (daniel.bela@lifbi.de), Leibniz-Institute for Educational Trajectories e.V. (LIfBi), Germany
program define regexunab , rclass
	// Stata version information: use unicode functions for string comparisons in Stata 14 and younger
	if (`c(stata_version)'>=14) {
		local regexm_fct ustrregexm
		version 14
	}
	else {
		local regexm_fct regexm
		version 12
	}
	// declare macros
	local targetmacro
	local expression
	local expressions
	local rest
	local colon
	local var
	local resultlist
	local minimum
	local maximum
	local varcount
	local plural
	// parse arguments
	gettoken targetmacro 0 : 0 , parse(":")
	gettoken colon 0 : 0 , parse(":")
	if (`"`colon'"'!=":") error 198
	syntax anything(everything equalok name=expressions id="regular expression(s)") [, MINimum(integer 1) MAXimum(integer 32767) NAME(string)]
	// resolve regular expression
	foreach expression of local expressions {
		foreach var of varlist _all {
			if (`regexm_fct'(`"`var'"',`"`macval(expression)'"')) local resultlist : list resultlist | var
		}
	}
	// return result
	c_local `targetmacro' `"`resultlist'"'
	local varcount : word count `resultlist'
	if (`varcount'>=`minimum' & `varcount'<=`maximum') exit 0
	// error handling (mostly equivalent to unab.ado)
	if (missing(`"`name'"')) {
		if (!missing("`resultlist'")) {
			display as error in smcl "`resultlist':"
		}
		error cond(`varcount'<`minimum', 102, 103)
	}
	if (`varcount'<`minimum') display as error in smcl `"`name':  too few variables specified"'
	else display as error in smcl `"`name':  too many variables specified"'
	display as error in smcl _column(`=length(`"`name'"')+4') _continue
	if (`minimum'==`maximum') {
		if (`maximum' > 1) local plural s
		display as error in smcl "`minimum' variable`plural' required"
	}
	else if (`minimum'<=0) {
		if (`maximum'==1) display as error in smcl "0 or 1 variables required"
		else display as error in smcl "`maximum' or fewer variables required"
	}
	else if (`maximum'>=32767) display as error in smcl "`minimum' or more variables required"
	else display as error in smcl "`minimum' - `maximum' variables required"
	exit cond(`varcount'<`minimum', 102, 103)
end
// EOF