Skip to content

Commit 01fe364

Browse files
committed
added CLAUDE.md
1 parent cab337d commit 01fe364

2 files changed

Lines changed: 235 additions & 0 deletions

File tree

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.gitattributes export-ignore
22
.github/ export-ignore
33
.gitignore export-ignore
4+
CLAUDE.md export-ignore
45
ncs.* export-ignore
56
phpstan*.neon export-ignore
67
tests/ export-ignore

CLAUDE.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
**Nette Command Line** is a lightweight PHP library providing two focused utilities:
8+
- `Parser`: Command-line argument and option parsing with help text extraction
9+
- `Console`: Terminal color output with intelligent capability detection
10+
11+
**Key characteristics:**
12+
- Zero runtime dependencies (PHP 8.2-8.5 only)
13+
- Minimal codebase
14+
- Part of the Nette Framework ecosystem
15+
- Triple-licensed: BSD-3-Clause, GPL-2.0-only, GPL-3.0-only
16+
17+
## Essential Commands
18+
19+
### Development Setup
20+
```bash
21+
composer install # Install dev dependencies
22+
```
23+
24+
### Testing
25+
```bash
26+
composer run tester # Run all tests with simple output
27+
vendor/bin/tester tests -s # Same as above
28+
vendor/bin/tester tests -s # Run with code coverage
29+
vendor/bin/tester tests/Parser.phpt -s # Run specific test file
30+
```
31+
32+
### Code Quality
33+
```bash
34+
composer run phpstan # Run PHPStan static analysis (level 5)
35+
```
36+
37+
### CI/CD Information
38+
- Tests run on PHP 8.2, 8.3, 8.4, 8.5 via GitHub Actions
39+
- Coding style checked via Nette Code Checker and Coding Standard
40+
- PHPStan runs on master branch (informative only)
41+
42+
## Architecture
43+
44+
### Four-Class Design
45+
46+
**Parser (`src/CommandLine/Parser.php` - 368 lines)**
47+
- Parses command-line arguments using help text or fluent API
48+
- Two approaches: `addFromHelp()` for help-text-driven definitions, or fluent `addSwitch()`/`addOption()`/`addArgument()` methods
49+
- Supports: flags, arguments, aliases, default values, enums, file paths, custom normalizers
50+
- Modern PascalCase constants (e.g., `Parser::Argument`, `Parser::Optional`)
51+
- Deprecated UPPERCASE constants maintained for backward compatibility
52+
53+
**Console (`src/CommandLine/Console.php`)**
54+
- ANSI color output with automatic terminal capability detection
55+
- Respects `NO_COLOR` and `FORCE_COLOR` environment variables (https://no-color.org)
56+
- Exposes two separate static checks:
57+
- `detectTerminal()` — pure CLI+TTY check (Windows VT100 or `stream_isatty`), useful for auto-disabling features that only make sense interactively (progress indicators, line-rewriting output, interactive prompts)
58+
- `detectColors()` — builds on `detectTerminal()` and adds `NO_COLOR`/`FORCE_COLOR` handling
59+
- 16 named colors with foreground/background combinations
60+
61+
**Option (`src/CommandLine/Option.php` - 39 lines)**
62+
- `final readonly class` representing a single option or positional argument configuration
63+
- Properties: `name`, `type`, `alias`, `fallback`, `repeatable`, `enum`, `normalizer`
64+
- Auto-computed `positional` property based on `-` prefix
65+
66+
**ValueType (`src/CommandLine/ValueType.php` - 22 lines)**
67+
- Enum describing value requirement for options/arguments:
68+
- `None` - switch without value (e.g., `--verbose`)
69+
- `Required` - value must be provided (e.g., `--output <file>`)
70+
- `Optional` - value can be omitted (e.g., `--format [type]`)
71+
72+
### Key Design Patterns
73+
74+
**Help Text as Schema:**
75+
The `addFromHelp()` method extracts option definitions from formatted help text:
76+
77+
```php
78+
$parser = new Parser;
79+
$parser->addFromHelp('
80+
-p, --param=<value> Parameter description (default: 123)
81+
--verbose Enable verbose mode
82+
');
83+
```
84+
85+
The help text format drives the parser configuration - options, arguments, defaults, and enums are all extracted from the help string structure.
86+
87+
**Fluent API:**
88+
For more control, use `addSwitch()`, `addOption()`, and `addArgument()` methods:
89+
90+
```php
91+
$parser = new Parser;
92+
$parser
93+
->addSwitch('--verbose', '-v')
94+
->addOption('--output', '-o')
95+
->addOption('--format', '-f', optionalValue: true, fallback: 'json', enum: ['json', 'xml', 'csv'])
96+
->addArgument('input', optional: false);
97+
```
98+
99+
**Early-Exit Options with `parseOnly()`:**
100+
For options like `--help` or `--version` that should work without providing required arguments:
101+
102+
```php
103+
$parser = new Parser;
104+
$parser
105+
->addSwitch('--help', '-h')
106+
->addArgument('input'); // required
107+
108+
// Check --help before full validation
109+
if ($parser->parseOnly(['--help'])['--help']) {
110+
$parser->help();
111+
exit;
112+
}
113+
114+
$args = $parser->parse(); // full parsing with validation
115+
```
116+
117+
The `parseOnly()` method parses only specified options, ignoring everything else. No validation, no exceptions.
118+
119+
**Option Configuration Array:**
120+
When using `addFromHelp()`, additional options can be passed via second parameter:
121+
- `Parser::Argument` - requires a value
122+
- `Parser::Optional` - value is optional
123+
- `Parser::Repeatable` - can be specified multiple times
124+
- `Parser::Enum` - restricted to specific values
125+
- `Parser::RealPath` - validates file path existence
126+
- `Parser::Normalizer` - custom transformation function
127+
- `Parser::Default` - default value when not specified
128+
129+
## Coding Standards
130+
131+
### Nette Framework Conventions
132+
- Every file: `declare(strict_types=1)` at the top
133+
- Tab indentation (not spaces)
134+
- Comprehensive type hints on all parameters and return values
135+
- PSR-12 inspired with Nette-specific modifications
136+
- Minimal but clear documentation
137+
138+
### Naming Conventions
139+
- PascalCase for class constants (modern style, e.g., `Parser::Optional`)
140+
- camelCase for methods and properties
141+
- Deprecated UPPERCASE constants aliased to PascalCase equivalents
142+
143+
### Documentation Style
144+
- Classes: Brief description without unnecessary verbosity (e.g., "Stupid command line arguments parser")
145+
- Methods: Document when adding value beyond type signatures
146+
- Properties: Inline `@var` annotations for complex types
147+
148+
## Testing with Nette Tester
149+
150+
### Test File Structure
151+
Files use `.phpt` extension and follow this pattern:
152+
153+
```php
154+
<?php
155+
156+
declare(strict_types=1);
157+
158+
use Nette\CommandLine\Parser;
159+
use Tester\Assert;
160+
161+
require __DIR__ . '/bootstrap.php';
162+
163+
164+
test('description of what is tested', function () {
165+
$cmd = new Parser('...');
166+
Assert::same(['expected'], $cmd->parse(['input']));
167+
});
168+
169+
170+
test('another test case', function () {
171+
// Test implementation
172+
});
173+
```
174+
175+
### Testing Patterns
176+
- Use `test()` function for each test case with clear descriptions
177+
- No comments before `test()` calls - the description parameter serves this purpose
178+
- Group related tests in the same file
179+
- Use `Assert::same()` for exact equality checks
180+
- Use `Assert::exception()` for exception testing
181+
182+
### Bootstrap Setup
183+
All tests require `require __DIR__ . '/bootstrap.php';` which:
184+
- Loads Composer autoloader
185+
- Configures Tester environment
186+
- Sets up test functions
187+
188+
## Version Management
189+
190+
**Current branch:** master (1.9-dev)
191+
**PHP Support:** 8.2 minimum, tested through 8.5
192+
**Branch alias:** dev-master → 1.9-dev
193+
194+
### Backward Compatibility
195+
- Deprecated constants maintained with `@deprecated` annotations
196+
- Old UPPERCASE constants aliased to new PascalCase versions
197+
- Breaking changes noted in commit messages with "(BC break)"
198+
199+
## Common Development Scenarios
200+
201+
### Adding Parser Features
202+
When extending the Parser class:
203+
1. Add new constants in PascalCase format
204+
2. Create UPPERCASE deprecated aliases if replacing old names
205+
3. Update help text regex in constructor if needed
206+
4. Add comprehensive tests in `tests/Parser.phpt`
207+
5. Consider enum validation and normalizer patterns
208+
209+
### Console Color Additions
210+
When modifying Console output:
211+
1. Respect `$this->useColors` flag
212+
2. Return plain strings when colors disabled
213+
3. Test with `NO_COLOR` / `FORCE_COLOR` environment variables
214+
4. Consider cross-platform compatibility (Windows VT100)
215+
5. When adding interactive-only features (progress bars, prompts), gate them on `detectTerminal()` rather than `detectColors()` — a user may want colors disabled via `NO_COLOR` but still have a usable progress indicator
216+
217+
### Test Writing
218+
1. Create or extend `.phpt` files in `tests/` directory
219+
2. Use descriptive test names in `test()` function
220+
3. Cover both success and error cases
221+
4. Test edge cases (empty input, missing values, invalid formats)
222+
223+
## Dependencies and Tooling
224+
225+
**Runtime:** None (PHP 8.2+ only)
226+
227+
**Development:**
228+
- `nette/tester` ^2.5 - Testing framework
229+
- `tracy/tracy` ^2.9 - Debugging and error handling
230+
- `phpstan/phpstan-nette` ^2.0 - Static analysis with Nette-specific rules
231+
232+
**Autoloading:**
233+
- PSR-4: `Nette\``src/`
234+
- Classmap fallback for `src/` directory

0 commit comments

Comments
 (0)