interface iCmd extends BaseIface {}
class cCmd extends BaseClass implements iCmd {
// GENERAL
const ESC = "\e";
// COLOR VALUES:
const COL_BLK_FG = 30;
const COL_BLK_BG = 40;
const COL_WHT_FG = 37;
const COL_WHT_BG = 47;
const COL_GRN_FG = 32;
const COL_GRN_BG = 42;
const COL_YEL_FG = 33;
const COL_YEL_BG = 43;
const COL_BLU_FG = 34;
const COL_BLU_BG = 44;
const COL_RESET_FG = 39; // default foreground
const COL_RESET_BG = 49; // default background
// ++ CONFIG ++ //
protected function ElementClass() : string { return ElementClass::class; }
protected function FallbackStyleClass() : string { return FallStyleClass::class; }
// -- CONFIG -- //
// ++ MARKS ++ //
protected function MarkForBold(bool $bOn) : string { return $bOn ? "\e[1m" : "\e[22m"; }
protected function MarkForItal(bool $bOn) : string { return $bOn ? '' : ''; }
protected function MarkForSmall(bool $bOn) : string { return $bOn ? '' : ''; }
// -- MARKS -- //
// ++ API ++ //
// text formatting
public function NewLine() : string { return "\n"; }
public function LineBreaks(string $s) : string { return $s; }
public function BoldIt(?string $s) : string { return "\e[1m$s\e[22m"; }
public function ItalIt(?string $s) : string { return $s; }
public function SmallIt(?string $s) : string { return "($s)"; }
public function UBarIt(?string $s) : string {
$nLen = $this->VisibleLength($s);
return $s.CRLF.str_repeat('-',$nLen); // TODO: make '-' configurable via a style
}
// colors
public function BlueIt(string $s) : string { return "\e[34m$s\e[0m"; }
public function GreenIt(string $s) : string { return "\e[32m$s\e[0m"; }
public function YellowIt(string $s) : string { return "\e[93m$s\e[0m"; }
// styles
public function DebugIt(string $s) : string { return "\e[100m\e[97m(\e[93mD\e[97m\e[22m) \e[30m$s\e[0m"; }
public function InfoIt(string $s) : string {
return
EscCol(self::COL_GRN_BG)
.EscCol(self::COL_WHT_FG)
.'('
.EscCol(self::COL_BLK_FG)
.'I'
.EscCol(self::COL_WHT_FG)
.')'
.EscCol(self::COL_RESET_BG)
.' '
.EscCol(self::COL_GRN_FG)
.$s
.EscCol(0)
;
}
#"\e[42m(\e[30mI\e[22m)\e[0m ".$this->YellowIt($s); }
public function FaintIt(string $s) : string { return "\e[2m$s\e[22m"; }
public function XMLTagIt(string $s) : string { return $this->BlueIt($this->BoldIt('<')).$s.$this->BlueIt($this->BoldIt('>')); }
// 2021-08-23 Written but not tested.
public function TitleIt(string $s) : string {
$nLen = strlen($s);
$sLine = '+'.str_repeat('-',$nLen+2).'+';
$CRLF = $this->NewLine();
return $CRLF.$sLine.$CRLF."| $s |".$CRLF.$sLine.$CRLF;
}
public function ErrorIt(string $s) : string { return "\e[1;31m$s\e[0m"; }
// experimental in TTY
public function LinkIt(string $sText, string $sURL) : string { return "\e]8;;$sURL\e\\$sText\e]8;;\e\\"; }
// 2021-09-24 This will need improving. Not tested.
public function BoxIt(string $s) : string { return $s; }
// TODO 2025-02-19: replace this with a Style system call
public function InlineClass(string $sText, string $sClass) : string { return $sText; }
// There really isn't any CLI equivalent, but maybe we can pretty this up more later.
public function HideDrop(string $sSummary, string $sContent) : string {
$ftSumm = $this->BlueIt($sSummary);
$ftDash = $this->BoldIt('====');
return "\n$ftDash [+] $ftSumm $ftDash\n$sContent\n$ftDash [-] $ftSumm $ftDash\n";
}
// fixed-pitch / linebreaks: CLI is always in that mode, so do nothing
public function OpenFixed() : string { return "\n"; }
public function ShutFixed() : string { return "\n"; }
public function FixPitchIt(string $s) : string { return "'"`UNIQ--pre-00000001-QINU`"'"; }
public function NewLineIt(string $s) : string { return $s; } // no conversion needed
// bulk text formatting
// crude indentation
public function MakeList(string $s) : string { return str_replace("\n","\n ",$s); }
// graphic elements
public function HorizLine() : string { return str_repeat('-',40); }
// characters
public function LeftArrow() : string { return '<-'; }
public function RightArrow() : string { return '->'; }
// markup
// NOTE: Not to be confused with VisibleLength()
public function StripMarkup(string $s) : string { return $s; }
/**
ACTION: write the output to a temp file, then use an external program to render it for TTY.
HISTORY:
2024-08-13 written; would eventually like better rendering...
*/
public function RenderHTML(string $ht) : string {
$crlf = $this->NewLine();
// get temp filename to use for output
$fnRaw = tempnam('/tmp','woozalia');
$fsRaw = $fnRaw.'.html';
// write the output to the temp file
$ok = file_put_contents($fsRaw,$ht);
if ($ok) {
$fsRend = $fnRaw.'.txt';
$sCmd = "html2text -o '$fsRend' '$fsRaw'";
// 2024-08-13 WORKING HERE
$ok = exec($sCmd,$arRes);
if ($ok) {
$sOut = implode($crlf,$arRes);
} else {
echo $this->ErrorIt('Error: could not re-render tempfile ')." [$fsRaw] to [$fsRend].".$crlf;
echo $ht; // echo the rest of the display without rendering
die();
}
} else {
echo $this->ErrorIt('Error: could not write to tempfile ')." [$fsRaw]".$crlf;
echo $ht; // echo the rest of the display without rendering
die();
}
return $sOut;
}
// -- API -- //
// ++ TTY-only ++ //
public function VisibleLength(string $sFull) : int {
// TODO
$nViz = 0;
$dxFi = 0;
do {
// Get postion of next ESC sequence, if any:
$dxSt = strpos($sFull,"\e[",$dxFi);
if (is_int($dxSt)) {
// ESC sequence-start found
// Get the number of [visible] characters since the end of the previous ESC sequence:
$nViz += ($dxSt-$dxFi);
#$sDbg = ($nViz > 0) ? substr($sFull,$dxFi,$nViz) : '';
#echo " - dxFi=[$dxFi] dxSt=[$dxSt] nViz=[$nViz] substr=[$sDbg]\n";
$dxFi = strpos($sFull,'m',$dxSt);
#echo " - next dxFi=[$dxFi]\n";
if (is_int($dxFi)) {
$dxFi++; // skip the ending char
$bFnd = TRUE;
} else {
#echo " - No finishing mark!\n";
$bFnd = FALSE;
// This should kind of never happen...
}
} else {
// No [more] start-marks to find, so add in the remaining length:
$nViz += strlen($sFull) - $dxFi;
$bFnd = FALSE;
#$sDbg = ($nViz > 0) ? substr($sFull,$dxFi,$nViz) : '';
#echo " - end-part found; dxFi=[$dxFi] nViz=[$nViz] substr=[$sDbg]\n";
}
} while ($bFnd);
#echo " - nViz=[$nViz]\n";
#echo "DASHES= [".str_repeat('-',$nViz).']'.CRLF;
return $nViz;
}
// ++ TTY-only (so far) ++ //
public function ClearToEOL() : string { return self::ESC.'[0J'; }
// -- TTY-only ++ //
}