4 Commits

5 changed files with 87 additions and 16 deletions

View File

@ -16,10 +16,6 @@ Major changes:
* The event `Shell::EVT_BAD_COMMAND` will be fired if a command can
not be found, assuming `Context->execute()` does not accept the
command. (see *examples/commandevents.php*)
* When calling `Context->addCommand()` you can now use both `help`
and `descr` as the last argument to provide the description text
for the command. This change is intended to make `addCommand` and
the doccomment `@descr` more similar.
New features:

View File

@ -30,7 +30,7 @@ $myShell->setPrompt("test>");
$ctx = $myShell->createContext("root");
$ctx->addCommand("hello", function () {
echo "Hello World!\n";
}, [ 'descr'=>'Say hello' ]);
}, [ 'help'=>'Say hello' ]);
// Run the shell
$myShell->run();

31
examples/input.php Normal file
View File

@ -0,0 +1,31 @@
<?php
/*
* This example demonstrates how to use events to catch commands that
* have not been handled by any context or builtin.
*
*/
require_once __DIR__."/../vendor/autoload.php";
use NoccyLabs\Shell\Shell;
use NoccyLabs\Shell\Style;
use NoccyLabs\Shell\Context;
$myShell = new Shell();
// Set the initial prompt, not really needed.
$myShell->setPrompt("test>");
// Create an anonymous context and add a command
$ctx = $myShell->createContext("root");
$ctx->addCommand("hello", function () use ($myShell) {
$myShell->getInput("What is your name?", function ($name) use ($myShell) {
echo "Hello, {$name}\n";
$myShell->getInput("Who is your daddy and what does he do?", function ($daddy) {
echo "{$daddy}? Oookay...\n";
});
});
});
// Run the shell
$myShell->run();

View File

@ -132,7 +132,6 @@ class Context
$info = $this->commandInfo[$command];
$args = array_key_exists("args",$info)?$info['args']:"";
$help = array_key_exists("help",$info)?$info['help']:"";
$help = $help?:(array_key_exists("descr",$info)?$info['descr']:"");
$ret[trim("{$command} {$args}")] = $help;
}
return $ret;

View File

@ -54,6 +54,18 @@ class Shell
* @var Style The style applied to the input text
*/
protected $input_style = null;
/**
* @var callable The callback to pass the input on to
*/
protected $input_callback = null;
/**
* @var string Question prompt for getInput()
*/
protected $input_prompt = null;
/**
* @var string The prompt before changing to $input_prompt
*/
protected $input_last_prompt = null;
/**
* Constructor
@ -395,19 +407,27 @@ class Shell
}
}
ksort($ghelp);
printf("Commands in current context:\n");
$_ = function($command,$args,$info) {
printf(" \e[97m%s\e[0m \e[90;3m%s\e[0m - \e[36m%s\e[0m\n", $command, $args, $info);
};
printf("\e[1mCommands:\e[0m\n");
foreach ($help as $command=>$info) {
printf(" %-20s %s\n", $command, $info);
if (strpos($command," ")!==false) {
list($command,$args) = explode(" ",$command,2);
} else $args=null;
$_($command, $args,$info);
}
if (count($ghelp)) {
printf("\nImported from parent contexts:\n");
foreach ($ghelp as $command=>$info) {
printf(" %-20s %s\n", $command, $info);
}
printf("\n\e[0mCommands from parent contexts:\e[0m\n");
if (strpos($command," ")!==false) {
list($command,$args) = explode(" ",$command,2);
} else $args=null;
$_($command, $args,$info);
}
printf("\nGlobal commands:\n");
printf(" %-20s %s\n", "exit", "Leave the shell");
printf(" %-20s %s\n", "..", "Discard the current context and go to parent");
$_("exit", null, "Leave the shell");
$_(".", null, "Show the context tree");
$_("..", null, "Discard the current context and go to parent");
break;
case 'exit':
$this->stop();
@ -532,6 +552,31 @@ class Shell
return $event;
}
public function getInput($prompt, callable $callback)
{
$this->addListener(Shell::EVT_UPDATE_PROMPT, [ $this, "onInputPrompt" ], $prompt);
$this->addListener(Shell::EVT_BEFORE_COMMAND, [ $this, "onInputHandler" ], $this->prompt, $callback);
}
public function onInputPrompt(Event $e, $prompt)
{
$this->setPrompt($prompt);
$e->stopPropagation();
$this->removeListener(Shell::EVT_UPDATE_PROMPT, [ $this, "onInputPrompt" ], $prompt);
}
public function onInputHandler(Event $e, $last_prompt, $callback)
{
// Restore the prompt
$this->setPrompt($last_prompt);
// Remove the listeners and compose the result string
$this->removeListener(Shell::EVT_BEFORE_COMMAND, [ $this, "onInputHandler" ], $last_prompt, $callback);
$input = trim($e->command." ".join(" ",$e->args));
$e->stopPropagation();
// Call the callback
call_user_func($callback, $input);
}
/**
* Stop the shell; calling this method will cause the main run() to return.
*