| Clade Aliases
|
| Alias |
Clade
|
| Base* [c,i] |
Sys\Routing\Kiosk
|
| FListIface |
Sys\Data\tree\XML\tags\base\FoundList
|
| ItWent* [c,i] |
Sys\Events\ItWent
|
| LogIface |
Data\File\Log\Log
|
| QStr* [c,i] |
Data\Mem\QVar\Str
|
|
About
- PURPOSE: base class for parsing and managing command-line options
- I originally tried to use
getopt(), but the way it does stuff just adds confusion and removes flexibility.
Terminology
At one point I was using the following:
- AppOptions - the options made available by the app
- CmdOptions - the options invoked by the user in a particular session
I seem to be gravitating towards just calling AppOptions "Options" and using... some other term for CmdOptions.
Pages
Code
as of 2025-11-15
interface iKiosk extends BaseIface {
// OPTIONS: standard
function DocsURL() : string;
// OUTPUT
function DescribeActions() : string;
function Errors() : ItWentIface; // 2025-08-26 possibly this needs renaming
// RETURNS: string showing basic command structure for the app
function RenderAppUsage() : string ;
}
abstract class caKiosk extends BaseClass implements iKiosk {
// ++ CONFIG ++ //
protected function ItWentClass() : string { return ItWentClass::class; }
// -- CONFIG -- //
// ++ ACTION ++ //
/**
* CEMENT: Kiosk\Root
* INSTAR: show usage/help message
*/
protected function GoHome() {
echo $this->RenderAppUsage();
}
// -- ACTION -- //
// ++ VALUES ++ //
public function NameString() : string { return $this->FTagFor_AppItem()->SName(); }
// -- VALUES -- //
// ++ INPUT ++ //
// ACTION: do any setup needed so we're ready to lookup user (command) input against the known (application) options
protected function SetupTerms() { echo self::PromptForMethod(); }
// ACTION: do all the fiddly reorganizing needed to figure out what the input means
protected function ParseInput() {
// 2025-03-09 This is done in the config.
// It also first gets called in WUIDL Kiosk, so maybe it should just be there.
}
// ACTION: act on the input
protected function HandleInput() { echo self::PromptForMethod(); }
// ACTION: deal with errors (currently, just display them)
protected function HandleErrors() {
$oScrn = self::Screen();
$oaErrs = $this->Errors();
$nErr = $oaErrs->Count();
if ($nErr > 0) {
$ar = $oaErrs->GetVals();
$sPlur = ($nErr == 1) ? '' : 's';
echo $oScrn->ErrorIt("$nErr error$sPlur found:").CRLF;
$oList = $oScrn->NewList();
foreach ($ar as $oErr) {
// 2024-10-27 we may need a RenderToList() to handle diag info properly
$oList->AddLine($oErr->Render());
}
echo $oList->Render();
echo $this->RenderCommonHelp();
}
}
// -- INPUT -- //
// ++ UI: ERRORS ++ //
private $oHow = NULL; public function Errors() : ItWentIface { return $this->oHow ?? ($this->oHow = new ($this->ItWentClass())); }
// ++ UI: HELP ++ //
/**
* HISTORY:
* 2024-07-08 Made this public so Options object can call it when the CLI input isn't right.
* This feels like it needs further refinement, but this is a Just Get It Working.
*/
public function RenderCommonHelp() : string {
#echo $this->ReflectObject()->Report();
$urlDocs = $this->DocsURL();
return
"USAGE: ".$this->RenderAppUsage()."\n"
."DOCS: $urlDocs\n"
.$this->RenderHelpText()
."\n"
;
}
abstract protected function RenderHelpText() : string;
/**
* ACTION: describe the app and what it's planning to do
* (or would try to do but can't for some reason),
* based on the current command-line options.
* NOTE: Displaying help, if there's nothing to do, is not
* the job of this method; it's done elsewhere.
* HISTORY:
* 2024-11-09 Removed help display when no action requested --
* it's redundant, and done better elsewhere.
* 2024-11-16 Restored the help display, because it's no longer
* being generated elsewhere.
* 2025-03-07 renamed DescribeSelf() -> DescribeActions()
* 2025-04-04 moved from app-specific Kiosk to here
*/
public function DescribeActions() : string {
/* 2025-04-03 old incomplete code
$sSelf = $this->FTagFor_AppItem()->Summary();
$sOut = $sSelf.' (WORK NEEDED HERE)'.CRLF;
return $sOut;
*/
// 2025-04-03 What if we just copy from DBA?
$oScrn = self::Screen();
$sSelf = $this->FTagFor_AppItem()->Summary();
#$osPath = $this->QStoragePath();
$sOut = $sSelf.CRLF;
$oActs = $this->Actions();
$nActs = $oActs->Count();
if ($nActs == 0) {
$sOut .= 'No action requested.'.CRLF;
$sOut .= $this->RenderHelpText();
} else {
$sS = ($nActs == 1) ? '' : 's';
$sOut .= "Planned action$sS:".CRLF;
$oList = $oScrn->NewList();
#echo $oList->ReflectThis()->Report();
foreach ($oActs as $sKey => $oAct) {
$oList->AddLine($oAct->Describe());
#$sOut .= $oAct->Describe();
}
$sOut .= $oList->Render();
}
return $sOut;
}
// -- UI -- //
// ++ OBJECTS ++ //
private $osName = NULL; public function QSelfName() : QStrIface { return $this->osName ?? ($this->osName = QStrClass::AsNew()); }
private $oLog = NULL;
protected function _LogFile(LogIface $o) { $this->oLog = $o; }
protected function HasLog() : bool { return !is_null($this->oLog); }
public function LogFile() : LogIface {
if (!($this->HasLog())) {
$oSet = self::Settings();
$fsLog = $oSet->LogFileSpec();
$scLog = $oSet->LogFileClass();
$oLog = new $scLog($fsLog);
$this->oLog = $oLog;
} else {
$oLog = $this->oLog;
}
return $oLog;
}
// -- OBJECTS -- //
// ++ TERMS: APP: management ++ //
abstract protected function AppInTerms() : FListIface;
// -- TERMS -- //
}