fix:repo cleanup
This commit is contained in:
+21
@@ -2,6 +2,24 @@
|
||||
|
||||
All notable changes are documented in this file using the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
|
||||
|
||||
## [4.2.0] - 2025-09-14
|
||||
|
||||
### Changed
|
||||
|
||||
* [#3](https://github.com/sebastianbergmann/cli-parser/pull/3): Print most similar options when reporting unknown options
|
||||
|
||||
## [4.1.0] - 2025-09-13
|
||||
|
||||
### Changed
|
||||
|
||||
* [#2](https://github.com/sebastianbergmann/cli-parser/pull/2): Print similar options when reporting ambiguous options
|
||||
|
||||
## [4.0.0] - 2025-02-07
|
||||
|
||||
### Removed
|
||||
|
||||
* This component is no longer supported on PHP 8.2
|
||||
|
||||
## [3.0.2] - 2024-07-03
|
||||
|
||||
### Changed
|
||||
@@ -42,6 +60,9 @@ All notable changes are documented in this file using the [Keep a CHANGELOG](htt
|
||||
|
||||
* Initial release
|
||||
|
||||
[4.2.0]: https://github.com/sebastianbergmann/cli-parser/compare/4.1.0...4.2.0
|
||||
[4.1.0]: https://github.com/sebastianbergmann/cli-parser/compare/4.0.0...4.1.0
|
||||
[4.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/3.0...4.0.0
|
||||
[3.0.2]: https://github.com/sebastianbergmann/cli-parser/compare/3.0.1...3.0.2
|
||||
[3.0.1]: https://github.com/sebastianbergmann/cli-parser/compare/3.0.0...3.0.1
|
||||
[3.0.0]: https://github.com/sebastianbergmann/cli-parser/compare/2.0...3.0.0
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020-2024, Sebastian Bergmann
|
||||
Copyright (c) 2020-2025, Sebastian Bergmann
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
[](https://packagist.org/packages/sebastian/cli-parser)
|
||||
[](https://packagist.org/packages/sebastian/cli-parser)
|
||||
[](https://github.com/sebastianbergmann/cli-parser/actions)
|
||||
[](https://codecov.io/gh/sebastianbergmann/cli-parser)
|
||||
|
||||
|
||||
+4
-4
@@ -17,14 +17,14 @@
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=8.2"
|
||||
"php": ">=8.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^11.0"
|
||||
"phpunit/phpunit": "^12.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "8.2.0"
|
||||
"php": "8.3.0"
|
||||
},
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.0-dev"
|
||||
"dev-main": "4.2-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+56
-15
@@ -19,17 +19,19 @@ use function current;
|
||||
use function explode;
|
||||
use function is_array;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function key;
|
||||
use function levenshtein;
|
||||
use function next;
|
||||
use function preg_replace;
|
||||
use function reset;
|
||||
use function rtrim;
|
||||
use function sort;
|
||||
use function str_ends_with;
|
||||
use function str_starts_with;
|
||||
use function strlen;
|
||||
use function strstr;
|
||||
use function substr;
|
||||
use function usort;
|
||||
|
||||
final class Parser
|
||||
{
|
||||
@@ -42,11 +44,11 @@ final class Parser
|
||||
* @throws RequiredOptionArgumentMissingException
|
||||
* @throws UnknownOptionException
|
||||
*
|
||||
* @return array{0: list<array{0: non-empty-string, 1: ?non-empty-string}>, 1: list<non-empty-string>}
|
||||
* @return array{0: list<array{0: string, 1: ?string}>, 1: list<string>}
|
||||
*/
|
||||
public function parse(array $argv, string $shortOptions, ?array $longOptions = null): array
|
||||
{
|
||||
if (empty($argv)) {
|
||||
if ($argv === []) {
|
||||
return [[], []];
|
||||
}
|
||||
|
||||
@@ -111,8 +113,8 @@ final class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{0: non-empty-string, 1: ?non-empty-string}> $options
|
||||
* @param list<string> $argv
|
||||
* @param list<array{0: string, 1: ?string}> $options
|
||||
* @param list<string> $argv
|
||||
*
|
||||
* @throws RequiredOptionArgumentMissingException
|
||||
*/
|
||||
@@ -125,7 +127,7 @@ final class Parser
|
||||
$optionArgument = null;
|
||||
|
||||
if ($argument[$i] === ':' || ($spec = strstr($shortOptions, $option)) === false) {
|
||||
throw new UnknownOptionException('-' . $option);
|
||||
throw new UnknownOptionException('-' . $option, []);
|
||||
}
|
||||
|
||||
if (strlen($spec) > 1 && $spec[1] === ':') {
|
||||
@@ -142,8 +144,6 @@ final class Parser
|
||||
throw new RequiredOptionArgumentMissingException('-' . $option);
|
||||
}
|
||||
|
||||
assert(is_string($optionArgument));
|
||||
|
||||
next($argv);
|
||||
}
|
||||
}
|
||||
@@ -153,9 +153,9 @@ final class Parser
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $longOptions
|
||||
* @param list<array{0: non-empty-string, 1: ?non-empty-string}> $options
|
||||
* @param list<string> $argv
|
||||
* @param list<string> $longOptions
|
||||
* @param list<array{0: string, 1: ?string}> $options
|
||||
* @param list<string> $argv
|
||||
*
|
||||
* @throws AmbiguousOptionException
|
||||
* @throws OptionDoesNotAllowArgumentException
|
||||
@@ -170,12 +170,19 @@ final class Parser
|
||||
$optionArgument = null;
|
||||
|
||||
if (count($list) > 1) {
|
||||
/** @phpstan-ignore offsetAccess.notFound */
|
||||
$optionArgument = $list[1];
|
||||
}
|
||||
|
||||
$optionLength = strlen($option);
|
||||
|
||||
$similarOptions = [];
|
||||
|
||||
foreach ($longOptions as $i => $longOption) {
|
||||
$similarOptions[] = [
|
||||
levenshtein($longOption, $option),
|
||||
'--' . rtrim($longOption, '='),
|
||||
];
|
||||
$opt_start = substr($longOption, 0, $optionLength);
|
||||
|
||||
if ($opt_start !== $option) {
|
||||
@@ -184,12 +191,25 @@ final class Parser
|
||||
|
||||
$opt_rest = substr($longOption, $optionLength);
|
||||
|
||||
if ($opt_rest !== '' && $i + 1 < $count && $option[0] !== '=' && str_starts_with($longOptions[$i + 1], $option)) {
|
||||
throw new AmbiguousOptionException('--' . $option);
|
||||
if ($opt_rest !== '' &&
|
||||
$i + 1 < $count &&
|
||||
$option[0] !== '=' &&
|
||||
/** @phpstan-ignore offsetAccess.notFound */
|
||||
str_starts_with($longOptions[$i + 1], $option)
|
||||
) {
|
||||
$candidates = [];
|
||||
|
||||
foreach ($longOptions as $aLongOption) {
|
||||
if (str_starts_with($aLongOption, $option)) {
|
||||
$candidates[] = '--' . rtrim($aLongOption, '=');
|
||||
}
|
||||
}
|
||||
|
||||
throw new AmbiguousOptionException('--' . $option, $candidates);
|
||||
}
|
||||
|
||||
if (str_ends_with($longOption, '=')) {
|
||||
if (!str_ends_with($longOption, '==') && !strlen((string) $optionArgument)) {
|
||||
if (!str_ends_with($longOption, '==') && (string) $optionArgument === '') {
|
||||
if (false === $optionArgument = current($argv)) {
|
||||
throw new RequiredOptionArgumentMissingException('--' . $option);
|
||||
}
|
||||
@@ -206,6 +226,27 @@ final class Parser
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnknownOptionException('--' . $option);
|
||||
throw new UnknownOptionException('--' . $option, $this->formatSimilarOptions($similarOptions));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{int, string}> $similarOptions
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
private function formatSimilarOptions(array $similarOptions): array
|
||||
{
|
||||
usort($similarOptions, static function (array $a, array $b)
|
||||
{
|
||||
return $a[0] <=> $b[0];
|
||||
});
|
||||
|
||||
$similarFormatted = [];
|
||||
|
||||
foreach (array_slice($similarOptions, 0, 5) as [$distance, $label]) {
|
||||
$similarFormatted[] = $label;
|
||||
}
|
||||
|
||||
return $similarFormatted;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-2
@@ -9,17 +9,22 @@
|
||||
*/
|
||||
namespace SebastianBergmann\CliParser;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
|
||||
final class AmbiguousOptionException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct(string $option)
|
||||
/**
|
||||
* @param array<string> $candiates
|
||||
*/
|
||||
public function __construct(string $option, array $candiates)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
'Option "%s" is ambiguous',
|
||||
'Option "%s" is ambiguous. Similar options are: %s',
|
||||
$option,
|
||||
implode(', ', $candiates),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,18 +9,30 @@
|
||||
*/
|
||||
namespace SebastianBergmann\CliParser;
|
||||
|
||||
use function implode;
|
||||
use function sprintf;
|
||||
use RuntimeException;
|
||||
|
||||
final class UnknownOptionException extends RuntimeException implements Exception
|
||||
{
|
||||
public function __construct(string $option)
|
||||
/**
|
||||
* @param array<string> $similarOptions
|
||||
*/
|
||||
public function __construct(string $option, array $similarOptions)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf(
|
||||
'Unknown option "%s"',
|
||||
$option,
|
||||
),
|
||||
$message = sprintf(
|
||||
'Unknown option "%s"',
|
||||
$option,
|
||||
);
|
||||
|
||||
if ($similarOptions !== []) {
|
||||
$message = sprintf(
|
||||
'Unknown option "%s". Most similar options are %s',
|
||||
$option,
|
||||
implode(', ', $similarOptions),
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($message);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user