Skip to content

Change how command lines are parsed into args. #6703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
NTT1906 opened this issue May 24, 2025 · 2 comments
Open

Change how command lines are parsed into args. #6703

NTT1906 opened this issue May 24, 2025 · 2 comments
Labels
Category: API Related to the plugin API Opinions Wanted Request for comments & opinions from the community Type: Enhancement Contributes features or other improvements to PocketMine-MP

Comments

@NTT1906
Copy link
Contributor

NTT1906 commented May 24, 2025

Problem description

The current SimpleCommandMap::dispatch() use CommandHelper::parseQuoteAware() to parse command line to args, currently this following command line

  • /tellraw @a[name="Arie1906", c=1] "quoted \"你好\"" {"rawtext": [{"text":"§bI am blue"}]} would be parsed to [/tellraw, @a[name="Arie1906",, c=1], quoted "你好", {"rawtext":, [{"text":"§bI, am, blue"}]}]
  • Issues:
    • The returned args are messy and require extra complexity to capture those grouped tags/json input ([...], {...} or (...))
    • The args have lost those spaces between I, am, blue; despite it being in a quote.
  • IMO, it's should ideally return [/tellraw, @a[name="Arie1906, c=1], quoted "你好", {"rawtext": [{"text":"§bI am blue"}]}]
  • The result above output from this following code scaped out of PMMP: RUN
<?php
function parseQuoteAware(string $commandLine) : array{
  $args = [];
  preg_match_all('/"((?:\\\\.|[^\\\\"])*)"|(\S+)/u', $commandLine, $matches);
  foreach($matches[0] as $k => $_){
    for($i = 1; $i <= 2; ++$i){
      if($matches[$i][$k] !== ""){
        $match = $matches[$i][$k];
        $args[] = preg_replace('/\\\\([\\\\"])/u', '$1', $match) ?? throw new AssumptionFailedError(preg_last_error_msg());
        break;
      }
    }
  }
  return $args;
}

$cmdLine = '/tellraw @a[name="Arie1906", c=1] "quoted \"string\"" {"rawtext": [{"text":"§bI     am blue"}]}';
var_dump(parseQuoteAware($cmdLine));

Proposed solution

This following will parse the command line exactly as I wanted while having no effects on performance. RUN

function parseQuoteAware(string $commandLine) : array{
  $args = [];
  preg_match_all('/"((?:\\\\.|[^\\\\"])*)"|[~^][^\s~^]*|\S+\s*/u', $commandLine, $matches, PREG_UNMATCHED_AS_NULL);
  $size = count($matches[0]);
  for ($k = 0; $k < $size; ++$k) {
    if ($matches[1][$k] !== null) {
      $args[] = str_replace('\"', '"', $matches[1][$k]);
      continue;
    }
    $match = $matches[0][$k];
    $level = (substr_count($match, "[") - substr_count($match, "]"))
           + (substr_count($match, "{") - substr_count($match, "}"))
           + (substr_count($match, "(") - substr_count($match, ")"));
    if ($level == 0 || $k == $size - 1) {
      $args[] = rtrim($match);
    } else {
      $matches[0][$k + 1] = $match . $matches[0][$k + 1];
    }
  }
  return $args;
}

Alternative solutions or workarounds

No response

@dktapps
Copy link
Member

dktapps commented May 24, 2025

The proposed solution is too techy and it's too difficult to understand wtf it's doing. I'd be more inclined to go with #6704 to allow people to implement this themselves.

@dktapps dktapps added Category: API Related to the plugin API Type: Enhancement Contributes features or other improvements to PocketMine-MP Opinions Wanted Request for comments & opinions from the community labels May 24, 2025
@NTT1906
Copy link
Contributor Author

NTT1906 commented May 24, 2025

I agree. The other way might also help minimize the damage of BC break

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Category: API Related to the plugin API Opinions Wanted Request for comments & opinions from the community Type: Enhancement Contributes features or other improvements to PocketMine-MP
Projects
None yet
Development

No branches or pull requests

2 participants