Index

MMO\core\shell

MMO\core\shell · 64 symbols · generated 30 Sep 2026

function

ask

shell.php:1155

Ask input from the user

function ask(string $message, ?array $options = null, ?string $default = null): ?string
Namespace
MMO\core\shell
$messagestringthe message to display
$options = nullnull | arrayread
$default = nullnull | stringthe default value to return
returnsnull | stringthe command. null if the user has pressed escape. empty string if nothing was typed
$name = ask('What is your name?', null, 'Anonymous'); // e.g. 'Marc' if the user typed "Marc"
Call graph
function

characters

shell.php:217

Split a text into the characters a terminal shows, one column each: a character is one whatever its bytes (UTF-8), and a letter followed by a combining accent is one character too. A text that is not valid UTF-8 is split into bytes.

function characters(string $text): array
Namespace
MMO\core\shell
The text must hold no ANSI sequence: its bytes would be counted as characters ([`splitANSI`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#splitansi)).
$textstring
returnsarray
characters('déjà') === ['d', 'é', 'j', 'à']
Call graph
function

choose

shell.php:1224

Ask for one of a few choices, listed one per line and numbered, with what each one means.

function choose(string $message, array $options, string|int|null $default = null): string|int|null
Namespace
MMO\core\shell
The answer is a number, a key, or the start of a single key; ENTER answers the default. Anything else is refused, and asked again when there is someone at a terminal to answer ([`prompt`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#prompt)).
$messagestringthe question
$optionsarraykey => what choosing it means, or a list of keys
$default = nullstring | int | nullthe key ENTER answers
returnsstring | int | nullthe chosen key. null when there was no valid answer (prompt)
choose('How does it let you in?', ['agent' => 'your ssh agent holds the key', 'key' => 'a key file'], 'agent'); // - How does it let you in? // 1) agent your ssh agent holds the key // 2) key a key file // [agent] > // returns 'key' when the user types "2", "key" or "k"
Call graph
function

colorCard

shell.php:2037

Print a table with a preview of every SHELL_* color/style constant. Useful to check what your terminal supports.

function colorCard(): string
Namespace
MMO\core\shell
returnsstring
echo colorCard(); // prints a table with one row per SHELL_* color, each showing a small colored swatch
Call graph

Uses (1)

function

columns

shell.php:1460

Attempt to get the number of columns of the current terminal

function columns(): int|false
Namespace
MMO\core\shell
returnsint | falsefalse if it cannot detect the number of columns
columns(); // e.g. 120 in a 120-column-wide terminal. false when run outside of a real tty (no $TERM)
Call graph
function

commandExists

shell.php:412

Tells if a command is available and executable on the current system

function commandExists(string $command): bool
Namespace
MMO\core\shell
$commandstring
returnsbool
commandExists('php') === truecommandExists('this-command-does-not-exist') === false
Call graph

Uses (1)

function

confirm

shell.php:1141

Ask the user for a confirmation

function confirm(string $message, bool $default = true): ?bool
Namespace
MMO\core\shell
$messagestring
$default = trueboolwhat ENTER answers, shown in brackets. Make it false when a yes is hard to undo
returnsnull | booltrue/false for yes/no, null if the user pressed ESC or nobody answered (read)
$ok = confirm('Delete this file?'); // e.g. true if the user typed "y" (or pressed ENTER, since "y" is the default)$ok = confirm('Overwrite it?', false); // false when the user just presses ENTER
Call graph
function

diff

shell.php:1937

The differences between two texts, line by line, the way diff -u shows them: a removed line in red after a -, an added one in green after a +, each change among a few unchanged lines around it, and before each group an @@ line saying where it is. Ready to print, so that a change to a file is read before it is made.

function diff(string $old, string $new, int $context = 3): string
Namespace
MMO\core\shell
$oldstring
$newstring
$context = 3inthow many unchanged lines to show around a change
returnsstring'' when both texts have the same lines
echo diff("a\nb\nc\n", "a\nB\nc\n"); // @@ -1,3 +1,3 @@ // a // -b // +B // c
function

error

shell.php:1371

Print an error message, prefixed with '!! ' in red. $message is rendered through

function error(string $message, array $context = []): void
Namespace
MMO\core\shell
See
printf, so {key} placeholders are replaced with $context values.
$messagestring
$context = []array
returnsvoid
error('Connection to {host} failed', ['host' => 'db01']); // prints "!! Connection to db01 failed" in red
Call graph
function

escape

shell.php:1712

Escapes a string to be used as an argument and qotes it.

function escape( ?string $arg, bool $force = false, bool $isWin = MMO\core\shell\IS_WINDOWS ): string
Namespace
MMO\core\shell
If it is only one word, it is not quoted Set force = true to force quote SECURITY NOTE: on POSIX (`$isWin = false`), this now wraps in SINGLE quotes with `'\''`-style escaping of any embedded single quote (the same technique `escapeshellarg()` uses) -- it used to wrap in double quotes instead, which does NOT stop a POSIX shell from still interpreting `$(...)`/backtick command substitution (and some backslash escapes) inside the "escaped" value. This was a real, confirmed command-injection hole: `escape("hello\$(touch /tmp/pwned)world")` used to return `"hello$(touch /tmp/pwned)world"`, and running that through a real shell executed the injected command -- the double-quote wrapping provided no protection at all. Single-quote wrapping is the only reliable way to fully neutralize shell interpretation of the escaped value's content. The Windows (`$isWin = true`) path is unchanged: cmd.exe has no `$(...)`/backtick substitution to begin with (that's a POSIX shell feature), so it wasn't exposed to this specific vulnerability, and cmd.exe's own quoting rules don't support POSIX-style single-quote escaping at all.
$argnull | stringthe argument that will be escaped
$force = falseboolif false won't quote the argument unless it needs to.
$isWin = MMO\core\shell\IS_WINDOWSboolif true, escape for windows command line. Else escape for shell
returnsstring
escape('simple') === 'simple' // no special characters: left untouched, not quotedescape('has space') === "'has space'" // needs quoting because of the spaceescape(null) === '""' // null/empty is always quoted, so it survives as an empty argumentescape('simple', true) === "'simple'" // $force=true always quotes, even when not strictly neededescape("it's") === "'it'\\''s'" // an embedded single quote is closed, escaped, and reopenedescape('$(touch /tmp/x)') === "'\$(touch /tmp/x)'" // wrapped in single quotes: inert, not executed
Call graph
function

evalColors

shell.php:372

Used to put shell colors directly into a text Any SHELL_* colors must be in brackets to be replaced

function evalColors(string $text): string
Namespace
MMO\core\shell
$textstring
returnsstring
`{SHELL_RED}this is a red text{SHELL_FLUSH}`
function

exec

shell.php:1772

Execute a command through php exec, serializing the parameters passed

function exec(string $command, bool $throwException = true, ?int &$exitCode = null): string
Namespace
MMO\core\shell
$commandstringthe command to execute
$throwException = trueboolif true, will throw eRuntime if exit code > 0
$exitCode = nullnull | intthe returned exit code
returnsstringthe output of the command
exec('echo hello') === 'hello'exec('exit 1', false, $exitCode); // returns '' and sets $exitCode = 1, instead of throwing
Call graph
function

execInBackground

shell.php:1786

Launch a command in the background (fire and forget), serializing the parameters passed

function execInBackground(string $command, bool $isWin = MMO\core\shell\IS_WINDOWS): void
Namespace
MMO\core\shell
$commandstringthe command to execute
$isWin = MMO\core\shell\IS_WINDOWSboolforce the execution in WINDOWS or SHELL
returnsvoid
execInBackground('php long-running-task.php'); // returns immediately, the script keeps running detached
function

explain

shell.php:1416

Print a paragraph of explanation, indented and wrapped to the terminal (100 columns at most), so that it reads as prose rather than as lines running off the screen.

function explain(string $text, int $indent = 2): void
Namespace
MMO\core\shell
Text between backticks -- a command, a file, a key -- is highlighted (the backticks stay where there is no color). Line breaks are kept. A line starting with `$ ` is a command to copy and is never wrapped; the lines a list item wraps onto start under its text, not under its bullet (`- `, `* `, `1. `).
$textstring
$indent = 2intspaces before every line
returnsvoid
explain('Load your key once per session with `ssh-add ~/.ssh/id_ed25519`.'); // prints " Load your key once per session with ssh-add ~/.ssh/id_ed25519.", the command in cyan
Call graph
function

getCursor

shell.php:575

Get the current position of the terminal cursor

function getCursor(): ?array
Namespace
MMO\core\shell
returnsnull | arrayint, 1: int}|null [line, column]. null if the terminal did not answer the position report
[$line, $col] = getCursor()??[null, null]; // e.g. [12, 1] when the cursor is at the start of line 12
Call graph
function

getEnv

shell.php:1563

Alias to getenv(). Return null instead of false in case value is not set in the env

function getEnv(?string $key = null): array|string|null
Namespace
MMO\core\shell
$key = nullnull | stringif null, return every env variable
returnsarray | string | null
getEnv('PATH'); // e.g. '/usr/local/bin:/usr/bin:/bin'getEnv('THIS_VAR_IS_NOT_SET') === null
Call graph
function

getInput

shell.php:470

The stream user input is read from.

function getInput()
Namespace
MMO\core\shell
returnsthe one given to setInput, else STDIN
fgets(getInput()); // the next line the user typed, or the next line of the stream given to setInput()
Call graph
function

heading

shell.php:1398

Print a title: set apart from what comes before it by a blank line, and ruled across the terminal (100 columns at most) -- how the steps of a long run are told apart at a glance.

function heading(string $title, string $subtitle = ''): void
Namespace
MMO\core\shell
$titlestring
$subtitle = ''stringprinted after it, dimmed
returnsvoid
heading('Step 2 of 7: servers', 'the machines targets live on'); // (a blank line) // Step 2 of 7: servers the machines targets live on // ─────────────────────────────────────────────────── (across the terminal)
Call graph

Uses (1)

function

hideCursor

shell.php:191
function hideCursor(): void
Namespace
MMO\core\shell
returnsvoid
function

isInteractive

shell.php:484

Tells if the answers are typed by someone at a terminal, rather than read from a pipe, a file or a stream given to setInput. Only a terminal has keys: without one, input is read a whole line at a time, and an answer that is not valid cannot be typed again.

function isInteractive(): bool
Namespace
MMO\core\shell
returnsbool
isInteractive(); // true in a terminal, false for `echo y | php script.php`
Call graph
function

isRunning

shell.php:426

Tells if a process with the given PID is currently running.

function isRunning(string|int $pid): bool
Namespace
MMO\core\shell
$pidstring | int
returnsbool
isRunning(getmypid()) === true // the current process is always runningisRunning(999999) === false // (assuming no process has this pid)
Call graph
function

isTty

shell.php:1538

Tells if the current terminal is a tty (native terminal device)

function isTty(): bool
Namespace
MMO\core\shell
returnsbool
isTty(); // e.g. true when run in an interactive shell, false when run non-interactively (e.g. a cron job)
function

lengthANSI

shell.php:229

Get length of a text, removing ansi sequences: a character is counted as one whatever its bytes (UTF-8).

function lengthANSI(string $text): int
Namespace
MMO\core\shell
$textstring
returnsint
lengthANSI("\033[0;31mHello\033[0m") === 5 // the escape sequences are not countedlengthANSI('● déjà…') === 7 // characters, not bytes
Call graph
function

lines

shell.php:1473

Attempt to get the number of lines of the current terminal

function lines(): int|false
Namespace
MMO\core\shell
returnsint | falsefalse if it cannot detect the number of lines
lines(); // e.g. 30 in a 30-line-tall terminal. false when run outside of a real tty (no $TERM)
Call graph
function

moveBack

shell.php:187
function moveBack(int $count = 1): void
Namespace
MMO\core\shell
$count = 1int
returnsvoid
Call graph

Used by (2)

function

moveCursorCol

shell.php:190
function moveCursorCol(int $count): void
Namespace
MMO\core\shell
$countint
returnsvoid
Call graph

Used by (2)

function

moveCursorLine

shell.php:189
function moveCursorLine(int $count): void
Namespace
MMO\core\shell
$countint
returnsvoid
Call graph

Used by (1)

function

padANSI

shell.php:305

Pad string ingoring ANSI sequences

function padANSI( string $text, int $length, string $pad_string = ' ', int $pad_type = MMO\core\shell\STR_PAD_RIGHT ): string
Namespace
MMO\core\shell
$textstring
$lengthint
$pad_string = ' 'string
$pad_type = MMO\core\shell\STR_PAD_RIGHTint
returnsstring
padANSI('AB', 5, '.') === 'AB...' // STR_PAD_RIGHT (default)padANSI('AB', 5, '.', STR_PAD_LEFT) === '...AB'padANSI('AB', 6, '.', STR_PAD_BOTH) === '..AB..'padANSI('●', 3, '·') === '●··' // characters, not bytes
Call graph
function

parse

shell.php:1646

Parse a command line This command line option parser supports any combination of three types of options [single character options (-a -b or -ab or -c -d=dog or -cd=dog), long options (--foo or --bar=baz) and arguments (arg1 arg2)]

function parse(array|string $cmd): array
Namespace
MMO\core\shell
Author
Marc Mouret and Patrick Fisher <patrick@pwfisher.com>
$cmdarray | stringthe command
returnsarray
$ php test.php --foo --bar=baz --spam eggs ["foo"] => true ["bar"] => "baz" ["spam"] => true [0] => "eggs"$ php test.php -abc foo ["a"] => true ["b"] => true ["c"] => true [0] => "foo"$ php test.php arg1 arg2 arg3 [0] => "arg1" [1] => "arg2" [2] => "arg3"$ php test.php plain-arg --foo --bar=baz --funny="spam=eggs" --also-funny=spam=eggs 'plain arg 2' -abc -k=value "plain arg 3" --s="original" --s='overwrite' --s [0] => "plain-arg" ["foo"] => true ["bar"] => "baz" ["funny"] => "spam=eggs" ["also-funny"]=> "spam=eggs" [1] => "plain arg 2" ["a"] => true ["b"] => true ["c"] => true ["k"] => "value" [2] => "plain arg 3" ["s"] => "overwrite"
Call graph
function

printInRect

shell.php:2087

Print lines in a rectangle and returns text's positions in the rectangle This function is safe with ANSI sequences

function printInRect( array $lines, ?int $maxColCount = null, ?int $maxLineCount = null, string $colDelimiter = ' ' ): array
Namespace
MMO\core\shell
$linesarraya list of texts
$maxColCount = nullnull | intnumber max of columns
$maxLineCount = nullnull | intnumber max of lines
$colDelimiter = ' 'stringdelimiter between columns
returnsarray[ -1: [lineCount, lineLength, colCount, colLength], text index => [[line1, column1], [line2, column2], ...] ]
throwsif the texts cannot fit in the rectangle -- nothing is printed then (select)
printInRect(['Apple', 'Banana', 'Cherry', 'Date'], 12, 10); // prints, one item per line (they don't fit side by side in 12 columns): // Apple // Banana // Cherry // Date // and returns [-1 => [4, 6, 1, 8], 0 => [[0, 0]], 1 => [[1, 0]], 2 => [[2, 0]], 3 => [[3, 0]]]
Call graph
function

progress

shell.php:1805

Print and redraw an in-place progress bar. Call repeatedly with an increasing $current to update it.

function progress(int $current, int $total, string $label = '', int $width = 30): void
Namespace
MMO\core\shell
$currentintthe current progress
$totalintthe total (100%) progress
$label = ''stringan optional label printed after the bar
$width = 30intthe width (in characters) of the bar itself
returnsvoid
for ($i = 0; $i <= 10; $i++) {progress($i, 10, 'downloading...');} // redraws in place: "[███████████████░░░░░░░░░░░░░░░] 50% downloading..." (at $i=5), reaching 100% at $i=10
Call graph

Uses (1)

function

prompt

shell.php:1176

Ask for a value, showing the one ENTER keeps, until the answer is a valid one.

function prompt(string $message, ?string $default = null, ?callable $validate = null): ?string
Namespace
MMO\core\shell
`-` alone answers with nothing: it is how an optional value that has a default is cleared. Without a terminal ([`isInteractive`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#isinteractive)) an invalid answer is not asked again -- nobody is there to correct it, and the next line answers another question -- so it ends the question the way the end of the input does. At a terminal, only what is typed once the question is on screen answers it ([`read`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#read)).
$messagestringthe question
$default = nullnull | stringwhat ENTER answers, shown in brackets
$validate = nullnull | callablefn(string $answer): ?string -- null when the answer is fine, otherwise why it is not, shown before the question is asked again
returnsnull | stringthe answer, trimmed: '' for -, or for ENTER when there is no default. null when there was no valid answer: the input ended (Ctrl+D), or an invalid one came from something that is not a terminal
prompt('Project name', 'acme.portal'); // 'acme.portal' when the user just presses ENTERprompt('Port', '22', fn(string $port) => ctype_digit($port)? null : 'a number, e.g. 22');
Call graph
function

promptList

shell.php:1199

Ask for a list of values, separated by commas.

function promptList(string $message, array $default = [], ?callable $validate = null): ?array
Namespace
MMO\core\shell
ENTER keeps the list shown in brackets, `-` alone answers an empty list.
$messagestringthe question
$default = []arraywhat ENTER answers
$validate = nullnull | callablefn(array $answer): ?string, as for prompt
returnsnull | arraythe values, trimmed, without empty ones. null when there was no valid answer (prompt)
promptList('Tags', ['staging']); // ['staging', 'eu'] when the user types "staging, eu"
Call graph

Uses (1)

function

protectShellBuffering

shell.php:518

Install a SIGINT/SIGTERM safety net so the terminal is not left in raw/no-echo mode if the process is interrupted (e.g. Ctrl+C) while shell buffering is stopped. Without this, an interrupted read()/select()/ readCallback() leaves the user's terminal broken (no echo) since finally blocks never run on a signal.

function protectShellBuffering(): void
Namespace
MMO\core\shell
Installed automatically (and only once) by [`stopShellBuffering`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#stopshellbuffering). No-op if the pcntl extension is unavailable.
returnsvoid
protectShellBuffering(); // usually not called directly: stopShellBuffering() does this for you
Call graph
function

read

shell.php:705

Read a command from the user input.

function read(?array $options = null, ?string $default = null): ?string
Namespace
MMO\core\shell
Available key bindings: ESC: return null Tab: list available commands At a terminal the answer is typed key by key, and an option is taken the moment it is typed, without ENTER. Only keys typed once the prompt is on screen count: those typed before it -- the ENTER after a one-letter answer to the previous question -- are dropped, as are those left once the answer is complete. Keys that arrive together (a paste, fast typing, keys sent in one go over ssh) are taken one at a time, an escape sequence (an arrow) whole. Without a terminal (a pipe, a file, a stream given to [`setInput`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#setinput)) there are no keys, only lines: the next line is the answer, matched against $options exactly or by the start of a single one of them -- and, when every option is one letter, by its first letter, so `yes` answers `y`. A line that matches none is refused rather than asked for again: nobody is there to type it again, and the next line answers another question.
$options = nullnull | arraypossible options: if given, they are auto-completed as the user types and can be navigated with the up/down arrow keys
$default = nullnull | stringreturned if the user presses ENTER without typing anything. Shown in brackets
returnsnull | stringthe command. null if the user has pressed escape or the input has ended -- nobody answered, so neither is an answer, the default included -- or, without a terminal, if the line matched none of $options. empty string if nothing was typed
$cmd = read(['start', 'stop', 'status'], 'status'); // e.g. $cmd === 'start' if the user typed "start"
Call graph
function

readAnswer

internalshell.php:1262

Show what ENTER answers, then read the answer.

function readAnswer(?string $default): ?string
Namespace
MMO\core\shell
At a terminal, what was typed before the question is dropped first: it is no answer to it ([`read`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#read)).
$defaultnull | string
returnsnull | stringthe answer, trimmed: $default for ENTER alone, '' for - alone. null when the input has ended
readAnswer('22'); // prints " [22] > ", then returns '22' for an empty line
Call graph
function

readCallback

shell.php:599

Read every key press by the user on the command line (as opposed to fgets which waits on return key)

function readCallback(callable $fn, bool $echo = true): string
Namespace
MMO\core\shell
$fncallable($char, $current_user_input): string|false. The closure SHOULD return the new user input. The closure MUST return false to stop the user input or a string started with \0
$echo = trueboolif false, no characters are printed on the screen
returnsstringthe complete user input
//reads digits only, stops (and discards the last keypress) as soon as 4 digits have been typed readCallback(function (string $c, string $text) { if (!ctype_digit($c)) {return $text;}// ignore non-digit keys $text .= $c; return (strlen($text) >= 4)? ("\0" . $text) : $text;// "\0" prefix stops reading once complete });
Call graph
function

readKeys

shell.php:672

Wait for the user to press a key, then read it with every key that came with it -- a paste, fast typing, keys sent in one go over ssh -- one string for each: a character, or a whole escape sequence (the up arrow is "\e[A").

function readKeys(): array
Namespace
MMO\core\shell
At a terminal out of line buffering ([`stopShellBuffering`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#stopshellbuffering)): in it, nothing comes before ENTER.
returnsarraythe keys, in the order they were typed. empty when the input has ended
stopShellBuffering(); $keys = readKeys(); // ['y', "\n"] for `y` and ENTER typed in one go, ["\e[A"] for the up arrow restoreShellBuffering();
Call graph

Used by (1)

function

readLine

shell.php:497

Read one line of user input, without its line ending.

function readLine(bool $echo = true): ?string
Namespace
MMO\core\shell
At a terminal the line is typed and corrected as the terminal allows (backspace, paste) and ENTER ends it. Anywhere else it is the next line of the input, and it is echoed, so that a transcript shows each answer beside its question.
$echo = trueboolfalse to never print the line (a secret)
returnsnull | stringthe line. null when the input has ended (Ctrl+D at a terminal)
$name = readLine(); // 'marc' after the user typed "marc" then ENTER
Call graph
function

readOption

internalshell.php:853

The half of read that has no terminal to read keys from: the next line of the input is the answer.

function readOption(?array $options, ?string $default): ?string
Namespace
MMO\core\shell
$optionsnull | arraywhat read() was given, sorted
$defaultnull | string
returnsnull | stringthe answer, null when the input has ended or the line matches none of $options
readOption(['n', 'y'], 'y'); // 'y' for a line "yes", or an empty line
Call graph

Uses (1)

Used by (1)

function

readPending

shell.php:635

Take what the user has typed that nothing has read yet, without waiting for more -- or, given a timeout, waiting that long at most for a first key. Every question drops it before asking (read, prompt, choose,

function readPending(float $timeout = 0.0): string
Namespace
MMO\core\shell
See
readSecret): keys typed before a question is on screen are no answer to it. At a terminal only: nothing else can be asked whether something is waiting, and gives ''. Out of line buffering (stopShellBuffering) that is every key typed; in it, the lines ENTER has ended.
$timeout = 0.0floatseconds to wait for a first key when none is waiting. 0: not at all
returnsstringwhat was typed, '' if nothing was
stopShellBuffering(); readPending(); // e.g. "\n": the ENTER typed after a one-letter answer, which needed none restoreShellBuffering();
Call graph
function

readSecret

shell.php:1293

Ask for a secret (e.g. a password) from the user. The typed characters are never echoed by the terminal itself.

function readSecret(string $message, ?string $mask = '*'): ?string
Namespace
MMO\core\shell
At a terminal, what was typed before the question is on screen is dropped: it is no answer to it ([`read`](https://mmoframework.fr/documentation/mmo.core/php/shell.md#read)).
$messagestringthe message to display
$mask = '*'null | stringa single character to display in place of each typed character, for feedback. null to display nothing at all.
returnsnull | stringthe secret typed by the user. null when the input ended before ENTER: half a secret is not one
$password = readSecret('Password'); // the user sees "- Password > ****" as they type, $password holds the real value$password = readSecret('Password', null); // nothing at all is echoed as the user types
Call graph
function

removeANSI

shell.php:204

Strip ANSI escape sequences (colors, cursor movement, ...) from a text, leaving only the visible characters.

function removeANSI(string $text): string
Namespace
MMO\core\shell
$textstring
returnsstring
removeANSI("\033[0;31mHello\033[0m") === 'Hello'
Call graph
function

restoreShellBuffering

shell.php:563

Undo one call to stopShellBuffering. Calls nest: buffering is only actually restored once every stopShellBuffering() call has a matching restoreShellBuffering() call.

function restoreShellBuffering(): bool
Namespace
MMO\core\shell
returnsboolfalse if buffering was already fully restored (nothing to do), or if stty itself failed
restoreShellBuffering(); // see stopShellBuffering() for a full example
Call graph
function

say

shell.php:1347

Print an informational message, prefixed with '- ' in purple. $message is rendered through

function say(string $message, array $context = []): void
Namespace
MMO\core\shell
See
printf, so {key} placeholders are replaced with $context values.
$messagestring
$context = []array
returnsvoid
say('Deploy {status}', ['status' => 'complete']); // prints "- Deploy complete" in purple
Call graph
function

select

shell.php:891

Print a menu of choices and return the keys of the selected options

function select( string $title, array $options, ?int $min = null, ?int $max = null, array $selection = [] ): ?array
Namespace
MMO\core\shell
$titlestringthe title of the menu
$optionsarray{value => text} or [...value]
$min = nullnull | intminimum number of options the user must select before ENTER is accepted
$max = nullnull | intmaximum number of options that can be selected; selection stops automatically once reached. 1 is a single choice (menu): selecting an option replaces the one selected before, and ends it
$selection = []arraythe keys of $options that start out pre-selected
returnsnull | arraythe selected keys of $options. null if escape was pressed, or if the options do not fit the terminal and the input has ended
$picked = select('Pick fruits', ['apple' => 'Apple', 'pear' => 'Pear'], 1, 2); // e.g. ['apple'] if the user selected only Apple then pressed ENTER
Call graph
function

serialize

shell.php:1739

Serialize the command All parameters with no string key (plain args) are left untouched (no escape).

function serialize( array $cmd, string $long = '=', string $short = '=', bool $isWin = MMO\core\shell\IS_WINDOWS ): string
Namespace
MMO\core\shell
The rest is escaped.
$cmdarraythe command arguments
$long = '='stringthe separator for long argument (--xxx)
$short = '='stringthe separator for short argument (-x)
$isWin = MMO\core\shell\IS_WINDOWSboolescape for windows command line if true, else escape for shell
returnsstring
serialize(['foo' => true, 'bar' => 'baz', 0 => 'plain-arg', 'a' => true]) === '--foo --bar=baz plain-arg -a' // the round-trip counterpart of @see parse
Call graph
function

setCursor

shell.php:188
function setCursor(int $col, int $line = 0): void
Namespace
MMO\core\shell
$colint
$line = 0int
returnsvoid
function

setInput

shell.php:460

Read the user's answers from another stream than STDIN: a file of answers, or -- in a test -- a php://memory stream written beforehand. Every function reading user input reads from it (read, readLine,

function setInput($stream): void
Namespace
MMO\core\shell
See
prompt, choose, confirm, readSecret, readCallback, select, menu). select() and menu() read keys from it rather than lines, one read per key as a terminal gives them: a php://memory stream holding several keys hands them over four bytes at a time, and they run together.
$streamnull to read from STDIN again
returnsvoid
$answers = fopen('php://memory', 'w+'); fwrite($answers, "y\nmarc\n"); rewind($answers); setInput($answers); confirm('Continue?'); // true, read from $answers prompt('Your name'); // 'marc' setInput(null); // back to STDIN
function

showCursor

shell.php:192
function showCursor(): void
Namespace
MMO\core\shell
returnsvoid
function

sigchildEnabled

shell.php:1503

Tells if PHP has been compiled with the '--enable-sigchild' option.

function sigchildEnabled(): bool
Namespace
MMO\core\shell
returnsbool
sigchildEnabled(); // e.g. false on most standard PHP builds
Call graph
function

split

shell.php:1595

Split string on space, except for quoted words

function split(string $cmd): array
Namespace
MMO\core\shell
$cmdstring
returnsarray
'plain-arg plain arg --foo --bar=baz --funny="spam=egg\\" s" --also-funny=spam=eggs \'plain arg 2\' -abc -k=value "plain arg 3" --s="original" --s=\'marc\\\'s good\' --s' [0] plain-arg [1] plain [2] arg [3] --foo [4] --bar=baz [5] --funny= [6] "spam=egg\"·s" [7] --also-funny=spam=eggs [8] 'plain·arg·2' [9] -abc [10] -k=value [11] "plain·arg·3" [12] --s= [13] "original" [14] --s= [15] 'marc\'s·good' [16] --s
Call graph

Used by (1)

function

splitANSI

shell.php:243

Split text ignoring ANSI sequences

function splitANSI(string $text, int $length, ?int $max = null): array
Namespace
MMO\core\shell
$textstring
$lengthint
$max = nullnull | intmaximum number of splits
returnsarray
splitANSI("\033[0;31mHelloWorld\033[0m", 5) === ["\033[0;31mHello", "World\033[0m"] // split every 5 visible characters, the color codes stay attached // to whichever chunk they were adjacent to
Call graph
function

stopShellBuffering

shell.php:548

Stop shell line buffering so you can capture direct input from user, without waiting for a flush (ENTER)

function stopShellBuffering(bool $echo = false): bool
Namespace
MMO\core\shell
$echo = falseboolif false, no characters are printed on the screen
returnsboolif false, shell could not be stopped from buffering -- or there is no terminal to stop (isInteractive).
stopShellBuffering(); // now fgetc(STDIN) returns as soon as a key is pressed, without waiting for ENTER $c = fgetc(STDIN); restoreShellBuffering(); // always pair with a matching restoreShellBuffering() call, e.g. in a finally block
Call graph
function

substrANSI

shell.php:281

substr() ignoring ANSI sequences: offset and length count visible characters, whatever their bytes (UTF-8).

function substrANSI(string $text, int $offset, ?int $length = null): string
Namespace
MMO\core\shell
$textstring
$offsetint
$length = nullnull | int
returnsstring
substrANSI("\033[1mdéjà vu\033[0m", 0, 4) === "\033[1mdéjà" // the color codes stay attached
Call graph

Used by (1)

function

success

shell.php:1383

Print what went right, prefixed with '✔ ' in green. $message is rendered through

function success(string $message, array $context = []): void
Namespace
MMO\core\shell
See
printf, so {key} placeholders are replaced with $context values.
$messagestring
$context = []array
returnsvoid
success('wrote {file}', ['file' => 'deploy.json']); // prints "✔ wrote deploy.json" in green
Call graph

Uses (1)

function

supportColor

shell.php:1486

Tells if the current output supports ANSI colors/escape sequences.

function supportColor(): bool
Namespace
MMO\core\shell
Can be forced by defining SHELL_ENABLE_COLORS or setting the SHELL_ENABLE_COLORS env variable.
returnsbool
supportColor(); // e.g. true when run interactively in a real terminal, false when output is piped/redirected
Call graph

Uses (1)

Used by (2)

function

supportPty

shell.php:1518

Tells if the current terminal support pty (pseudo terminal device).

function supportPty(): bool
Namespace
MMO\core\shell
returnsbool
supportPty(); // e.g. true on Linux/macOS, always false on Windows
Call graph
function

table

shell.php:1844

Make a table text WARNING: to make sure columns are ordered correctly, make sure last item has all the columns in the right order

function table(array $data, string $title = '', ?int $size = null): string
Namespace
MMO\core\shell
$dataarray(array(col1 => AA, col2 => AB), array(col1 => BA, col2 => BB)). Last item must have all the columns
$title = ''stringtable's title
$size = nullnull | inttable's size. use null to fit to content size
returnsstring
echo table([['col1' => 'AA', 'col2' => 'AB'], ['col1' => 'BA', 'col2' => 'BB']], 'MyTitle'); // ┌ MyTitle ┐ // ├────┼────┤ // ├col1│col2┤ // ├────┼────┤ // ├ AA │ AB ┤ // ├────┼────┤ // ├ BA │ BB ┤ // ├────┼────┤ // └────┴────┘
Call graph
function

warning

shell.php:1359

Print a warning message, prefixed with '! ' in brown/yellow. $message is rendered through

function warning(string $message, array $context = []): void
Namespace
MMO\core\shell
See
printf, so {key} placeholders are replaced with $context values.
$messagestring
$context = []array
returnsvoid
warning('Disk usage at {pct}%', ['pct' => 90]); // prints "! Disk usage at 90%" in brown
Call graph

Uses (1)

function

windowsConsoleSize

internalshell.php:1444

Parse mode con's output (windows only).

function windowsConsoleSize(): ?array
Namespace
MMO\core\shell
`mode con` always reports lines then columns, in that fixed order, regardless of the system's locale.
returnsnull | arrayint, columns: int}|null null if it cannot be detected
windowsConsoleSize(); // e.g. ['lines' => 30, 'columns' => 120] on a 120x30 windows console
Call graph

Used by (2)

function

wrapANSI

shell.php:336

Wrap a text so that no line is wider than $width visible characters -- an ANSI sequence takes no room, and a character is counted as one whatever its bytes (UTF-8).

function wrapANSI(string $text, int $width, string $break = MMO\core\shell\PHP_EOL): string
Namespace
MMO\core\shell
Lines break between words. A word wider than $width is not cut but gets a line of its own: a path or a url cut in two cannot be copied any more. The text's own line breaks are kept, and the indentation a line starts with is repeated on the lines it wraps onto.
$textstring
$widthint
$break = MMO\core\shell\PHP_EOLstringwhat ends each line
returnsstring
wrapANSI('the quick brown fox', 10) === "the quick\nbrown fox"wrapANSI("\033[1mthe\033[0m quick", 9) === "\033[1mthe\033[0m quick" // 9 visible characters: one line
Call graph

Used by (1)

function

writeAt

shell.php:193
function writeAt(int $col, int $line, string $text): void
Namespace
MMO\core\shell
$colint
$lineint
$textstring
returnsvoid
Call graph

Used by (1)