iekdensity #206: specify error codes

iekdensity #206: specify error codes

And refine messages displayed and formatting

*! version DEVELOP 16OCT2019 Matteo Ruzzante mruzzante@worldbank.org

	cap prog drop    iekdensity
		prog define  iekdensity

		syntax 		 varname(numeric) [if] [in] [aw fw iw] , 	/// Specify outcome variable (only fweights, aweights, and iweights are allowed in original [kdensity] command)
																///
			TREATvar(varname numeric)							/// Specify treatment variable
																///
		   [													///
		    color(string)										/// Specify string of colors
																///
		    stat(string)										/// Add lines with (one) statistic
		    statstyle(string)									/// Lines style. Default is dashed pattern.
																///
		    effect												/// Add note with treatment effect (beta, SD, and p-value)
		    control(numlist int max=1)							/// Specify value of control variable -- for comparisons
			effectformat(string)								/// Format of treatment treatment effect. Default is "%9.3f".
		    ABSorb(varname numeric)								/// Strata variable
		    REGressionoptions(string)							/// Allows any normal options for linear regressions
																///
		    KDENSITYoptions(string)								/// Allows kernel options (namely [kernel], [bwidth], [n], and all the [cline_options]) for univariate kernel density estimation
		    GRaphoptions(string)								/// Allows any normal options for twoway graphs
		   ]

/*******************************************************************************
	Prepare settings
*******************************************************************************/

		qui {

			// Set minimum version for this command
			version 11

			// Preserve current dataset
			preserve

			// Remove observations excluded by if and in conditions
			marksample touse, novarlist
			keep if   `touse'

			**************************************************
			* Check if treatment variable is binary or factor
			**************************************************

			// Remove observations with a missing value in treatvar()
			drop if    missing(`treatvar')

			// Create a local of all codes in treatvar()
			levelsof  `treatvar'			, local(treatvar_levels)

			// Saving the name of the value label of the treatvar()
			local 	   treatvar_value_label : value label `treatvar'

			// Counting how many levels there are in treatvar()
			local 	   treatvar_num_groups  : word  count `treatvar_levels'

/*******************************************************************************
	Prepare optional options
*******************************************************************************/
/*------------------------------------------------------------------------------
	Color options
------------------------------------------------------------------------------*/
{
			// If no [color] is specified, keep standard Stata color palette.
			// Otherwise, set user-specified colors
			if	missing("`color'") {

				set scheme s2color

				local 	  treatvar_count = 0

				foreach   treatvar_num of local treatvar_levels {

					if 	 `treatvar_count' == 0 local color_`treatvar_num' "navy"
					if 	 `treatvar_count' == 1 local color_`treatvar_num' "maroon"
					if 	 `treatvar_count' == 2 local color_`treatvar_num' "forest_green"
					if 	 `treatvar_count' == 3 local color_`treatvar_num' "dkorange"
					if   `treatvar_count' == 4 local color_`treatvar_num' "teal"
					if	 `treatvar_count' == 5 local color_`treatvar_num' "cranberry"

					local treatvar_count = `treatvar_count' + 1
				}
			}

			if !missing("`color'") {

				// Check that the number of colors specified matches
				local color_num_groups : word count `color'

				// If it is smaller or larger, we throw an error
				if   `color_num_groups' > `treatvar_num_groups' {

					  noi di as error "{phang}The number of colors you specified in {bf:color()} is higher than the number of categories in the treatment variable {bf:treatvar()}.{p_end}"
					  noi di as error "{phang}Please define one color for each category.{p_end}"
					  noi di 		  ""
								error 198
				}

				if   `color_num_groups' < `treatvar_num_groups' {

					  noi di as error "{phang}The number of colors you specified in {bf:color()}  is smaller than the number of categories in the treatment variable {bf:treatvar()}.{p_end}"
					  noi di as error "{phang}Please define one color for each category.{p_end}"
					  noi di 		  ""
							    error 198
				}

				else {

					// Put colors in correct local for the graph
					local colorNum = 1

					foreach   treatvarNum of local treatvar_levels {

						local treatvar_`treatvarNum' 		 = word("`treatvar_levels'" , `colorNum')
						di "`treatvar_`treatvarNum''"

						local color_`treatvar_`treatvarNum'' = word("`color'"		    , `colorNum')

						di "`color_`treatvar_`treatvarNum''''"

						local colorNum = `colorNum' + 1
					}
				}
			}
}
/*------------------------------------------------------------------------------
	Stat options
------------------------------------------------------------------------------*/
{
			*******************************************
			* Test that option was correctly specified
			*******************************************

			// If no [stat] is specified, option [statstyle] also shouldn't be
			if missing("`stat'") & !missing("`statstyle'") {

				noi di as error "{phang}{bf:statstyle()} requires the option {bf:stat()} to be specified..{p_end}"
				noi di as error "{phang}If you want to use {bf:statstyle()}, you need to include the option {bf:stat()} too.{p_end}"
				noi di 		    ""
						  error 198

			}
			// If no [stat] is specified, do not attach any vertical line in the plot
			else if  missing("`stat'") {

				local STATxline ""

			}
			// If [stat] option is specified, add option to graph vertical lines
			else if !missing("`stat'") {

				local statIfList 	 ""
				local statBoldString ""
				local statsList		 mean min max p1 p5 p10 p25 p50 p75 p90 p95 p99

				foreach possibleStat of local statsList 	{

					local statIfList	 `" `statIfList' "`stat'" != "`possibleStat'" & "'
					local statBoldString `"`statBoldString' {bf:`possibleStat'},"'

				}

				// Remove final comma
				local statBoldString = substr("`statBoldString'", 1, length("`statBoldString'") - 1)

				di `"`statIfList'"'

				// Check that the stat is among possible statistics
				if `statIfList' "ok" == "ok" {

					noi di as error "{phang}The {bf:stat()} you selected cannot be shown in the graph.{p_end}"
					noi di as error "{phang}The available statistics are:`statBoldString'.{p_end}"
					noi di 		    ""
							  error 198
				}

				else {

					// Summarize variable and store locals with defined value
					foreach    varNum of local treatvar_levels {

						sum   `varlist' if `treatvar' == `varNum' , d
						local `varlist'_`varNum' = `r(`stat')'
					}
				}

				if missing("`statstyle'") {

					// In the absence of [statstyle], we only use the 'dash' patttern
					local 	  STATxline ""

					foreach   varNum of local treatvar_levels {

						local STATxline `" `STATxline' xline( ``varlist'_`varNum'' , lcolor(`color_`varNum''%80) lpattern(dash) ) "'
					}
				}

				di "`STATxline'"

				else if !missing("`statstyle'") {

					// Check that [statstyle] is correctly specified
					set graphics off //we set graphics off as the option [nograph] is conflicting with [xline]
					cap kdensity `varlist' , xline( ``varlist'_0' , `statstyle' )

					if _rc != 0 {

						set graphics on

						// If it's not, replot the kernel density, which will automaticallty show the underlying error
						kdensity `varlist' , xline( ``varlist'_0' , `statstyle' )
					}
					else {

						// Store local with [xline] option to be graphed
						local 	  STATxline ""

						foreach   varNum of local treatvar_levels {

							local STATxline `" `STATxline' xline( ``varlist'_`varNum'' , lcolor(`color_`varNum''%80) `statstyle' ) "'
						}
					}

					set graphics on
				}
			}
}
/*------------------------------------------------------------------------------
	Control options
------------------------------------------------------------------------------*/
{
			// If control() is used, test that the value specified exists in the [treatvar]
			local control_correct : list control in treatvar_levels

			if   `control_correct' == 0 {

				  noi di as error "{phang}The code listed in {bf:control(`control')} is not used in {bf:tretavar(`treatvar')}. See tabulation of {it:`treatvar'} below:{p_end}"
				  noi tab  `treatvar', nol
				  noi di 		  ""
							error 197
			}
}
/*------------------------------------------------------------------------------
	Treatment effect options
------------------------------------------------------------------------------*/
{
			// If [effectnote], [absorb], or [regressoptions] option is specified, check that [effect] was specified
			if "`effect'" == "" {

				foreach effectOption in effectnote absorb regressoptions {

					if "``effectOption''" != "" {

						noi di as error "{phang}{bf:`effectOption'()} requires the option {bf:effect} to be specified.{p_end}""
						noi di as error "{phang}If you want to use {bf:`effectOption'()}, you need to include the option {bf:effect} too.{p_end}"
						noi di 		    ""
								  error 198
					}
				}

				// If no [effect] is specified, do not attach any note with the effect
				local EFFECTnote ""
			}

			// If [effect] option is specified, add option to include note
			if "`effect'" != "" {

				// If format is specified, check that it is possible
				if "`effectformat'" != "" {

					// ------------------------------------------------
					// The procedure below is taken from 'iebaltab.ado'

					** Creating a numeric mock variable that we attempt to apply the format
					*  to. This allows us to piggy back on Stata's internal testing to be
					*  sure that the format specified is at least one of the valid numeric
					*  formats in Stata
						tempvar  formattest
						gen 	`formattest' = 1
					cap	format  `formattest' `effectformat'

					if _rc == 120 {

						noi di as error "{phang}The format specified in effectformat(`effectformat') is not a valid Stata format. See {help format} for a list of valid Stata formats. This command only accept the f, fc, g, gc and e format.{p_end}"
						noi di 		    ""
							      error 120
					}
					else if _rc != 0 {

						noi di as error "{phang}Something unexpected happened related to the option format(`format'). Make sure that the format you specified is a valid format. See {help format} for a list of valid Stata formats. If this problem remains, please report this error to mruzzante@worldbank.org.{p_end}"
						noi di 		    ""
							      error _rc
					}
					else {
						** We know here that the format is one of the numeric formats that Stata allows

						local formatAllowed 0
						local charLast  = substr("`effectformat'", -1, .)
						local char2Last = substr("`effectformat'", -2, .)

						if  "`charLast'" == "f" | "`charLast'" == "e" {
							local formatAllowed 1
						}
						else if "`charLast'" == "g"  {
							if "`char2Last'" == "tg" {
								*format tg not allowed. all other valid formats ending on g are allowed
								local formatAllowed 0
							}
							else {

								*Formats that end in g that is not tg can only be g which is allowed.
								local formatAllowed 1
							}
						}
						else if  "`charLast'" == "c" {
							if "`char2Last'" != "gc" & "`char2Last'" != "fc" {
								*format ends on c but is neither fc nor gc
								local formatAllowed 0
							}
							else {

								*Formats that end in c that are either fc or gc are allowed.
								local formatAllowed 1
							}
						}
						else {
							*format is neither f, fc, g, gc nor e
							local formatAllowed 0
						}
						if `formatAllowed' == 0 {
							di as error "{phang}The format specified in {bf:effectformat(`effectformat')} is not allowed. Only format f, fc, g, gc and e are allowed. See {help format} for details on Stata formats.{p_end}"
							noi di 		""
								  error 120
						}
						*If format passed all tests, store it in the local used for display formats
						local TEformat  "`effectformat'"
					}

					// ------------------------------------------------
				}

				if "`effectformat'" == "" {

					// Otherwise, we will use "%9.3f"
					local TEformat  "%9.3f"
				}

				// Standard case with binary treatment
				// -----------------------------------
				if `treatvar_num_groups' == 2 {

					if "`treatvar_levels'" == "0 1" & missing("`control'") {

						// Estimate treatment effect
						if "`absorb'" == "" {
							reg  `varlist' `treatvar' [`weight'`exp'] , `regressionoptions'
						}

						// If there are strata, estimate treatment effect controlling for strata
						if "`absorb'" != "" {

							areg `varlist' `treatvar' [`weight'`exp'] , `regressionoptions' abs(`absorb')
						}

						// Store estimated coefficient, standard error, p-value, and number of observations
						mat   results = r(table)
						local beta	  = string( _b[`treatvar'] , "`TEformat'")
						local se	  = string(_se[`treatvar'] , "`TEformat'")
						local pvalue  = results[4, 1]

						local obs	  = e(N)

						// Add level of statistical significance
						local stars     ""

						foreach signLevel in 0.1 0.05 0.01 {

							if `pvalue' < `signLevel' local stars "`stars'*"
						}

						local EFFECTnote " note(Treatment effect = `beta' (`se')`stars'. N = `obs'.) "
					}

					// If the values are not 0/1 and no [control] is specified, signal this to the user
					else if "`treatvar_levels'" != "0 1" {

						if missing("`control'") {

							noi di as error "{phang}The treatment variable in {bf:treatvar()} is not a 0/1 dummy variable. See tabulation of {it:`treatvar'} below.{p_end}""
							noi di as error "{phang}If you want to compute the treatment effect, you need to indicate which value is referred to the control group using the option {bf:control()}.{p_end}"
							noi tab  `treatvar', nolab
							noi di 		    ""
									  error 198
						}

						else if !missing("`control") {

							// When the binary variable is not 0/1, recode variable to be 0/1, depending on the control specified
							tempvar  treatmentAux
							gen	    `treatmentAux' = 0 if `treatvar' == `control' & !mi(`treatvar')
							replace `treatmentAux' = 1 if `treatvar' != `control' & !mi(`treatvar')

							if "`absorb'" == "" {
								reg  `varlist' `treatmentAux' [`weight'`exp'] , `regressionoptions'
							}

							if "`absorb'" != "" {

								areg `varlist' `treatmentAux' [`weight'`exp'] , `regressionoptions' abs(`absorb')
							}

							mat   results = r(table)
							local beta	  = string( _b[`treatmentAux'] , "`TEformat'")
							local se	  = string(_se[`treatmentAux'] , "`TEformat'")
							local pvalue  = results[4, 1]

							local obs	  = e(N)

							local stars     ""

							foreach signLevel in 0.1 0.05 0.01 {

								if `pvalue' < `signLevel' local stars "`stars'*"
							}

							local EFFECTnote " note(Treatment effect = `beta' (`se')`stars'. N = `obs'.) "
						}
					}
				}

				// Case with factor variables
				// --------------------------
				if `treatvar_num_groups'  > 2 {

					di "ok"

					// In this case, the control value must be specified
					if  missing("`control'") {

						noi di as error "{phang}The treatment variable in {bf:treatvar()} is a factor variable. See tabulation of {it:`treatvar'} below.{p_end}"
						noi di as error "{phang}If you want to compute the treatment effect, you need to indicate which value is referred to the control group using the option {bf:control()}.{p_end}"
						noi tab  `treatvar', nolab
						noi di 		    ""
								  error 198
					}

					if !missing("`control'") {

						// Local with values other than [control]
						levelsof `treatvar' if `treatvar' != `control', local(treatvar_comparison)

						// Generate new treatment factor variable
						tempvar  treatmentAux
						gen 	`treatmentAux' = 0 if `treatvar' == `control'	// equal to 0 for the control group

						local    treatvarCount = 0
						foreach  treatvarNum of local treatvar_comparison {

							local    treatvarCount = `treatvarCount' + 1		// and going from 1 to the total number of treatment arms for the rest
							replace `treatmentAux' = `treatvarCount' if `treatvar' == `treatvarNum'
						}

						// Run regression with control as base group
						if "`absorb'" == "" {
							reg  `varlist' ib0.`treatmentAux' [`weight'`exp'] , `regressionoptions'
						}

						if "`absorb'" != "" {

							areg `varlist' ib0.`treatmentAux' [`weight'`exp'] , `regressionoptions' abs(`absorb')
						}

						mat   results = r(table)

						// Store estimates for each treatment
						forv  estimateNum = 1/`treatvarCount' {

							local resultsMatCol = `estimateNum' + 1 //the first column of the matrix is left for the base group, i.e., the control

							local   beta`estimateNum' = string(results[1, `resultsMatCol'], "`TEformat'")
							local     se`estimateNum' = string(results[2, `resultsMatCol'], "`TEformat'")
							local pvalue`estimateNum' = 	   results[4, `resultsMatCol']

							local  stars`estimateNum'   ""

							foreach signLevel in 0.1 0.05 0.01 {

								if `pvalue`estimateNum'' < `signLevel' local stars`estimateNum' "`stars`estimateNum''*"
							}
						}

						local obs = e(N)

						// Stack each effect in a single note
						forv  estimateNum = 1/`treatvarCount' {

							if	`estimateNum' == 1 {
								local EFFECTnote 				   "  [`treatvar' == `estimateNum'] `beta`estimateNum'' (`se`estimateNum'')`stars`estimateNum'';"
							}
							else {
								local EFFECTnote `" "`EFFECTnote'" "  [`treatvar' == `estimateNum'] `beta`estimateNum'' (`se`estimateNum'')`stars`estimateNum'';" "'
							}
						}

						local EFFECTnote `" note("{bf:Treatment effects} =" `EFFECTnote' "  N = `obs'.") "'
					}
				}
			}
}
/*******************************************************************************
	Prepare figure inputs
*******************************************************************************/
{
			// If the treatment variable has no defined label, we leave the value in the legend
			if  missing("`treatvar_value_label'") {

				foreach treatvarNum of local treatvar_levels {

					local label_`treatvarNum' "`treatvarNum'"
				}
			}

			// If the treatmnet variable has labels, we will display it in the legend
			if !missing("`treatvar_value_label'") {

				foreach treatvarNum of local treatvar_levels {

					local label_`treatvarNum' : label (`treatvar') `treatvarNum'
				}
			}

			// Prepare [kdensity] code and legend argument
			local     treatCount = 0
			local kdensityString  "tw"
			local 	legendString `"legend(order(0 "Treatment assignment:" "'

			foreach treatvarNum of local treatvar_levels {

				local treatCount	  = `treatCount' + 1

				local kdensityString `" `kdensityString' (kdensity `varlist' if `treatvar' == `treatvarNum' [`weight'`exp'] , `kdensityoptions' color(`color_`treatvarNum'') ) "'

				local   legendString `"   `legendString' `treatCount' "`label_`treatvarNum''" "'
			}

			// Add final parenthesis and number of rows (this can be changed by the user through graphoptions()
			if   `treatvar_num_groups' == 2 		 local rowString "row(1)"

			local legendString         `" `legendString') `rowString' )"'

			// Record outcome variable label to be shown as x-axis title
			local varLab 				: var label `varlist'
		}
}

/*******************************************************************************
	Plot the figure!
*******************************************************************************/

		`kdensityString' 		///
		 , 						///
		`STATxline' 			///
		`EFFECTnote' 			///
		`legendString'			///
		 ytitle(Density) 		///
		 xtitle(`varLab')		///
		`graphoptions'

		// Restore original dataset
		restore

	// End
	end

	// And now, you shall plot the distributions! ;)

*! version DEVELOP 16OCT2019 Matteo Ruzzante mruzzante@worldbank.org

	cap prog drop    iekdensity
		prog define  iekdensity

		syntax 		 varname(numeric) [if] [in] [aw fw iw] , 	/// Specify outcome variable (only fweights, aweights, and iweights are allowed in original [kdensity] command)
																///
			TREATvar(varname numeric)							/// Specify treatment variable
																///
		   [													///
		    color(string)										/// Specify string of colors
																///
		    stat(string)										/// Add lines with (one) statistic
		    statstyle(string)									/// Lines style. Default is dashed pattern.
																///
		    effect												/// Add note with treatment effect (beta, SD, and p-value)
		    control(numlist int max=1)							/// Specify value of control variable -- for comparisons
			effectformat(string)								/// Format of treatment treatment effect. Default is "%9.3f".
		    ABSorb(varname numeric)								/// Strata variable
		    REGressionoptions(string)							/// Allows any normal options for linear regressions
																///
		    KDENSITYoptions(string)								/// Allows kernel options (namely [kernel], [bwidth], [n], and all the [cline_options]) for univariate kernel density estimation
		    GRaphoptions(string)								/// Allows any normal options for twoway graphs
		   ]

/*******************************************************************************
	Prepare settings
*******************************************************************************/

		qui {

			// Set minimum version for this command
			version 11

			// Preserve current dataset
			preserve

			// Remove observations excluded by if and in conditions
			marksample touse, novarlist
			keep if   `touse'

			**************************************************
			* Check if treatment variable is binary or factor
			**************************************************

			// Remove observations with a missing value in treatvar()
			drop if    missing(`treatvar')

			// Create a local of all codes in treatvar()
			levelsof  `treatvar'			, local(treatvar_levels)

			// Saving the name of the value label of the treatvar()
			local 	   treatvar_value_label : value label `treatvar'

			// Counting how many levels there are in treatvar()
			local 	   treatvar_num_groups  : word  count `treatvar_levels'

/*******************************************************************************
	Prepare optional options
*******************************************************************************/
/*------------------------------------------------------------------------------
	Color options
------------------------------------------------------------------------------*/
{
			// If no [color] is specified, keep standard Stata color palette.
			// Otherwise, set user-specified colors
			if	missing("`color'") {

				set scheme s2color

				local 	  treatvar_count = 0

				foreach   treatvar_num of local treatvar_levels {

					if 	 `treatvar_count' == 0 local color_`treatvar_num' "navy"
					if 	 `treatvar_count' == 1 local color_`treatvar_num' "maroon"
					if 	 `treatvar_count' == 2 local color_`treatvar_num' "forest_green"
					if 	 `treatvar_count' == 3 local color_`treatvar_num' "dkorange"
					if   `treatvar_count' == 4 local color_`treatvar_num' "teal"
					if	 `treatvar_count' == 5 local color_`treatvar_num' "cranberry"

					local treatvar_count = `treatvar_count' + 1
				}
			}

			if !missing("`color'") {

				// Check that the number of colors specified matches
				local color_num_groups : word count `color'

				// If it is smaller or larger, we throw an error
				if   `color_num_groups' > `treatvar_num_groups' {

					  noi di as error "{phang}The number of colors you specified in {bf:color()} is higher than the number of categories in the treatment variable {bf:treatvar()}."
					  noi di as error "{phang}Please define one color for each category."
								error
				}

				if   `color_num_groups' < `treatvar_num_groups' {

					noi di as error "{phang}The number of colors you specified in {bf:color()}  is smaller than the number of categories in the treatment variable {bf:treatvar()}."
					noi di as error "{phang}Please define one color for each category."
							  error
				}

				else {

					// Put colors in correct local for the graph
					local colorNum = 1

					foreach   treatvarNum of local treatvar_levels {

						local treatvar_`treatvarNum' 		 = word("`treatvar_levels'" , `colorNum')
						di "`treatvar_`treatvarNum''"

						local color_`treatvar_`treatvarNum'' = word("`color'"		    , `colorNum')

						di "`color_`treatvar_`treatvarNum''''"

						local colorNum = `colorNum' + 1
					}
				}
			}
}
/*------------------------------------------------------------------------------
	Stat options
------------------------------------------------------------------------------*/
{
			*******************************************
			* Test that option was correctly specified
			*******************************************

			// If no [stat] is specified, option [statstyle] also shouldn't be
			if missing("`stat'") & !missing("`statstyle'") {

				noi di as error "{phang}{bf:statstyle()} requires the option {bf:stat()} to be specified."
				noi di as error "{phang}If you want to use {bf:statstyle()}, you need to include the option {bf:stat()} too."
						  error

			}
			// If no [stat] is specified, do not attach any vertical line in the plot
			else if  missing("`stat'") {

				local STATxline ""

			}
			// If [stat] option is specified, add option to graph vertical lines
			else if !missing("`stat'") {

				local statIfList 	 ""
				local statBoldString ""
				local statsList		 mean min max p1 p5 p10 p25 p50 p75 p90 p95 p99

				foreach possibleStat of local statsList 	{

					local statIfList	 `" `statIfList' "`stat'" != "`possibleStat'" & "'
					local statBoldString `"`statBoldString' {bf:`possibleStat'},"'

				}

				// Remove final comma
				local statBoldString = substr("`statBoldString'", 1, length("`statBoldString'") - 1)

				di `"`statIfList'"'

				// Check that the stat is among possible statistics
				if `statIfList' "ok" == "ok" {

					noi di as error "{phang}The {bf:stat()} you selected cannot be shown in the graph."
					noi di as error "{phang}The available statistics are:`statBoldString'."
							  error
				}

				else {

					// Summarize variable and store locals with defined value
					foreach    varNum of local treatvar_levels {

						sum   `varlist' if `treatvar' == `varNum' , d
						local `varlist'_`varNum' = `r(`stat')'
					}
				}

				if missing("`statstyle'") {

					// In the absence of [statstyle], we only use the 'dash' patttern
					local 	  STATxline ""

					foreach   varNum of local treatvar_levels {

						local STATxline `" `STATxline' xline( ``varlist'_`varNum'' , lcolor(`color_`varNum''%80) lpattern(dash) ) "'
					}
				}

				di "`STATxline'"

				else if !missing("`statstyle'") {

					// Check that [statstyle] is correctly specified
					set graphics off //we set graphics off as the option [nograph] is conflicting with [xline]
					cap kdensity `varlist' , xline( ``varlist'_0' , `statstyle' )

					if _rc != 0 {

						set graphics on

						// If it's not, replot the kernel density, which will automaticallty show the underlying error
						kdensity `varlist' , xline( ``varlist'_0' , `statstyle' )
					}
					else {

						// Store local with [xline] option to be graphed
						local 	  STATxline ""

						foreach   varNum of local treatvar_levels {

							local STATxline `" `STATxline' xline( ``varlist'_`varNum'' , lcolor(`color_`varNum''%80) `statstyle' ) "'
						}
					}

					set graphics on
				}
			}
}
/*------------------------------------------------------------------------------
	Control options
------------------------------------------------------------------------------*/
{
			// If control() is used, test that the value specified exists in the [treatvar]
			local control_correct : list control in treatvar_levels

			if   `control_correct' == 0 {

				  noi di as error "{phang}The code listed in {bf:control(`control')} is not used in {bf:tretavar(`treatvar')}. See tabulation of `treatvar' below:"
				  noi tab `testvar', nol
				  error 197
			}
}
/*------------------------------------------------------------------------------
	Treatment effect options
------------------------------------------------------------------------------*/
{
			// If [effectnote], [absorb], or [regressoptions] option is specified, check that [effect] was specified
			if "`effect'" == "" {

				foreach effectOption in effectnote absorb regressoptions {

					if "``effectOption''" != "" {

						noi di as error "{phang}{bf:`effectOption'()} requires the option {bf:effect} to be specified."
						noi di as error "{phang}If you want to use {bf:`effectOption'()}, you need to include the option {bf:effect} too."
								  error
					}
				}

				// If no [effect] is specified, do not attach any note with the effect
				local EFFECTnote ""
			}

			// If [effect] option is specified, add option to include note
			if "`effect'" != "" {

				// If format is specified, check that it is possible
				if "`effectformat'" != "" {

					// ------------------------------------------------
					// The procedure below is taken from 'iebaltab.ado'

					** Creating a numeric mock variable that we attempt to apply the format
					*  to. This allows us to piggy back on Stata's internal testing to be
					*  sure that the format specified is at least one of the valid numeric
					*  formats in Stata
						tempvar  formattest
						gen 	`formattest' = 1
					cap	format  `formattest' `effectformat'

					if _rc == 120 {

						di as error "{phang}The format specified in effectformat(`effectformat') is not a valid Stata format. See {help format} for a list of valid Stata formats. This command only accept the f, fc, g, gc and e format.{p_end}"
						error 120
					}
					else if _rc != 0 {

						di as error "{phang}Something unexpected happened related to the option format(`format'). Make sure that the format you specified is a valid format. See {help format} for a list of valid Stata formats. If this problem remains, please report this error to mruzzante@worldbank.org.{p_end}"
						error _rc
					}
					else {
						** We know here that the format is one of the numeric formats that Stata allows

						local formatAllowed 0
						local charLast  = substr("`effectformat'", -1, .)
						local char2Last = substr("`effectformat'", -2, .)

						if  "`charLast'" == "f" | "`charLast'" == "e" {
							local formatAllowed 1
						}
						else if "`charLast'" == "g"  {
							if "`char2Last'" == "tg" {
								*format tg not allowed. all other valid formats ending on g are allowed
								local formatAllowed 0
							}
							else {

								*Formats that end in g that is not tg can only be g which is allowed.
								local formatAllowed 1
							}
						}
						else if  "`charLast'" == "c" {
							if "`char2Last'" != "gc" & "`char2Last'" != "fc" {
								*format ends on c but is neither fc nor gc
								local formatAllowed 0
							}
							else {

								*Formats that end in c that are either fc or gc are allowed.
								local formatAllowed 1
							}
						}
						else {
							*format is neither f, fc, g, gc nor e
							local formatAllowed 0
						}
						if `formatAllowed' == 0 {
							di as error "{phang}The format specified in effectformat(`effectformat') is not allowed. Only format f, fc, g, gc and e are allowed. See {help format} for details on Stata formats.{p_end}"
							error 120
						}
						*If format passed all tests, store it in the local used for display formats
						local TEformat  "`effectformat'"
					}

					// ------------------------------------------------
				}

				if "`effectformat'" == "" {

					// Otherwise, we will use "%9.3f"
					local TEformat  "%9.3f"
				}

				// Standard case with binary treatment
				// -----------------------------------
				if `treatvar_num_groups' == 2 {

					if "`treatvar_levels'" == "0 1" & missing("`control'") {

						// Estimate treatment effect
						if "`absorb'" == "" {
							reg  `varlist' `treatvar' [`weight'`exp'] , `regressionoptions'
						}

						// If there are strata, estimate treatment effect controlling for strata
						if "`absorb'" != "" {

							areg `varlist' `treatvar' [`weight'`exp'] , `regressionoptions' abs(`absorb')
						}

						// Store estimated coefficient, standard error, p-value, and number of observations
						mat   results = r(table)
						local beta	  = string( _b[`treatvar'] , "`TEformat'")
						local se	  = string(_se[`treatvar'] , "`TEformat'")
						local pvalue  = results[4, 1]

						local obs	  = e(N)

						// Add level of statistical significance
						local stars     ""

						foreach signLevel in 0.1 0.05 0.01 {

							if `pvalue' < `signLevel' local stars "`stars'*"
						}

						local EFFECTnote " note(Treatment effect = `beta' (`se')`stars'. N = `obs'.) "
					}

					// If the values are not 0/1 and no [control] is specified, signal this to the user
					else if "`treatvar_levels'" != "0 1" {

						if missing("`control'") {

							noi di as error "{phang}The treatment variable in {bf:treatvar()} is not a 0/1 dummy variable."
							noi di as error "{phang}If you want to compute the treatment effect, you need to indicate which value is referred to the control group using the option {bf:control()}."
									  error
						}

						else if !missing("`control") {

							// When the binary variable is not 0/1, recode variable to be 0/1, depending on the control specified
							tempvar  treatmentAux
							gen	    `treatmentAux' = 0 if `treatvar' == `control' & !mi(`treatvar')
							replace `treatmentAux' = 1 if `treatvar' != `control' & !mi(`treatvar')

							if "`absorb'" == "" {
								reg  `varlist' `treatmentAux' [`weight'`exp'] , `regressionoptions'
							}

							if "`absorb'" != "" {

								areg `varlist' `treatmentAux' [`weight'`exp'] , `regressionoptions' abs(`absorb')
							}

							mat   results = r(table)
							local beta	  = string( _b[`treatmentAux'] , "`TEformat'")
							local se	  = string(_se[`treatmentAux'] , "`TEformat'")
							local pvalue  = results[4, 1]

							local obs	  = e(N)

							local stars     ""

							foreach signLevel in 0.1 0.05 0.01 {

								if `pvalue' < `signLevel' local stars "`stars'*"
							}

							local EFFECTnote " note(Treatment effect = `beta' (`se')`stars'. N = `obs'.) "
						}
					}
				}

				// Case with factor variables
				// --------------------------
				if `treatvar_num_groups'  > 2 {

					di "ok"

					// In this case, the control value must be specified
					if  missing("`control'") {

						noi di as error "{phang}The treatment variable in {bf:treatvar()} is a factor variable."
						noi di as error "{phang}If you want to compute the treatment effect, you need to indicate which value is referred to the control group using the option {bf:control()}."
								  error
					}

					if !missing("`control'") {

						// Local with values other than [control]
						levelsof `treatvar' if `treatvar' != `control', local(treatvar_comparison)

						// Generate new treatment factor variable
						tempvar  treatmentAux
						gen 	`treatmentAux' = 0 if `treatvar' == `control'	// equal to 0 for the control group

						local    treatvarCount = 0
						foreach  treatvarNum of local treatvar_comparison {

							local    treatvarCount = `treatvarCount' + 1		// and going from 1 to the total number of treatment arms for the rest
							replace `treatmentAux' = `treatvarCount' if `treatvar' == `treatvarNum'
						}

						if "`absorb'" == "" {
							reg  `varlist' ib0.`treatmentAux' [`weight'`exp'] , `regressionoptions'
						}

						if "`absorb'" != "" {

							areg `varlist' ib0.`treatmentAux' [`weight'`exp'] , `regressionoptions' abs(`absorb')
						}

						mat   results = r(table)

						forv  estimateNum = 1/`treatvarCount' {

							local resultsMatCol = `estimateNum' + 1 //the first column of the matrix is left for the base group, i.e., the control

							local   beta`estimateNum' = string(results[1, `resultsMatCol'], "`TEformat'")
							local     se`estimateNum' = string(results[2, `resultsMatCol'], "`TEformat'")
							local pvalue`estimateNum' = 	   results[4, `resultsMatCol']

							local  stars`estimateNum'   ""

							foreach signLevel in 0.1 0.05 0.01 {

								if `pvalue`estimateNum'' < `signLevel' local stars`estimateNum' "`stars`estimateNum''*"
							}
						}

						local obs = e(N)

						forv  estimateNum = 1/`treatvarCount' {

							if	`estimateNum' == 1 {
								local EFFECTnote 				   "  [`treatvar' == `estimateNum'] `beta`estimateNum'' (`se`estimateNum'')`stars`estimateNum'';"
							}
							else {
								local EFFECTnote `" "`EFFECTnote'" "  [`treatvar' == `estimateNum'] `beta`estimateNum'' (`se`estimateNum'')`stars`estimateNum'';" "'
							}
						}

						local EFFECTnote `" note("{bf:Treatment effects} =" `EFFECTnote' "  N = `obs'.") "'
					}
				}
			}
}
/*******************************************************************************
	Prepare figure inputs
*******************************************************************************/
{
			// If the treatment variable has no defined label, we leave the value in the legend
			if  missing("`treatvar_value_label'") {

				foreach treatvarNum of local treatvar_levels {

					local label_`treatvarNum' "`treatvarNum'"
				}
			}

			// If the treatmnet variable has labels, we will display it in the legend
			if !missing("`treatvar_value_label'") {

				foreach treatvarNum of local treatvar_levels {

					local label_`treatvarNum' : label (`treatvar') `treatvarNum'
				}
			}

			// Prepare [kdensity] code and legend argument
			local     treatCount = 0
			local kdensityString  "tw"
			local 	legendString `"legend(order(0 "Treatment assignment:" "'

			foreach treatvarNum of local treatvar_levels {

				local treatCount	  = `treatCount' + 1

				local kdensityString `" `kdensityString' (kdensity `varlist' if `treatvar' == `treatvarNum' [`weight'`exp'] , `kdensityoptions' color(`color_`treatvarNum'') ) "'

				local   legendString `"   `legendString' `treatCount' "`label_`treatvarNum''" "'
			}

			// Add final parenthesis and number of rows (this can be changed by the user through graphoptions()
			if   `treatvar_num_groups' == 2 		 local rowString "row(1)"

			local legendString         `" `legendString') `rowString' )"'

			// Record outcome variable label to be shown as x-axis title
			local varLab 				: var label `varlist'
		}
}

/*******************************************************************************
	Plot the figure!
*******************************************************************************/

		`kdensityString' 		///
		 , 						///
		`STATxline' 			///
		`EFFECTnote' 			///
		`legendString'			///
		 ytitle(Density) 		///
		 xtitle(`varLab')		///
		`graphoptions'

		// Restore original dataset
		restore

	// End
	end

	// And now, you shall plot the distributions! ;)


iematch : countdown output one line

iematch : countdown output one line

I made the countdown on observations left to match to appear on one line
to take less space

	clear all

	*command starts here

	cap program drop 	iematch
	    program define	iematch

		syntax  [if] [in]  , ///
			GRPdummy(varname) 		///
			MATCHcont(varname) 		///
			[						///
			idvar(varname)			///
			matchidname(string)		///
			matchdiffname(string)	///
			matchnoname(string)		///
			]

		*****
		*1 format errors as smcl
		*2 make match only on obs with value in group dummy
		*3 m:1 match

		noi di "Syntax OK!"

		pause on

		qui {

		********************************
		*
		*	Gen temp sort and merge var
		*
		********************************

		tempvar originalSort

		gen `originalSort' = _n

		preserve

			if "`if'`in'" != "" keep `if'`in'

			********************************
			*
			*	Checking group dummy
			*
			********************************

			*Test that the group dummy is 1, 0 or missing
			cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .
			if _rc != 0 {

				di as error "The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command."
				error _rc
			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`grpdummy')
			if `r(N)' > 0 {
				*This is not an error just outputting the number
				noi di "`r(N)' observation(s) were excluded due to missing value in group dummy"
			}
			*Drop obs with missing
			drop if missing(`grpdummy')

			********************************
			*
			*	Checking match continous var
			*
			********************************

			*Test that the continous is numeric
			cap confirm numeric variable `matchcont'
			if _rc != 0 {

				di as error "The variable to match on specified in matchcont(`matchcont') is not a numeric variable."
				error 109

			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`matchcont')
			if `r(N)' > 0 {
				*This is not an error just outputting the number
				noi di "`r(N)' observation(s) were excluded due to missing value in match varaible"
			}
			*Drop obs with missing
			drop if missing(`matchcont')

			********************************
			*
			*	Checking duplicates in varaible names in options
			*
			********************************

			*Create a local of all varnames used in any option
			local allnewvars `idvar' `matchidname' `matchdiffname' `matchnoname'

			*Check if there are any duplicates in the local of all varnames in options
			local dupnewvars : list dups allnewvars

			*Throw error if there were any duplicates
			if "`dupnewvars'" != "" {

				di as error "The same variable name was used twice or more in the options. Go back and check syntax"
				error 198

			}

			********************************
			*
			*	Checking ID var
			*
			********************************

			*Checking set-up for the ID var used for _matchID
			if "`idvar'" == "" {

				*Copy this name
				local idvar _ID

				*Make sure that the default name _ID is not already used
				cap confirm variable `idvar'
				if _rc == 0 {

					di as error "A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set."
					error 110

				}

				*Generate the ID var from row number
				gen `idvar' = _n

			}
			else {

				*Make sure that user specified ID is uniquely and fully identifying the observations
				cap isid `idvar'
				if _rc != 0 {

					di as error "Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using if or in."
					error 450

				}
			}

			********************************
			*
			*	Checking and generating the MatchID and the MatchDiff var
			*
			********************************

			*Test input from user or test if deafault value is valiable
			iematchMatchVarCheck _matchID `matchidname'
			local matchIDname "`r(validVarName)'"
			gen  `matchIDname' = .

			iematchMatchVarCheck _matchDiff `matchdiffname'
			local matchDiffName "`r(validVarName)'"
			gen `matchDiffName' = .

			iematchMatchVarCheck _matchOrReason `matchnoname'
			local noMatchReasonName "`r(validVarName)'"
			gen `noMatchReasonName' = .

			*Create a label for missing values that explains no match
			label define matchLabel 0 "Not Matched" 1 "Matched" .n "Obs not included in match"

			*Apply the label
			label value `noMatchReasonName' matchLabel

			********************************
			*
			*	Creating tempvar used
			*
			********************************

			*Initiate the temporary variables used by this command
			tempvar hi_diff lo_diff pref match newMatch rand

			gen `hi_diff' = .
			gen `lo_diff' = .

			gen `pref' = .
			gen byte `match' = 0
			gen byte `newMatch' = 0

			** Generate random variable that seperate two obs
			*  with the same value in the continuos variable
			gen `rand' = uniform()

			********************************
			*
			*	Start matching
			*
			********************************
			noi di ""
			noi di "{pstd}Observations left to match: {p_end}"
			count if `grpdummy' == 1 & `match' == 0
			local left2Match = `r(N)'
			noi di "{pstd}`left2Match' " _c

			while (`left2Match' > 0) {

				sort `match' `matchcont' `rand'

				replace `lo_diff' 	= .
				replace `hi_diff' 	= .
				replace `pref'		= . if `match' == 0
				replace `newMatch' 	= 0

				replace `lo_diff' = abs(`matchcont' - `matchcont'[_n-1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n-1]
				replace `hi_diff' = abs(`matchcont' - `matchcont'[_n+1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n+1]

				replace `pref' = `idvar'[_n-1] if `match' == 0 & `lo_diff' <  `hi_diff'
				replace `pref' = `idvar'[_n+1] if `match' == 0 & `lo_diff' >= `hi_diff'

				replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n-1] & `pref'[_n-1] == `idvar'
				replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n+1] & `pref'[_n+1] == `idvar'

				replace `match' = 1 							if `newMatch' == 1
				replace `matchDiffName' = min(`lo_diff', `hi_diff') 	if `newMatch' == 1
				replace `matchIDname' = `idvar' 						if `newMatch' == 1 & `grpdummy' == 1
				replace `matchIDname' = `pref' 						if `newMatch' == 1 & `grpdummy' == 0

				*order _match* , last

				count if `grpdummy' == 1 & `match' == 0
				local left2Match = `r(N)'
				noi di "`left2Match' " _c
			}

			replace `noMatchReasonName' = 0 if `match' == 0 & `grpdummy' == 0

			keep `matchIDname' `matchDiffName' `idvar' `originalSort' `noMatchReasonName'

			tempfile mergefile

			save `mergefile'

		restore

		tempvar mergevar

		merge 1:1  `originalSort' using `mergefile', gen(`mergevar')

		replace `noMatchReasonName' = .n if `mergevar' == 1

		replace `noMatchReasonName' = 1 if `noMatchReasonName' == .

		noi di "{p_end}" _c
		noi tab `noMatchReasonName' `grpdummy', m

		sort `originalSort'

	}

	end

	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName userName

		if "`defaultName'" == "_matchID" 		local optionName matchidname
		if "`defaultName'" == "_matchDiff" 		local optionName matchdiffname
		if "`defaultName'" == "_matchOrReason" 	local optionName matchnoname

		*All the default names
		local dfltNms _noMatchReason _matchDiff _matchOrReason

		*The other two default names
		local othDfltNms : list dfltNms - defaultName

		*Creating two locals with the deafult name in each local
		local Oth1 : word 1 of `othDfltNms'
		local Oth2 : word 2 of `othDfltNms'

		*Testing that the option name is not the same as the other variable's default name.
		if ("`defaultName'" == "_matchID" & ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "_ID"))  {

			noi di as error `" ("`defaultName'" == "_matchID" & ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "_ID")) "'

			noi di as error "The new name specified in `optionName'() is not allowed to be _ID, `Oth1', nor `Oth2'"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "`userName'" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `userName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name specified in `optionName'(`userName') is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified in `optionName'(`userName') is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end

	clear

*	set seed 1235324

	set obs 400000

	gen id = _n

	gen rand1 = uniform()

	gen tmt = (rand1 < .40)

	*replace tmt = . if (rand1 < .05)

	drop rand1
	tab tmt

	gen p_hat = uniform()

	*replace p_hat = . if p_hat < .01

	iematch  , grp(tmt) match(p_hat) idvar(id) // matchidname(Kallefille)

	pause
	clear all

	*command starts here

	cap program drop 	iematch
	    program define	iematch

		syntax  [if] [in]  , ///
			GRPdummy(varname) 		///
			MATCHcont(varname) 		///
			[						///
			idvar(varname)			///
			matchidname(string)		///
			matchdiffname(string)	///
			matchnoname(string)		///
			]

		*****
		*1 format errors as smcl
		*2 make match only on obs with value in group dummy
		*3 m:1 match

		noi di "Syntax OK!"

		pause on

		qui {

		********************************
		*
		*	Gen temp sort and merge var
		*
		********************************

		tempvar originalSort

		gen `originalSort' = _n

		preserve

			if "`if'`in'" != "" keep `if'`in'

			********************************
			*
			*	Checking group dummy
			*
			********************************

			*Test that the group dummy is 1, 0 or missing
			cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .
			if _rc != 0 {

				di as error "The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command."
				error _rc
			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`grpdummy')
			if `r(N)' > 0 {
				*This is not an error just outputting the number
				noi di "`r(N)' observation(s) were excluded due to missing value in group dummy"
			}
			*Drop obs with missing
			drop if missing(`grpdummy')

			********************************
			*
			*	Checking match continous var
			*
			********************************

			*Test that the continous is numeric
			cap confirm numeric variable `matchcont'
			if _rc != 0 {

				di as error "The variable to match on specified in matchcont(`matchcont') is not a numeric variable."
				error 109

			}

			**Exclude obs with missing value in groupdummy

			*Count number of obs to be dropped and and output that number if more than zero
			count if missing(`matchcont')
			if `r(N)' > 0 {
				*This is not an error just outputting the number
				noi di "`r(N)' observation(s) were excluded due to missing value in match varaible"
			}
			*Drop obs with missing
			drop if missing(`matchcont')

			********************************
			*
			*	Checking duplicates in varaible names in options
			*
			********************************

			*Create a local of all varnames used in any option
			local allnewvars `idvar' `matchidname' `matchdiffname' `matchnoname'

			*Check if there are any duplicates in the local of all varnames in options
			local dupnewvars : list dups allnewvars

			*Throw error if there were any duplicates
			if "`dupnewvars'" != "" {

				di as error "The same variable name was used twice or more in the options. Go back and check syntax"
				error 198

			}

			********************************
			*
			*	Checking ID var
			*
			********************************

			*Checking set-up for the ID var used for _matchID
			if "`idvar'" == "" {

				*Copy this name
				local idvar _ID

				*Make sure that the default name _ID is not already used
				cap confirm variable `idvar'
				if _rc == 0 {

					di as error "A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set."
					error 110

				}

				*Generate the ID var from row number
				gen `idvar' = _n

			}
			else {

				*Make sure that user specified ID is uniquely and fully identifying the observations
				cap isid `idvar'
				if _rc != 0 {

					di as error "Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using if or in."
					error 450

				}
			}

			********************************
			*
			*	Checking and generating the MatchID and the MatchDiff var
			*
			********************************

			*Test input from user or test if deafault value is valiable
			iematchMatchVarCheck _matchID `matchidname'
			local matchIDname "`r(validVarName)'"
			gen  `matchIDname' = .

			iematchMatchVarCheck _matchDiff `matchdiffname'
			local matchDiffName "`r(validVarName)'"
			gen `matchDiffName' = .

			iematchMatchVarCheck _matchOrReason `matchnoname'
			local noMatchReasonName "`r(validVarName)'"
			gen `noMatchReasonName' = .

			*Create a label for missing values that explains no match
			label define matchLabel 0 "Not Matched" 1 "Matched" .n "Obs not included in match"

			*Apply the label
			label value `noMatchReasonName' matchLabel

			********************************
			*
			*	Creating tempvar used
			*
			********************************

			*Initiate the temporary variables used by this command
			tempvar hi_diff lo_diff pref match newMatch rand

			gen `hi_diff' = .
			gen `lo_diff' = .

			gen `pref' = .
			gen byte `match' = 0
			gen byte `newMatch' = 0

			** Generate random variable that seperate two obs
			*  with the same value in the continuos variable
			gen `rand' = uniform()

			********************************
			*
			*	Start matching
			*
			********************************

			count if `grpdummy' == 1 & `match' == 0
			local left2Match = `r(N)'

			while (`left2Match' > 0) {

				sort `match' `matchcont' `rand'

				replace `lo_diff' 	= .
				replace `hi_diff' 	= .
				replace `pref'		= . if `match' == 0
				replace `newMatch' 	= 0

				replace `lo_diff' = abs(`matchcont' - `matchcont'[_n-1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n-1]
				replace `hi_diff' = abs(`matchcont' - `matchcont'[_n+1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n+1]

				replace `pref' = `idvar'[_n-1] if `match' == 0 & `lo_diff' <  `hi_diff'
				replace `pref' = `idvar'[_n+1] if `match' == 0 & `lo_diff' >= `hi_diff'

				replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n-1] & `pref'[_n-1] == `idvar'
				replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n+1] & `pref'[_n+1] == `idvar'

				replace `match' = 1 							if `newMatch' == 1
				replace `matchDiffName' = min(`lo_diff', `hi_diff') 	if `newMatch' == 1
				replace `matchIDname' = `idvar' 						if `newMatch' == 1 & `grpdummy' == 1
				replace `matchIDname' = `pref' 						if `newMatch' == 1 & `grpdummy' == 0

				*order _match* , last

				noi count if `grpdummy' == 1 & `match' == 0
				local left2Match = `r(N)'

				pause

			}

			replace `noMatchReasonName' = 0 if `match' == 0 & `grpdummy' == 0

			keep `matchIDname' `matchDiffName' `idvar' `originalSort' `noMatchReasonName'

			tempfile mergefile

			save `mergefile'

			*pause

		restore

		tempvar mergevar

		merge 1:1  `originalSort' using `mergefile', gen(`mergevar')

		replace `noMatchReasonName' = .n if `mergevar' == 1

		replace `noMatchReasonName' = 1 if `noMatchReasonName' == .

		noi tab `noMatchReasonName' `grpdummy', m

		sort `originalSort'

	}

	end

	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName userName

		if "`defaultName'" == "_matchID" 		local optionName matchidname
		if "`defaultName'" == "_matchDiff" 		local optionName matchdiffname
		if "`defaultName'" == "_matchOrReason" 	local optionName matchnoname

		*All the default names
		local dfltNms _noMatchReason _matchDiff _matchOrReason

		*The other two default names
		local othDfltNms : list dfltNms - defaultName

		*Creating two locals with the deafult name in each local
		local Oth1 : word 1 of `othDfltNms'
		local Oth2 : word 2 of `othDfltNms'

		*Testing that the option name is not the same as the other variable's default name.
		if ("`defaultName'" == "_matchID" & ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "_ID"))  {

			noi di as error `" ("`defaultName'" == "_matchID" & ("`userName'" == "`Oth1'" | "`userName'" == "`Oth2'" | "`userName'" == "_ID")) "'

			noi di as error "The new name specified in `optionName'() is not allowed to be _ID, `Oth1', nor `Oth2'"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "`userName'" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `userName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name specified in `optionName'(`userName') is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified in `optionName'(`userName') is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end

	clear

*	set seed 1235324

	set obs 40000

	gen id = _n

	gen rand1 = uniform()

	gen tmt = (rand1 < .40)

	replace tmt = . if (rand1 < .05)

	drop rand1
	tab tmt

	gen p_hat = uniform()

	replace p_hat = . if p_hat < .01

	iematch  , grp(tmt) match(p_hat) idvar(id) // matchidname(Kallefille)


Rewrite CC.do to make it fail if $CC fails

redo-ifchange config.sh
. ./config.sh

exec >$3
cat <<-EOF
	redo-ifchange \$SRCDIR/\$2.c
	$CC $CFLAGS -MD -MF /dev/fd/1 -o \$3 -c \$SRCDIR/\$2.c | sed 's/^[^:]*://g'|
	    sed 's/ \\\\$//g' | xargs redo-ifchange
EOF
chmod +x $3

redo-ifchange config.sh
. ./config.sh

exec >$3
cat <<-EOF
	redo-ifchange \$SRCDIR/\$2.c
	IFS= read DEPS << END
	\$($CC $CFLAGS -MD -MF /dev/fd/1 -o \$3 -c \$SRCDIR/\$2.c)
	END
	redo-ifchange \${DEPS#*:}
EOF
chmod +x $3