* Convenient program stopper
*! Version 1.0.2 22may2020
* Contact jesse.wursten@kuleuven.be for bug reports/inquiries.

* Changelog
** 26jun2018: The command is born.

*stop																	// Stop dofile, close log
*stop, sts(default) save												// Save sts option "default"
*stop																	// Stop dofile, close log, send message to saved sts option
*stop, sts(overwrite)													// Stop dofile, close log, do not send message to saved sts option
*stop, sts(default) message(Custom message) logfile(named)				// Stop dofile "named", display "Custom Message" and send "Custom Message" to sts url "Default" (note that default corresponds to a url because it was saved through sts itself)

*cap program drop stop stop_saveoption
program define stop
	version 8.0
	syntax [, sts(string) Message(string) Logfile(string) SAVEoptions]

	* Normal operation
	if `"`saveoptions'"' == "" {
		** Message
										local messageDefined "Dofile ran until specified stopping point."	// 3. Default message
		if "${stop_message}" != "" 		local messageDefined `"${stop_message}"'							// 2. Saved message
		if `"`message'"' != "" 			local messageDefined `"`message'"'									// 1. Specified message
		if `"`message'"' == "overwrite" local messageDefined "Dofile ran until specified stopping point."	// 0. Default message if user wants to overwrite saved message
		di as text _col(4) `"`messageDefined'"' _newline

		** Logfile
										local logfileDefined "_all"				// 3. Close all logfiles
		if "${stop_logfile}" != "" 		local logfileDefined "${stop_logfile}"	// 2. Close saved logfile
		if "`logfile'" != "" 			local logfileDefined "`logfile'"		// 1. Close specified logfile
		if "`logfile'" == "overwrite" 	local logfileDefined "_all" 			// 0. Close all logfiles if user wants to overwrite saved logfile

		cap noisily log close `logfileDefined'

		** Sendtoslack
										local stsDefined ""					// 3. Default is empty
		if "${stop_sts}" != "" 			local stsDefined `"${stop_sts}"'	// 2. Saved sts url
		if `"`sts'"' != "" 				local stsDefined `"`sts'"'			// 1. Specified sts url
		if `"`sts'"' == "overwrite" 	local stsDefined ""					// 0. Empty if user wants to overwrite saved sts url

		if "`stsDefined'" != "" {
			* Verify that sendtoslack is installed
			cap which sendtoslack
			if _rc != 0 {
				di _col(4) as error "sendtoslack not installed. Use code below to install."
				di _col(8) as result "ssc install sendtoslack"
				di _col(4) as text "Skipping sending of message."
			}

			* Send message
			if _rc == 0 sendtoslack, url(`stsDefined') message(`"`messageDefined'"') col(4)
		}

		** Report
		local mEff `"message(`messageDefined')"'
		if `"`messageDefined'"' == "Dofile ran until specified stopping point." local mEff ""

		local logfileEff "logfile(`logfileDefined')"
		if "`logfileDefined'" == "_all" local logfileEff ""

		local stsEff "sts(`stsDefined')"
		if "`stsDefined'" == "" local stsEff ""

		di _col(4) as text "Effective command executed: " as result `"stop, `stsEff' `mEff' `logfileEff'"'

		** Stop
		error 1
	}

	* Option saving (to profile.do)
	if `"`saveoptions'"' != "" {
		if `"`sts'"' != "" 		stop_saveoption, name(sts) 		value(`"`sts'"')
		if `"`message'"' != "" 	stop_saveoption, name(message) 	value(`"`message'"')
		if `"`logfile'"' != "" 	stop_saveoption, name(logfile) 	value(`"`logfile'"')
	}
end

program define stop_saveoption
	syntax, name(string) value(string)

	* Determine whether profile.do exists
	cap findfile profile.do

	** If profile.do does not exist yet
	** Create profile.do (asking permission)
	if _rc == 601 {
		di "Profile.do does not exist yet."
		di "Do you want to allow this program to create one for you? y: yes, n: no" _newline "(enter below)" _request(_createPermission)

		if "`createPermission'" == "y" {
			di "Creating profile.do as `c(sysdir_oldplace)'profile.do"
			tempname createdProfileDo

			file open `createdProfileDo' using `"`c(sysdir_oldplace)'profile.do"', write
			file close `createdProfileDo'
		}

		if "`createPermission'" != "y" {
			di "User did not give permission to create profile.do, aborting program."
			exit
		}
	}

	* Write in global for url
	** Verify if global is already defined (if so, give warning)
	*** Find location of profile.do
	qui findfile profile.do
	local profileDofilePath "`r(fn)'"

	*** Open
	tempname profileDofile
	file open `profileDofile' using "`profileDofilePath'", read text
	file read `profileDofile' line

	*** Loop over profile.do until ...
	***		you reached the end
	***		found the global we want to define
	local keepGoing = 1
	while `keepGoing' == 1 {
		if strpos(`"`macval(line)'"', "sts_`name'") > 0 {
			di as error  "Global was already defined in profile.do"
			di as result "The program will add the new definition at the bottom."
			di "You might want to open profile.do and remove the old entry."
			di "This is not required, but prevents clogging your profile.do."
			di "To do so, type: " as txt "doed `profileDofilePath'" _newline

			local keepGoing = 0
		}

		file read `profileDofile' line
		if r(eof) == 1 local keepGoing = 0
	}
	file close `profileDofile'

	** Write in the global
	file open `profileDofile' using "`profileDofilePath'", write text append
	file write `profileDofile' _newline `"global stop_`name' `"`value'"'"'
	file close `profileDofile'

	** Define it now too, as profile.do changes only take place once it has ran
	global stop_`name' `"`value'"'

	* Report back to user
	di as text "Added a default " as result "`name'" as text " to " as result "`profileDofilePath'"
	di as text "On this PC, " as result `"`name'(`value')"' as text " will now be used even if no " as result "`name'" as text " option was specified for the stop command."
	di as text "In other words, you can now type " as result "stop" as text " and it will execute " as result `"stop, `name'(`value')"' as text " (+ any other saved options)." _newline
end