*! 1.0 MBH 14 July 2022
*!   this do-file is meant to accompany the shell wrapper -inshell-
*!   and functions as a "diagnostic" routine

capture program drop inshell_diagnostics

program define inshell_diagnostics
version 14

if lower(c(os)) == "windows" {
	display ///
		as error ///
			" >>> Sorry, but {bf:inshell} does not currently have a diagnostics mode for {bf:Microsoft Windows}. Stay tuned."
	exit 1
}

if missing(c(console)) cls

if missing("${INSHELL_DISABLE_LOGO}") {
	local sides `= min(int((min(`: set linesize', 128) - 51) / 2), 42)'
	noisily display ///
	  as result ///
	    "{dup `= `sides'*2+51':░}" _n "{dup `sides':░}{dup 43:░}   ░   ░{dup `sides':░}" _n "{dup `sides':▒}▒▒  {dup 19:▒}   {dup 17:▒}   ▒   ▒{dup `sides':▒}" _n "{dup `sides':▒}▒▒▒▒▒   ▒   ▒▒▒▒     ▒▒   {dup 9:▒}   ▒▒▒▒▒   ▒   ▒{dup `sides':▒}" _n "{dup `sides':▓}▓   ▓▓   ▓▓   ▓   ▓▓▓▓▓     ▓▓▓▓▓  ▓▓▓   ▓▓   ▓   ▓{dup `sides':▓}" _n "{dup `sides':▓}▓   ▓▓   ▓▓   ▓▓▓    ▓▓   ▓▓  ▓▓{space 9}▓▓   ▓   ▓{dup `sides':▓}" _n "{dup `sides':▓}▓   ▓▓   ▓▓   ▓▓▓▓▓   ▓  ▓▓▓   ▓  {dup 9:▓}   ▓   ▓{dup `sides':▓}" _n "{dup `sides':█}█   █    ██   █      ██  ███   ███     ████   █   █{dup `sides':█}" _n "{dup `= `sides'*2+51':█}"
	noisily display ///
	  as result "{it}{space `= `sides'+11'}the {ul:ultimate} Stata shell wrapper" _n ///
	  as text   "{it}{space `= `sides'+19'}by Matthew Bryant Hall"
}

*********************** macro options **************************
local non_toggle_options   INSHELL_TERM INSHELL_PATHEXT
local toggle_options       INSHELL_ENABLE_AUTOCD INSHELL_DISABLE_REFOCUS INSHELL_DISABLE_LONGCMDMSG
local toggled_on         `: all globals "INSHELL_*ABLE*"'
local toggled_off         : list toggle_options - toggled_on
local s1                  3

tempname pathextisvalid

if !missing("${INSHELL_PATHEXT}") {
	mata : st_numscalar("`pathextisvalid'", direxists("${INSHELL_PATHEXT}"))
	if scalar(`pathextisvalid') != 1 {
		local save_INSHELL_PATHEXT  "${INSHELL_PATHEXT}"
		macro drop INSHELL_PATHEXT
	}
}

local s2 = max(`s1', max(`: strlen global INSHELL_TERM', `: strlen global INSHELL_PATHEXT'))
local dist1 0

foreach a in `toggle_options' {
	if !missing("${`a'}") global `a' "ON"
}

foreach b in `non_toggle_options' `toggle_options' {
		if `: strlen local b' > `dist1' local dist1 `= `: strlen local b' + 7'
}

noisily display ///
	as text	_n " >>> {it}these are the current" `"{stata "help inshell##syntax": macro options}"' " for {bf:inshell:}{sf}" _n

local maxofcol3 = max(`: strlen global INSHELL_TERM', `: strlen global INSHELL_PATHEXT', 3)
local dropcol `= 3 + max(60, `maxofcol3', `= 43 + `: strlen global S_SHELL'')'

foreach c in `non_toggle_options' {
	if !missing("${`c'}") {
		if !strpos("${S_SHELL}", "pwsh") {
			noisily display ///
				as result  "{space `s1'}`c'"                                             ///
				as text    "{space `= `dist1' - `: strlen local c' + 2'}{it}is set to"   ///
				as result  _col(`= `dropcol' - 3 - `:strlen global `c''') "{sf}${`c'}"   ///
				as text    _col(`dropcol') `"[{stata "macro drop `macval(c)' ": drop }]"'
		}
		else if strpos("${S_SHELL}", "pwsh") {
			noisily display ///
				as result  "{space `s1'}`c'"                                             ///
				as text    "{space `= `dist1' - `: strlen local c' + 2'}{it} has been"   ///
				as error   _col(`= `dropcol' - 11') "{sf}{bf:DISABLED}"
		}
	}
	else if missing("${`c'}") {
		noisily display ///
			as result "{space `s1'}`c'"                                                ///
			as text   "{space `= `dist1' - `: strlen local c' + 1'}{it}is {ul:not} set{sf}"
	}
}

foreach d in `toggled_on' {
	if !missing("${`d'}") {
		noisily display ///
			as result "{sf}{space `s1'}`d'"                                           ///
			as text   "{space `= `dist1' - `: strlen local d''}{it} is toggled"       ///
			as input  _col(`= `dropcol' - 5')  "{sf}{bf:ON}"                          ///
			as text   _col(`dropcol')      `"[{stata "macro drop `macval(d)' ": drop }]"'
	}
}

foreach e in `toggled_off' {
	noisily display ///
		as result "{sf}{space `s1'}`e'"                                             ///
		as text   "{space `= `dist1' - `: strlen local e''}{it} is toggled"         ///
		as error  _col(`= `dropcol' - 6') "{sf}{bf:OFF}"
}

if !missing("${INSHELL_TERM}") | !missing("${INSHELL_PATHEXT}") | !missing("${INSHELL_DISABLE_REFOCUS}") | !missing("${INSHELL_DISABLE_LONGCMDMSG}") | !missing("${INSHELL_ENABLE_AUTOCD}") {
	noisily display ///
		as text	_col(`dropcol') `"[{stata "macro drop INSHELL*" : drop ALL }]"' _n
}
else noisily display _n
*********************** S_SHELL **************************
if !missing("${S_SHELL}") {
	if strpos("${S_SHELL}", "//") {
		global S_SHELL = subinstr("${S_SHELL}", "//", "/", .)
	}
	noisily display ///
		as text       " >>> {bf:global} {it}shell macro "                                      ///
		as result     "{bf:S_SHELL}"                                                           ///
		as text       "{space `= `s1' - 2'}is set to{sf}"                                      ///
		as result    `"{space `= min(20 - `: strlen global S_SHELL', 4)'}${S_SHELL}{space 1}"' ///
		as text  _col(`dropcol') `"[{stata `"macro drop S_SHELL"': drop S_SHELL macro }]"'
}
************************** shell ********************************
capture noisily inshell_getshell
************************** PATH **************************
tempfile pathfile
if !strpos("${S_SHELL}", "pwsh") {
	capture quietly shell echo \$PATH > "`pathfile'"
}
capture confirm file "`pathfile'"
if !_rc {
	local get_path = subinstr(fileread("`pathfile'"), char(10), "", .)
}
if missing("`get_path'") {
	// the following lines are intended for Microsoft PowerShell
	tempfile pwsh_pathfile
	quietly shell \$ENV:PATH > `pwsh_pathfile'
	local get_path = subinstr(fileread("`pwsh_pathfile'"), char(10), "", .)
}
foreach f in `non_toggle_options' {
	if !missing("${`f'}") & strpos("${S_SHELL}", "pwsh") {
		// noisily display ///
		// 	as error ///
		// 		_n " >>> {bf:inshell} macro option `f' is set when global shell macro {bf:S_SHELL} is set to use {bf:Microsoft PowerShell} as Stata's {it:default} shell. This is not allowed. Only Unix shells are supported by this option. However, the setting has been overidden with no adverse risk to the user or their system."
			continue, break
	}
}
if (!missing("${INSHELL_PATHEXT}") & strpos("${S_SHELL}", "pwsh")) | !strpos("${S_SHELL}", "pwsh") {
	noisily display ///
		as text ///
			" >>> {it}your {bf:PATH} when using {bf:shell}`= cond("${INSHELL_PATHEXT}" != "" & strpos("${S_SHELL}", "pwsh") | "${INSHELL_PATHEXT}" == "", " {ul:and} {bf:inshell} ", " ")'is:{sf}" _n ///
		as result "{space `s1'}`get_path'" _n
}

if !strpos("${S_SHELL}", "pwsh") {
	capture which inshell
	if !_rc {
		capture inshell echo \$PATH
		local inshell_path "`r(no1)'"
		if !missing("${INSHELL_PATHEXT}") {
				local inshell_path_compare    `: subinstr local inshell_path ":" " ", all'
				local stata_path_compare      `: subinstr local get_path     ":" " ", all'
				local path_diff               `: list inshell_path_compare - stata_path_compare'
				if "`path_diff'" == "${INSHELL_PATHEXT}" local check "✅"
				noisily display ///
					as text     " >>> {it}your {ul:extended} {bf:PATH} when using {bf:inshell} is:{sf}" _n ///
					as result   "{space `s1'}`inshell_path'" _n
				noisily display ///
					as text     " >>> {it}the difference being that"     ///
					as result   "{sf} `path_diff' `check' "              ///
					as text     "{it} has been added to the beginning of your {bf:PATH}"
		}
	}
}
************************** invalid INSHELL_PATHEXT **************************************
if !missing("`save_INSHELL_PATHEXT'") {
	if scalar(`pathextisvalid') != 1 {
		noisily display ///
			as error  _n " >>>  {bf:inshell} path extension macro {bf:INSHELL_PATHEXT} was set to "    ///
			as text   "`save_INSHELL_PATHEXT'"                                                  _n  ///
			as error  " >>> Either this directory does not exist or it is inaccessible."        _n  ///
				" >>> As a result this program has cleared the INSHELL_PATHEXT macro."
	}
}

end