Nette Documentation Preview

syntax
Nette Command-Line
******************

.[perex]
Una libreria leggera per costruire applicazioni da riga di comando in PHP. Analizza switch, opzioni e argomenti posizionali e vi aiuta a produrre output colorato nel terminale con il supporto ANSI.

Installazione:

```shell
composer require nette/command-line
```

Richiede PHP versione 8.2 e supporta PHP fino alla 8.5.


Analisi degli argomenti da riga di comando
==========================================

Ogni script CLI deve gestire argomenti come `--verbose`, `-o output.txt` oppure semplici nomi di file. La classe [api:Nette\CommandLine\Parser] offre il modo più rapido di cominciare: basta scrivere il vostro testo di aiuto e lasciare che il parser ne ricavi le definizioni delle opzioni:

```php
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser->addFromHelp('
	-h, --help              Show this help
	-v, --verbose           Enable verbose mode
	-o, --output <file>     Output file
	-f, --format [type]     Output format (default: json)
	-I, --include <path>... Include paths
	--dry-run               Show what would be done
');

$args = $parser->parse();
```

Ecco fatto. Il parser capisce che `--verbose` è uno switch, che `--output` richiede un valore e che `--format` ha un valore facoltativo con `json` come ripiego. Il vostro testo di aiuto resta allineato alle definizioni reali delle opzioni.

Il metodo `parse()` restituisce un array associativo. Le chiavi corrispondono esattamente ai nomi delle opzioni come sono definiti, trattini compresi:

```php
[
	'--help' => true,         // oppure null se non è stata usata
	'--verbose' => null,
	'--output' => 'file.txt', // oppure null se non è stata usata
	'--format' => 'json',     // ripiego da (default: json)
	'--include' => ['src', 'lib'],
	'--dry-run' => null,
]
```

Per impostazione predefinita `parse()` legge da `$_SERVER['argv']`. Potete passare un array vostro, il che torna comodo per i test:

```php
$args = $parser->parse(['--verbose', '-o', 'out.txt']);
```


Sintassi del testo di aiuto
---------------------------

Il parser ricava le definizioni delle opzioni dal testo di aiuto formattato secondo queste regole:

| `--verbose`      | Switch (senza valore)
| `-v, --verbose`  | Switch con alias breve
| `--output <file>`| Opzione con valore obbligatorio
| `--format [type]`| Opzione con valore facoltativo
| `(default: json)`| Imposta il valore di ripiego
| `<path>...`      | Opzione ripetibile

Ogni riga definisce un'opzione. I nomi delle opzioni devono essere separati dalle loro descrizioni da almeno due spazi.


Configurazione aggiuntiva
-------------------------

Alcune impostazioni non si possono esprimere nel testo di aiuto. Passate come secondo parametro un array con chiavi corrispondenti ai nomi delle opzioni:

```php
$parser->addFromHelp('
	-c, --config <file>   Configuration file
	-I, --include <path>  Include path
	-n, --count <num>     Number of iterations
', [
	'--config' => [
		Parser::RealPath => true,
	],
	'--include' => [
		Parser::Repeatable => true,
	],
	'--count' => [
		Parser::Normalizer => fn($v) => (int) $v,
	],
]);
```

Chiavi disponibili:

| `Parser::Repeatable` | Raccoglie più valori in un array
| `Parser::RealPath`   | Verifica che il file esista e lo risolve in un percorso assoluto
| `Parser::Normalizer` | Funzione di trasformazione `fn($value) => ...`
| `Parser::Default`    | Valore di ripiego (uguale a `(default: x)` nel testo di aiuto)
| `Parser::Enum`       | Array dei valori consentiti


API fluent
==========

Quando vi serve più controllo sulle definizioni delle opzioni, usate l'API fluent con i metodi `addSwitch()`, `addOption()` e `addArgument()`. Questo approccio vi dà accesso a tutte le funzionalità, compresi normalizzatori, enum e controllo preciso su ogni parametro:

```php
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addSwitch('--verbose', '-v')
	->addOption('--output', '-o')
	->addArgument('file');

$args = $parser->parse();
```

Come con `addFromHelp()`, potete passare a `parse()` un array vostro per i test:

```php
$args = $parser->parse(['--verbose', '-o', 'out.txt', 'input.txt']);
```


Switch, opzioni e argomenti
---------------------------

Ci sono tre tipi di input da riga di comando:

Gli **switch** sono flag senza valore, come `--verbose` oppure `-v`. Vengono analizzati come `true` quando sono presenti, come `null` quando mancano:

```php
$parser->addSwitch('--verbose', '-v');
// --verbose  → true
// -v         → true
// (non usato) → null
```

Le **opzioni** accettano valori, come `--output file.txt`. Il valore si può separare con uno spazio oppure con `=`:

```php
$parser->addOption('--output', '-o');
// --output file.txt    → 'file.txt'
// --output=file.txt    → 'file.txt'
// -o file.txt          → 'file.txt'
// --output             → lancia un'eccezione (valore obbligatorio)
// (non usata)          → null
```

Notate che l'opzione in sé è sempre facoltativa: non usarla restituisce `null`. Quando però viene usata, il valore è obbligatorio per impostazione predefinita. Impostate `optionalValue: true` per permettere l'opzione senza valore (viene allora analizzata come `true`):

```php
$parser->addOption('--format', '-f', optionalValue: true);
// --format json        → 'json'
// --format             → true
// (non usata)          → null
```

Quando la stessa opzione viene usata più volte senza `repeatable: true`, vince l'ultimo valore:

```php
$parser->addOption('--output', '-o');
// -o first.txt -o second.txt  → 'second.txt'
```

Gli **argomenti** sono valori posizionali senza trattini. Per impostazione predefinita sono obbligatori. Impostate `optional: true` per renderli facoltativi:

```php
$parser->addArgument('input');
// script.php file.txt  → 'file.txt'
// (non usato)          → lancia un'eccezione

$parser->addArgument('output', optional: true);
// (non usato)          → null

$parser->addArgument('output', optional: true, fallback: 'out.txt');
// (non usato)          → 'out.txt'
```

Usate `fallback` per indicare il valore usato quando un'opzione o un argomento facoltativo non viene fornito. Per le opzioni con `optionalValue: true` tenete presente che usare l'opzione senza valore viene comunque analizzato come `true`, mentre il ripiego si usa solo quando l'opzione non è presente affatto:

```php
$parser->addOption('--format', '-f', optionalValue: true, fallback: 'json');
// --format xml  → 'xml'
// --format      → true (opzione usata senza valore)
// (non usata)   → 'json' (ripiego)
```

Gli argomenti possono comparire in qualsiasi punto della riga di comando, non devono per forza venire dopo le opzioni:

```php
// tutte queste forme sono equivalenti:
// script.php --verbose input.txt
// script.php input.txt --verbose
```


Limitare i valori con enum
--------------------------

Limitate i valori accettati a un insieme determinato:

```php
$parser->addOption('--format', '-f', enum: ['json', 'xml', 'csv']);
// --format yaml  → lancia "Value of option --format must be json, or xml, or csv."
```


Opzioni ripetibili
------------------

Impostate `repeatable: true` per raccogliere più valori in un array:

```php
$parser->addOption('--include', '-I', repeatable: true);
// -I src -I lib  → ['src', 'lib']
// (non usata)    → []

$parser->addArgument('files', optional: true, repeatable: true);
// a.txt b.txt    → ['a.txt', 'b.txt']
```


Trasformare i valori
--------------------

Usate un `normalizer` per trasformare il valore analizzato:

```php
$parser->addOption('--count', normalizer: fn($v) => (int) $v);
// --count 42  → 42 (intero)
```

Per validare i percorsi dei file usate il `normalizeRealPath` integrato:

```php
$parser->addOption('--config', normalizer: Parser::normalizeRealPath(...));
// --config app.ini     → '/full/path/to/app.ini'
// --config missing.ini → lancia "File path 'missing.ini' not found."
```


Combinare i due approcci
------------------------

Potete combinare `addFromHelp()` con i metodi fluent quando vi servono i normalizzatori solo per alcune opzioni:

```php
$parser
	->addFromHelp('
		-v, --verbose  Enable verbose mode
		-q, --quiet    Suppress output
	')
	->addOption('--config', '-c', normalizer: Parser::normalizeRealPath(...))
	->addArgument('input');
```


Gestione degli errori
---------------------

Il parser lancia `\Exception` per gli input non validi:

```php
use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addOption('--output', '-o')
	->addArgument('file');

try {
	$args = $parser->parse();
} catch (\Exception $e) {
	fwrite(STDERR, "Error: {$e->getMessage()}\n");
	exit(1);
}
```

Messaggi di errore più frequenti:

| `Option --output requires argument.`          | Opzione usata senza il valore obbligatorio
| `Unknown option --foo.`                       | Opzione non riconosciuta
| `Missing required argument <file>.`           | Argomento obbligatorio non fornito
| `Unexpected parameter foo.`                   | Argomento posizionale in più
| `Value of option --format must be json, or xml.` | Valore non presente nell'enum

Usate `isEmpty()` per verificare se non è stato fornito alcun argomento da riga di comando (cioè se l'utente ha lanciato solo `script.php` senza nulla dopo):

```php
if ($parser->isEmpty()) {
	$parser->help();
	exit;
}
```


Gestire --help e --version
--------------------------

Quando il vostro script ha argomenti obbligatori, lanciare `script.php --help` fallirebbe normalmente perché manca l'argomento obbligatorio. Usate `parseOnly()` per controllare prima le opzioni informative:

```php
$parser = new Parser;
$parser
	->addSwitch('--help', '-h')
	->addSwitch('--version', '-V')
	->addArgument('input');  // obbligatorio

// prima controlliamo le opzioni informative (nessuna validazione, nessuna eccezione)
$info = $parser->parseOnly(['--help', '--version']);

if ($info['--help']) {
	$parser->help();
	exit;
}

if ($info['--version']) {
	echo "1.0.0\n";
	exit;
}

// ora facciamo l'analisi completa con la validazione
$args = $parser->parse();
```

Il metodo `parseOnly()`:
- analizza solo le opzioni indicate, ignorando tutto il resto,
- rispetta gli alias (`-h` → `--help`),
- non lancia mai eccezioni,
- restituisce `null` per le opzioni che non sono state usate.


Output colorato
===============

La classe [api:Nette\CommandLine\Console] racchiude il testo nei codici colore ANSI, così il vostro output spicca nel terminale:

```php
use Nette\CommandLine\Console;

$console = new Console;
echo $console->color('red', 'Error!') . "\n";
echo $console->color('white/blue', 'White text on blue background') . "\n";
```

Il colore si indica come `'primo piano'` oppure `'primo piano/sfondo'`. I colori disponibili sono: `black`, `gray`, `silver`, `white`, `navy`, `blue`, `green`, `lime`, `teal`, `aqua`, `maroon`, `red`, `purple`, `fuchsia`, `olive` e `yellow`.

I colori si attivano automaticamente solo quando l'output li supporta. Il metodo `color()` restituisce una stringa semplice quando i colori sono disattivati, quindi si può sempre chiamare senza rischi. Il comportamento lo potete forzare a mano:

```php
$console->useColors(false); // disattiva i colori
$console->useColors(true);  // forza i colori
```


Rilevare il terminale
---------------------

Due metodi statici vi aiutano a decidere se usare funzionalità legate al terminale. `detectColors()` restituisce `false` quando è impostata la variabile d'ambiente [NO_COLOR |https://no-color.org], oppure quando l'output non è un terminale CLI; la variabile `FORCE_COLOR` ha la precedenza sul controllo del terminale:

```php
if (Console::detectColors()) {
	// il terminale supporta i colori ANSI
}
```

`detectTerminal()` vi dice se l'output è un terminale interattivo (un TTY). Torna utile per disattivare automaticamente le funzionalità che hanno senso solo in un terminale, come gli indicatori di avanzamento, l'output che riscrive la riga o le richieste interattive:

```php
if (Console::detectTerminal()) {
	// l'output va a un terminale interattivo, non a un file o a una pipe
}
```


Esempio completo
================

Ecco uno script reale di conversione file che combina `Parser` e `Console`:

```php
#!/usr/bin/env php
<?php
use Nette\CommandLine\Parser;

require __DIR__ . '/vendor/autoload.php';

$parser = new Parser;
$parser
	->addFromHelp('
		-h, --help           Show this help
		-v, --verbose        Show detailed output
		-n, --dry-run        Show what would be done
		-f, --format [type]  Output format (default: json)
		-o, --output <file>  Output file
	', [
		'--format' => [
			Parser::Enum => ['json', 'xml', 'csv'],
		],
	])
	->addArgument('input', normalizer: Parser::normalizeRealPath(...));

// gestiamo --help prima della validazione (evita l'errore "missing argument")
if ($parser->isEmpty() || $parser->parseOnly(['--help'])['--help']) {
	echo "Usage: convert [options] <input>\n\n";
	$parser->help();
	exit;
}

try {
	$args = $parser->parse();
} catch (\Exception $e) {
	fwrite(STDERR, "Error: {$e->getMessage()}\n");
	exit(1);
}

if ($args['--verbose']) {
	echo "Converting {$args['input']} to {$args['--format']}...\n";
}

if ($args['--dry-run']) {
	echo "Dry run: no changes made.\n";
	exit;
}

// ... qui la logica di conversione ...

echo "Done!\n";
```

Lo script accetta comandi come:

- `convert input.txt` - conversione con i valori predefiniti
- `convert -v --format xml input.txt` - modalità verbose, formato XML
- `convert -o result.txt input.txt` - indica il file di output
- `convert --help` - mostra l'aiuto (funziona anche senza il file di input)


{{sitename: Documentazione Nette}}

Nette Command-Line

Una libreria leggera per costruire applicazioni da riga di comando in PHP. Analizza switch, opzioni e argomenti posizionali e vi aiuta a produrre output colorato nel terminale con il supporto ANSI.

Installazione:

composer require nette/command-line

Richiede PHP versione 8.2 e supporta PHP fino alla 8.5.

Analisi degli argomenti da riga di comando

Ogni script CLI deve gestire argomenti come --verbose, -o output.txt oppure semplici nomi di file. La classe Nette\CommandLine\Parser offre il modo più rapido di cominciare: basta scrivere il vostro testo di aiuto e lasciare che il parser ne ricavi le definizioni delle opzioni:

use Nette\CommandLine\Parser;

$parser = new Parser;
$parser->addFromHelp('
	-h, --help              Show this help
	-v, --verbose           Enable verbose mode
	-o, --output <file>     Output file
	-f, --format [type]     Output format (default: json)
	-I, --include <path>... Include paths
	--dry-run               Show what would be done
');

$args = $parser->parse();

Ecco fatto. Il parser capisce che --verbose è uno switch, che --output richiede un valore e che --format ha un valore facoltativo con json come ripiego. Il vostro testo di aiuto resta allineato alle definizioni reali delle opzioni.

Il metodo parse() restituisce un array associativo. Le chiavi corrispondono esattamente ai nomi delle opzioni come sono definiti, trattini compresi:

[
	'--help' => true,         // oppure null se non è stata usata
	'--verbose' => null,
	'--output' => 'file.txt', // oppure null se non è stata usata
	'--format' => 'json',     // ripiego da (default: json)
	'--include' => ['src', 'lib'],
	'--dry-run' => null,
]

Per impostazione predefinita parse() legge da $_SERVER['argv']. Potete passare un array vostro, il che torna comodo per i test:

$args = $parser->parse(['--verbose', '-o', 'out.txt']);

Sintassi del testo di aiuto

Il parser ricava le definizioni delle opzioni dal testo di aiuto formattato secondo queste regole:

--verbose Switch (senza valore)
-v, --verbose Switch con alias breve
--output <file> Opzione con valore obbligatorio
--format [type] Opzione con valore facoltativo
(default: json) Imposta il valore di ripiego
<path>... Opzione ripetibile

Ogni riga definisce un'opzione. I nomi delle opzioni devono essere separati dalle loro descrizioni da almeno due spazi.

Configurazione aggiuntiva

Alcune impostazioni non si possono esprimere nel testo di aiuto. Passate come secondo parametro un array con chiavi corrispondenti ai nomi delle opzioni:

$parser->addFromHelp('
	-c, --config <file>   Configuration file
	-I, --include <path>  Include path
	-n, --count <num>     Number of iterations
', [
	'--config' => [
		Parser::RealPath => true,
	],
	'--include' => [
		Parser::Repeatable => true,
	],
	'--count' => [
		Parser::Normalizer => fn($v) => (int) $v,
	],
]);

Chiavi disponibili:

Parser::Repeatable Raccoglie più valori in un array
Parser::RealPath Verifica che il file esista e lo risolve in un percorso assoluto
Parser::Normalizer Funzione di trasformazione fn($value) => ...
Parser::Default Valore di ripiego (uguale a (default: x) nel testo di aiuto)
Parser::Enum Array dei valori consentiti

API fluent

Quando vi serve più controllo sulle definizioni delle opzioni, usate l'API fluent con i metodi addSwitch(), addOption() e addArgument(). Questo approccio vi dà accesso a tutte le funzionalità, compresi normalizzatori, enum e controllo preciso su ogni parametro:

use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addSwitch('--verbose', '-v')
	->addOption('--output', '-o')
	->addArgument('file');

$args = $parser->parse();

Come con addFromHelp(), potete passare a parse() un array vostro per i test:

$args = $parser->parse(['--verbose', '-o', 'out.txt', 'input.txt']);

Switch, opzioni e argomenti

Ci sono tre tipi di input da riga di comando:

Gli switch sono flag senza valore, come --verbose oppure -v. Vengono analizzati come true quando sono presenti, come null quando mancano:

$parser->addSwitch('--verbose', '-v');
// --verbose  → true
// -v         → true
// (non usato) → null

Le opzioni accettano valori, come --output file.txt. Il valore si può separare con uno spazio oppure con =:

$parser->addOption('--output', '-o');
// --output file.txt    → 'file.txt'
// --output=file.txt    → 'file.txt'
// -o file.txt          → 'file.txt'
// --output             → lancia un'eccezione (valore obbligatorio)
// (non usata)          → null

Notate che l'opzione in sé è sempre facoltativa: non usarla restituisce null. Quando però viene usata, il valore è obbligatorio per impostazione predefinita. Impostate optionalValue: true per permettere l'opzione senza valore (viene allora analizzata come true):

$parser->addOption('--format', '-f', optionalValue: true);
// --format json        → 'json'
// --format             → true
// (non usata)          → null

Quando la stessa opzione viene usata più volte senza repeatable: true, vince l'ultimo valore:

$parser->addOption('--output', '-o');
// -o first.txt -o second.txt  → 'second.txt'

Gli argomenti sono valori posizionali senza trattini. Per impostazione predefinita sono obbligatori. Impostate optional: true per renderli facoltativi:

$parser->addArgument('input');
// script.php file.txt  → 'file.txt'
// (non usato)          → lancia un'eccezione

$parser->addArgument('output', optional: true);
// (non usato)          → null

$parser->addArgument('output', optional: true, fallback: 'out.txt');
// (non usato)          → 'out.txt'

Usate fallback per indicare il valore usato quando un'opzione o un argomento facoltativo non viene fornito. Per le opzioni con optionalValue: true tenete presente che usare l'opzione senza valore viene comunque analizzato come true, mentre il ripiego si usa solo quando l'opzione non è presente affatto:

$parser->addOption('--format', '-f', optionalValue: true, fallback: 'json');
// --format xml  → 'xml'
// --format      → true (opzione usata senza valore)
// (non usata)   → 'json' (ripiego)

Gli argomenti possono comparire in qualsiasi punto della riga di comando, non devono per forza venire dopo le opzioni:

// tutte queste forme sono equivalenti:
// script.php --verbose input.txt
// script.php input.txt --verbose

Limitare i valori con enum

Limitate i valori accettati a un insieme determinato:

$parser->addOption('--format', '-f', enum: ['json', 'xml', 'csv']);
// --format yaml  → lancia "Value of option --format must be json, or xml, or csv."

Opzioni ripetibili

Impostate repeatable: true per raccogliere più valori in un array:

$parser->addOption('--include', '-I', repeatable: true);
// -I src -I lib  → ['src', 'lib']
// (non usata)    → []

$parser->addArgument('files', optional: true, repeatable: true);
// a.txt b.txt    → ['a.txt', 'b.txt']

Trasformare i valori

Usate un normalizer per trasformare il valore analizzato:

$parser->addOption('--count', normalizer: fn($v) => (int) $v);
// --count 42  → 42 (intero)

Per validare i percorsi dei file usate il normalizeRealPath integrato:

$parser->addOption('--config', normalizer: Parser::normalizeRealPath(...));
// --config app.ini     → '/full/path/to/app.ini'
// --config missing.ini → lancia "File path 'missing.ini' not found."

Combinare i due approcci

Potete combinare addFromHelp() con i metodi fluent quando vi servono i normalizzatori solo per alcune opzioni:

$parser
	->addFromHelp('
		-v, --verbose  Enable verbose mode
		-q, --quiet    Suppress output
	')
	->addOption('--config', '-c', normalizer: Parser::normalizeRealPath(...))
	->addArgument('input');

Gestione degli errori

Il parser lancia \Exception per gli input non validi:

use Nette\CommandLine\Parser;

$parser = new Parser;
$parser
	->addOption('--output', '-o')
	->addArgument('file');

try {
	$args = $parser->parse();
} catch (\Exception $e) {
	fwrite(STDERR, "Error: {$e->getMessage()}\n");
	exit(1);
}

Messaggi di errore più frequenti:

Option --output requires argument. Opzione usata senza il valore obbligatorio
Unknown option --foo. Opzione non riconosciuta
Missing required argument <file>. Argomento obbligatorio non fornito
Unexpected parameter foo. Argomento posizionale in più
Value of option --format must be json, or xml. Valore non presente nell'enum

Usate isEmpty() per verificare se non è stato fornito alcun argomento da riga di comando (cioè se l'utente ha lanciato solo script.php senza nulla dopo):

if ($parser->isEmpty()) {
	$parser->help();
	exit;
}

Gestire –help e –version

Quando il vostro script ha argomenti obbligatori, lanciare script.php --help fallirebbe normalmente perché manca l'argomento obbligatorio. Usate parseOnly() per controllare prima le opzioni informative:

$parser = new Parser;
$parser
	->addSwitch('--help', '-h')
	->addSwitch('--version', '-V')
	->addArgument('input');  // obbligatorio

// prima controlliamo le opzioni informative (nessuna validazione, nessuna eccezione)
$info = $parser->parseOnly(['--help', '--version']);

if ($info['--help']) {
	$parser->help();
	exit;
}

if ($info['--version']) {
	echo "1.0.0\n";
	exit;
}

// ora facciamo l'analisi completa con la validazione
$args = $parser->parse();

Il metodo parseOnly():

  • analizza solo le opzioni indicate, ignorando tutto il resto,
  • rispetta gli alias (-h--help),
  • non lancia mai eccezioni,
  • restituisce null per le opzioni che non sono state usate.

Output colorato

La classe Nette\CommandLine\Console racchiude il testo nei codici colore ANSI, così il vostro output spicca nel terminale:

use Nette\CommandLine\Console;

$console = new Console;
echo $console->color('red', 'Error!') . "\n";
echo $console->color('white/blue', 'White text on blue background') . "\n";

Il colore si indica come 'primo piano' oppure 'primo piano/sfondo'. I colori disponibili sono: black, gray, silver, white, navy, blue, green, lime, teal, aqua, maroon, red, purple, fuchsia, olive e yellow.

I colori si attivano automaticamente solo quando l'output li supporta. Il metodo color() restituisce una stringa semplice quando i colori sono disattivati, quindi si può sempre chiamare senza rischi. Il comportamento lo potete forzare a mano:

$console->useColors(false); // disattiva i colori
$console->useColors(true);  // forza i colori

Rilevare il terminale

Due metodi statici vi aiutano a decidere se usare funzionalità legate al terminale. detectColors() restituisce false quando è impostata la variabile d'ambiente NO_COLOR, oppure quando l'output non è un terminale CLI; la variabile FORCE_COLOR ha la precedenza sul controllo del terminale:

if (Console::detectColors()) {
	// il terminale supporta i colori ANSI
}

detectTerminal() vi dice se l'output è un terminale interattivo (un TTY). Torna utile per disattivare automaticamente le funzionalità che hanno senso solo in un terminale, come gli indicatori di avanzamento, l'output che riscrive la riga o le richieste interattive:

if (Console::detectTerminal()) {
	// l'output va a un terminale interattivo, non a un file o a una pipe
}

Esempio completo

Ecco uno script reale di conversione file che combina Parser e Console:

#!/usr/bin/env php
<?php
use Nette\CommandLine\Parser;

require __DIR__ . '/vendor/autoload.php';

$parser = new Parser;
$parser
	->addFromHelp('
		-h, --help           Show this help
		-v, --verbose        Show detailed output
		-n, --dry-run        Show what would be done
		-f, --format [type]  Output format (default: json)
		-o, --output <file>  Output file
	', [
		'--format' => [
			Parser::Enum => ['json', 'xml', 'csv'],
		],
	])
	->addArgument('input', normalizer: Parser::normalizeRealPath(...));

// gestiamo --help prima della validazione (evita l'errore "missing argument")
if ($parser->isEmpty() || $parser->parseOnly(['--help'])['--help']) {
	echo "Usage: convert [options] <input>\n\n";
	$parser->help();
	exit;
}

try {
	$args = $parser->parse();
} catch (\Exception $e) {
	fwrite(STDERR, "Error: {$e->getMessage()}\n");
	exit(1);
}

if ($args['--verbose']) {
	echo "Converting {$args['input']} to {$args['--format']}...\n";
}

if ($args['--dry-run']) {
	echo "Dry run: no changes made.\n";
	exit;
}

// ... qui la logica di conversione ...

echo "Done!\n";

Lo script accetta comandi come:

  • convert input.txt – conversione con i valori predefiniti
  • convert -v --format xml input.txt – modalità verbose, formato XML
  • convert -o result.txt input.txt – indica il file di output
  • convert --help – mostra l'aiuto (funziona anche senza il file di input)