Futilities/v0.6/clade/Kiosk: Difference between revisions

From Woozle Writes Code
< Futilities‎ | v0.6‎ | clade
Jump to navigation Jump to search
No edit summary
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{page/clade/v2
{{page/clade/v2
|fam=
|fam=
{{!}} align=right  {{!}} [WFe]{{l/ver/clade|p=ferreteria|Sys\Routing|Kiosk}}[ca]
{{!}} align=right  {{!}} [WFe]{{l/ver/clade|p=ferreteria|Sys\Routing|Kiosk}}
{{!}} align=center {{!}} &rArr; {{l/ver/clade/base|Kiosk}} &rArr;
{{!}} align=center {{!}} &rArr; {{l/ver/clade/base|Kiosk}} &rArr;
{{!}} align=left  {{!}}
{{!}} align=left  {{!}}
Line 14: Line 14:
{{!-!}} '''QStr'''*  [c,i] {{!!}} {{l/ver/clade/full|p=ferreteria|Data\Mem\QVar|Str}}
{{!-!}} '''QStr'''*  [c,i] {{!!}} {{l/ver/clade/full|p=ferreteria|Data\Mem\QVar|Str}}
}}
}}
==About==
* PURPOSE: base class for parsing and managing command-line options
** I originally tried to use <code>[https://www.php.net/manual/en/function.getopt.php getopt()]</code>, but the way it does stuff just adds confusion and removes flexibility.
==Terminology==
==Terminology==
At one point I was using the following:
At one point I was using the following:
* AppOptions - the options made available by the app
* AppOptions - the options made available by the app
Line 23: Line 25:
==Pages==
==Pages==
* [[/@history/]]
* [[/@history/]]
* [[/@fx/]]: functions documentation
* [[/@thinking/]]
* [[/@removed/]]
==Code==
''as of {{fmt/date|2025|11|15}}''
{{fmt/php/block|1=
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 ++ //


<syntaxhighlight lang=markdown>
    /**
# Details
    * CEMENT: Kiosk\Root
    * INSTAR: show usage/help message
    */
    protected function GoHome() {
        echo $this->RenderAppUsage();
    }


## 2024-12-19
    // -- ACTION -- //
    // ++ VALUES ++ //


```php
     public function NameString() : string { return $this->FTagFor_AppItem()->SName(); }
    private $oTerms = NULL;
    // RETURNS: an object encapsulating the *available* CLI options
     public function Terms() : TermsIface { return $this->oTerms ?? ($this->oTerms = $this->NewTerms()); }
    // 2024-12-16 old methodology
    public function Terms() : TermsIface { return $this->oTerms ?? ($this->oTerms = $this->BuildTerms()); }
    protected function BuildTerms() : TermsIface { echo self::PromptForMethod(); }
```


## 2024-11-07
    // -- VALUES -- //
    // ++ INPUT ++ //


We really need better terminology around Opts and Options. Opts has AppOpts() which returns a different class altogether.
    // ACTION: do any setup needed so we're ready to lookup user (command) input against the known (application) options
      * I'm going to start the de-tangling efforts by removing the Base2Iface & Base2Trait stuff.
    protected function SetupTerms() { echo self::PromptForMethod(); }
        * It doesn't make sense to have [WF]Sys\Data\Options as a parent *and* as a returned object (AppOpts() returns OptionsIface, which aliases to the same exact class).
    // ACTION: do all the fiddly reorganizing needed to figure out what the input means
      * Next, renaming iOpts/caOpts -> iKiosk/caKiosk, and removing commented-out code that seems unlikely to be applicable anymore. This includes:
    protected function ParseInput() {
        * protected function GetAppOptionKey(string $sText) : string { return $this->arAppOpts[$sText]; }
        // 2025-03-09 This is done in the config.
        * these bits which were already commented out on 2024-10-06:
        // It also first gets called in WUIDL Kiosk, so maybe it should just be there.
```php
    }
     /**----
    // ACTION: act on the input
      THINKING: This is a facility that will not always be used. The idea is that sometimes
    protected function HandleInput() { echo self::PromptForMethod(); }
        we want to treat options as commands which can be repeated with different arguments,
     // ACTION: deal with errors (currently, just display them)
        rather than just as options. Maybe this is actually a bad idea...
     protected function HandleErrors() {
     */
         $oScrn = self::Screen();
    public function DoSerially() {
        $oaErrs = $this->Errors();
         $arOpts = $this->GetCmdOptionsBySeq();
         $nErr = $oaErrs->Count();
         foreach ($arOpts as $nIdx => $oOpt) {
        if ($nErr > 0) {
             $sName = $oOpt->GetKey();
            $ar = $oaErrs->GetVals();
             $sKey = $this->GetAppOptionKey($sName);
            $sPlur = ($nErr == 1) ? '' : 's';
             $this->DoSerialOption($sKey);
            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();
         }
         }
     }
     }
    // STUB
    protected function DoSerialOption(int $nSeq) {}


     // ++ COMMAND: TERMS ++ //
    // -- INPUT -- //
     // ++ UI: ERRORS ++ //
 
    private $oHow = NULL; public function Errors() : ItWentIface { return $this->oHow ?? ($this->oHow = new ($this->ItWentClass())); }


     // 2024-10-06 More old command-term stuff that doesn't appear to be in use.
     // ++ UI: HELP ++ //


     private $arTerms = [];
     /**
     protected function AddCmdTerm(string $sText) {
    * HISTORY:
         $this->arTerms[] = $sText;
    *  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"
            ;
     }
     }
    protected function GetCmdTerms() : array { return $this->arTerms; }


     // 2022-08-05 Should probably be renamed to "HasTerms()", OSLT, for generalization
     abstract protected function RenderHelpText() : string;
    public function HasCmdTerms() : bool { return count($this->GetCmdTerms()) > 0; }


     // ++ COMMAND: DEFINED OPTIONS ++ //
     /**
    * 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();


    public function ShowProgress()  : bool {
         $sSelf = $this->FTagFor_AppItem()->Summary();
         // if we're listing anything, that fights with the progress-shower
        #$osPath = $this->QStoragePath();
        return ($this->HasCmdOption(self::ksOPT_SHOW_PROGRESS) and !$this->ListingOptions()->UseScreen());
        $sOut = $sSelf.CRLF;
    }


// ...
        $oActs = $this->Actions();


    // ++ UI: FEEDBACK ++ //
        $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();
      NOTE: This sort of includes DescribeSelf(), but gives the information
            #echo $oList->ReflectThis()->Report();
        in more technical terms -- largely for debugging purposes
            foreach ($oActs as $sKey => $oAct) {
    */
                $oList->AddLine($oAct->Describe());
    // 2024-10-06 Does not appear to have been used.
                #$sOut .= $oAct->Describe();
    public function DescribeRequest() : string  {
            }
        $arOpt = $this->GetCmdOptions();
            $sOut .= $oList->Render();
        $arTrm = $this->GetCmdTerms();


        $out = "++ INPUT DESCRIPTION ++\n";
        $nOpt = count($arOpt);
        if ($nOpt > 0) {
            $sPlur = (($nOpt == 1) ? '' : 's');
            $out .= "Option$sPlur set:\n";
            foreach ($arOpt as $sKey => $oOpt) {
                $sOpt = $oOpt->ShowSelf();
                $out .= " - [$sKey]: $sOpt\n";
            }
        } else {
            $out .= "No input options set.\n";
         }
         }
        return $sOut;
    }
    // -- UI -- //
    // ++ OBJECTS ++ //
    private $osName = NULL; public function QSelfName() : QStrIface { return $this->osName ?? ($this->osName = QStrClass::AsNew()); }


        $nTrm = count($arTrm);
    private $oLog = NULL;
         if ($nTrm > 0) {
    protected function _LogFile(LogIface $o) { $this->oLog = $o; }
             $sPlur = (($nTrm == 1) ? '' : 's');
    protected function HasLog() : bool { return !is_null($this->oLog); }
             $out .= "Term$sPlur:\n";
    public function LogFile() : LogIface {
             foreach ($arTrm as $nIdx => $sVal) {
         if (!($this->HasLog())) {
                $out .= " - [$sVal]\n";
             $oSet = self::Settings();
            }
            $fsLog = $oSet->LogFileSpec();
             $scLog = $oSet->LogFileClass();
             $oLog = new $scLog($fsLog);
            $this->oLog = $oLog;
         } else {
         } else {
             $out .= "No input terms given.\n";
             $oLog = $this->oLog;
         }
         }
        $out .= "-- INPUT DESCRIPTION --\n";
         return $oLog;
         return $out;
     }
     }


     // -- UI -- //
     // -- OBJECTS -- //
    // ++ TERMS: APP: management ++ //
 
    abstract protected function AppInTerms() : FListIface;
 
    // -- TERMS -- //


```
}
</syntaxhighlight>
}}

Latest revision as of 02:19, 16 November 2025

Clade Family
[WFe]Kiosk Kiosk

Legacy
WUIDL

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
Subpages

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 -- //

}