mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-01 07:43:03 +00:00
FormattedCommandAlias: match placeholders using regex
This commit is contained in:
parent
f4d71d0b48
commit
a353872327
@ -26,12 +26,20 @@ namespace pocketmine\command;
|
|||||||
use pocketmine\Server;
|
use pocketmine\Server;
|
||||||
use pocketmine\utils\TextFormat;
|
use pocketmine\utils\TextFormat;
|
||||||
use function count;
|
use function count;
|
||||||
use function ord;
|
use function preg_match;
|
||||||
use function strlen;
|
use function strlen;
|
||||||
use function strpos;
|
use function strpos;
|
||||||
use function substr;
|
use function substr;
|
||||||
|
|
||||||
class FormattedCommandAlias extends Command{
|
class FormattedCommandAlias extends Command{
|
||||||
|
/**
|
||||||
|
* - matches a $
|
||||||
|
* - captures an optional second $ to indicate required/optional
|
||||||
|
* - captures a series of digits which don't start with a 0
|
||||||
|
* - captures an optional - to indicate variadic
|
||||||
|
*/
|
||||||
|
private const FORMAT_STRING_REGEX = '/\G\$(\$)?((?!0)+\d+)(-)?/';
|
||||||
|
|
||||||
/** @var string[] */
|
/** @var string[] */
|
||||||
private array $formatStrings = [];
|
private array $formatStrings = [];
|
||||||
|
|
||||||
@ -68,50 +76,21 @@ class FormattedCommandAlias extends Command{
|
|||||||
* @param string[] $args
|
* @param string[] $args
|
||||||
*/
|
*/
|
||||||
private function buildCommand(string $formatString, array $args) : string{
|
private function buildCommand(string $formatString, array $args) : string{
|
||||||
$index = strpos($formatString, '$');
|
$index = 0;
|
||||||
while($index !== false){
|
while(($index = strpos($formatString, '$', $index)) !== false){
|
||||||
$start = $index;
|
$start = $index;
|
||||||
if($index > 0 && $formatString[$start - 1] === "\\"){
|
if($index > 0 && $formatString[$start - 1] === "\\"){
|
||||||
$formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start);
|
$formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start);
|
||||||
$index = strpos($formatString, '$', $index);
|
//offset is now pointing at the next character because we just deleted the \
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$required = false;
|
$info = self::extractPlaceholderInfo($formatString, $index);
|
||||||
if($formatString[$index + 1] == '$'){
|
if($info === null){
|
||||||
$required = true;
|
|
||||||
|
|
||||||
++$index;
|
|
||||||
}
|
|
||||||
|
|
||||||
++$index;
|
|
||||||
|
|
||||||
$argStart = $index;
|
|
||||||
|
|
||||||
while($index < strlen($formatString) && self::inRange(ord($formatString[$index]) - 48, 0, 9)){
|
|
||||||
++$index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($argStart === $index){
|
|
||||||
throw new \InvalidArgumentException("Invalid replacement token");
|
throw new \InvalidArgumentException("Invalid replacement token");
|
||||||
}
|
}
|
||||||
|
[$fullPlaceholder, $required, $position, $rest] = $info;
|
||||||
$position = (int) substr($formatString, $argStart, $index);
|
$position--; //array offsets start at 0, but placeholders start at 1
|
||||||
|
|
||||||
if($position === 0){
|
|
||||||
throw new \InvalidArgumentException("Invalid replacement token");
|
|
||||||
}
|
|
||||||
|
|
||||||
--$position;
|
|
||||||
|
|
||||||
$rest = false;
|
|
||||||
|
|
||||||
if($index < strlen($formatString) && $formatString[$index] === "-"){
|
|
||||||
$rest = true;
|
|
||||||
++$index;
|
|
||||||
}
|
|
||||||
|
|
||||||
$end = $index;
|
|
||||||
|
|
||||||
if($required && $position >= count($args)){
|
if($required && $position >= count($args)){
|
||||||
throw new \InvalidArgumentException("Missing required argument " . ($position + 1));
|
throw new \InvalidArgumentException("Missing required argument " . ($position + 1));
|
||||||
@ -119,20 +98,15 @@ class FormattedCommandAlias extends Command{
|
|||||||
|
|
||||||
$replacement = self::buildReplacement($args, $position, $rest);
|
$replacement = self::buildReplacement($args, $position, $rest);
|
||||||
|
|
||||||
|
$end = $index + strlen($fullPlaceholder);
|
||||||
$formatString = substr($formatString, 0, $start) . $replacement . substr($formatString, $end);
|
$formatString = substr($formatString, 0, $start) . $replacement . substr($formatString, $end);
|
||||||
|
|
||||||
$index = $start + strlen($replacement);
|
$index = $start + strlen($replacement);
|
||||||
|
|
||||||
$index = strpos($formatString, '$', $index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $formatString;
|
return $formatString;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function inRange(int $i, int $j, int $k) : bool{
|
|
||||||
return $i >= $j && $i <= $k;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $args
|
* @param string[] $args
|
||||||
* @phpstan-param list<string> $args
|
* @phpstan-param list<string> $args
|
||||||
@ -153,4 +127,21 @@ class FormattedCommandAlias extends Command{
|
|||||||
|
|
||||||
return $replacement;
|
return $replacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-return array{string, bool, int, bool}
|
||||||
|
*/
|
||||||
|
private static function extractPlaceholderInfo(string $commandString, int $offset) : ?array{
|
||||||
|
if(preg_match(self::FORMAT_STRING_REGEX, $commandString, $matches, 0, $offset) !== 1){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fullPlaceholder = $matches[0];
|
||||||
|
|
||||||
|
$required = ($matches[1] ?? "") !== "";
|
||||||
|
$position = (int) $matches[2];
|
||||||
|
$variadic = ($matches[3] ?? "") !== "";
|
||||||
|
|
||||||
|
return [$fullPlaceholder, $required, $position, $variadic];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user