Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 24 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Class library that can help in writing command line based applications with mini

<p align="center">
<a target="_blank" href="https://github.com/WebFiori/cli/actions/workflows/php84.yaml">
<img src="https://github.com/WebFiori/cli/actions/workflows/php83.yaml/badge.svg?branch=main">
<img src="https://github.com/WebFiori/cli/actions/workflows/php84.yaml/badge.svg?branch=main">
</a>
<a href="https://codecov.io/gh/WebFiori/cli">
<img src="https://codecov.io/gh/WebFiori/cli/branch/main/graph/badge.svg" />
Expand Down Expand Up @@ -104,13 +104,13 @@ exit(\$runner->start());
A complete sample application with multiple examples can be found here: **[📁 View Sample Application](https://github.com/WebFiori/cli/tree/main/examples)**

The sample application includes:
- **[Basic Commands](https://github.com/WebFiori/cli/tree/main/examples/01-basic-command)** - Simple command creation
- **[Arguments Handling](https://github.com/WebFiori/cli/tree/main/examples/02-command-with-args)** - Working with command arguments
- **[Interactive Mode](https://github.com/WebFiori/cli/tree/main/examples/03-interactive-mode)** - Building interactive applications
- **[Basic Commands](https://github.com/WebFiori/cli/tree/main/examples/01-basic-hello-world)** - Simple command creation
- **[Arguments Handling](https://github.com/WebFiori/cli/tree/main/examples/02-arguments-and-options)** - Working with command arguments
- **[User Input](https://github.com/WebFiori/cli/tree/main/examples/03-user-input)** - Building interactive applications
- **[Multi-Command Apps](https://github.com/WebFiori/cli/tree/main/examples/10-multi-command-app)** - Complex applications with multiple commands
- **[Progress Bars](https://github.com/WebFiori/cli/tree/main/examples/05-progress-bars)** - Visual progress indicators
- **[Progress Bars](https://github.com/WebFiori/cli/tree/main/examples/07-progress-bars)** - Visual progress indicators
- **[Table Display](https://github.com/WebFiori/cli/tree/main/examples/06-table-display)** - Formatting data in tables
- **[Testing Examples](https://github.com/WebFiori/cli/tree/main/examples/tests)** - Unit testing your commands
- **[Database Operations](https://github.com/WebFiori/cli/tree/main/examples/09-database-ops)** - Database CLI commands

## Installation

Expand Down Expand Up @@ -165,7 +165,7 @@ php app.php greet
# Output: Hello from WebFiori CLI!
```

**[📖 View Complete Example](https://github.com/WebFiori/cli/tree/main/examples/01-basic-command)**
**[📖 View Complete Example](https://github.com/WebFiori/cli/tree/main/examples/01-basic-hello-world)**

### Command with Arguments

Expand Down Expand Up @@ -210,7 +210,7 @@ php app.php greet-person --name=Sarah
# Output: Hello Friend Sarah!
```

**[📖 View Complete Example](https://github.com/WebFiori/cli/tree/main/examples/02-command-with-args)**
**[📖 View Complete Example](https://github.com/WebFiori/cli/tree/main/examples/02-arguments-and-options)**

### Multi-Command Application

Expand Down Expand Up @@ -394,7 +394,7 @@ This will show following output in terminal:
>>
```

**[📖 View Interactive Mode Example](https://github.com/WebFiori/cli/tree/main/examples/03-interactive-mode)**
**[📖 View Interactive Mode Example](https://github.com/WebFiori/cli/tree/main/examples/05-interactive-commands)**

### Input and Output Streams

Expand All @@ -411,7 +411,7 @@ $command->setInputStream(new FileInputStream('input.txt'));
$command->setOutputStream(new FileOutputStream('output.txt'));
```

**[📖 View Streams Example](https://github.com/WebFiori/cli/tree/main/examples/04-custom-streams)**
**[📖 View Streams Example](https://github.com/WebFiori/cli/tree/main/examples/08-file-processing)**

### ANSI Colors and Formatting

Expand All @@ -427,7 +427,7 @@ public function exec(): int {
}
```

**[📖 View Formatting Example](https://github.com/WebFiori/cli/tree/main/examples/07-ansi-formatting)**
**[📖 View Formatting Example](https://github.com/WebFiori/cli/tree/main/examples/04-output-formatting)**

### Progress Bars

Expand All @@ -449,7 +449,7 @@ public function exec(): int {
}
```

**[📖 View Progress Bar Example](https://github.com/WebFiori/cli/tree/main/examples/05-progress-bars)**
**[📖 View Progress Bar Example](https://github.com/WebFiori/cli/tree/main/examples/07-progress-bars)**

### Table Display

Expand All @@ -458,8 +458,8 @@ Display data in formatted tables:
```php
public function exec(): int {
$data = [
['John Doe', 30, 'New York'],
['Jane Smith', 25, 'Los Angeles']
['Ahmed Hassan', 30, 'Cairo'],
['Sarah Johnson', 25, 'Los Angeles']
];
$headers = ['Name', 'Age', 'City'];

Expand Down Expand Up @@ -593,34 +593,33 @@ class HelloCommandTest extends CommandTestCase {

```

**[📖 View Testing Examples](https://github.com/WebFiori/cli/tree/main/examples/tests)**
**[📖 View Testing Examples](https://github.com/WebFiori/cli/tree/main/examples/10-multi-command-app)**

## Examples

Explore comprehensive examples to learn different aspects of WebFiori CLI:

### Basic Examples
- **[📁 Basic Command](https://github.com/WebFiori/cli/tree/main/examples/01-basic-command)** - Create your first CLI command
- **[📁 Command with Arguments](https://github.com/WebFiori/cli/tree/main/examples/02-command-with-args)** - Handle command-line arguments
- **[📁 Interactive Mode](https://github.com/WebFiori/cli/tree/main/examples/03-interactive-mode)** - Build interactive CLI applications
- **[📁 Basic Command](https://github.com/WebFiori/cli/tree/main/examples/01-basic-hello-world)** - Create your first CLI command
- **[📁 Command with Arguments](https://github.com/WebFiori/cli/tree/main/examples/02-arguments-and-options)** - Handle command-line arguments
- **[📁 User Input](https://github.com/WebFiori/cli/tree/main/examples/03-user-input)** - Read and validate user input
- **[📁 Output Formatting](https://github.com/WebFiori/cli/tree/main/examples/04-output-formatting)** - Colors and text formatting

### Advanced Examples
- **[📁 Custom Streams](https://github.com/WebFiori/cli/tree/main/examples/04-custom-streams)** - Custom input/output handling
- **[📁 Progress Bars](https://github.com/WebFiori/cli/tree/main/examples/05-progress-bars)** - Visual progress indicators
- **[📁 Interactive Commands](https://github.com/WebFiori/cli/tree/main/examples/05-interactive-commands)** - Build interactive CLI applications
- **[📁 Table Display](https://github.com/WebFiori/cli/tree/main/examples/06-table-display)** - Format data in tables
- **[📁 ANSI Formatting](https://github.com/WebFiori/cli/tree/main/examples/07-ansi-formatting)** - Colors and text formatting
- **[📁 Progress Bars](https://github.com/WebFiori/cli/tree/main/examples/07-progress-bars)** - Visual progress indicators
- **[📁 File Processing](https://github.com/WebFiori/cli/tree/main/examples/08-file-processing)** - File manipulation commands
- **[📁 Database Operations](https://github.com/WebFiori/cli/tree/main/examples/09-database-ops)** - Database CLI commands

### Complete Applications
- **[📁 Multi-Command Application](https://github.com/WebFiori/cli/tree/main/examples/10-multi-command-app)** - Full-featured CLI application
- **[📁 Testing Suite](https://github.com/WebFiori/cli/tree/main/examples/tests)** - Unit testing examples

### Quick Links
- **[📖 All Examples](https://github.com/WebFiori/cli/tree/main/examples)** - Browse all available examples
- **[🧪 Test Examples](https://github.com/WebFiori/cli/tree/main/examples/tests/HelloCommandTest.php)** - See how to test your commands
- **[🚀 Sample App](https://github.com/WebFiori/cli/tree/main/examples/10-multi-command-app/app.php)** - Ready-to-run sample application
- **[🚀 Sample App](https://github.com/WebFiori/cli/tree/main/examples/10-multi-command-app/main.php)** - Ready-to-run sample application


---

**Ready to build amazing CLI applications? Start with the [📁 Basic Command Example](https://github.com/WebFiori/cli/tree/main/examples/01-basic-command) and work your way up!**
**Ready to build amazing CLI applications? Start with the [📁 Basic Command Example](https://github.com/WebFiori/cli/tree/main/examples/01-basic-hello-world) and work your way up!**
33 changes: 31 additions & 2 deletions WebFiori/Cli/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,24 @@ public function getInput(string $prompt, ?string $default = null, ?InputValidato
public function getInputStream() : InputStream {
return $this->inputStream;
}

/**
* Check if the current input stream supports interactive input.
*
* @return bool True if the input stream supports interactive input (real-time user interaction),
* false otherwise (files, pipes, arrays, etc.)
*/
public function supportsInteractiveInput(): bool {
$stream = $this->getInputStream();

// Only StdIn with tty supports true interaction
if ($stream instanceof Streams\StdIn) {
return function_exists('posix_isatty') && posix_isatty(STDIN);
}

// All other stream types are non-interactive
return false;
}
/**
* Returns the name of the command.
*
Expand Down Expand Up @@ -1017,12 +1035,18 @@ public function removeArgument(string $name) : bool {
* @param int $defaultIndex The index of the default value in case no value
* is selected and the user hit enter.
*
* * @param int $maxTrials The maximum number of trials the user can do to select
* a value. If -1 is passed, the user can select a value forever.
*
* @return string|null The method will return the value which is selected by
* the user. If choices array is empty, null is returned.
* the user. If choices array is empty, null is returned. Also, null is returned
* if max trials is reached and it is not -1.
*
*
*/
public function select(string $prompt, array $choices, int $defaultIndex = -1): ?string {
public function select(string $prompt, array $choices, int $defaultIndex = -1, int $maxTrials = -1): ?string {
if (count($choices) != 0) {
$currentTry = 0;
do {
$this->println($prompt, [
'color' => 'gray',
Expand All @@ -1037,6 +1061,11 @@ public function select(string $prompt, array $choices, int $defaultIndex = -1):
if ($check !== null) {
return $check;
}
$currentTry++;

if ($currentTry == $maxTrials && $maxTrials > 0) {
return null;
}
} while (true);
}

Expand Down
12 changes: 11 additions & 1 deletion WebFiori/Cli/KeysMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,17 @@ class KeysMap {
*
* </ul>
*/
public static function map(string $ch) : string {
public static function map($ch) : string {
// Handle end-of-stream case for any input type
if ($ch === false || $ch === null) {
return "\n"; // Treat as Enter key
}

// Ensure we have a string
if (!is_string($ch)) {
$ch = (string)$ch;
}

$keyMap = self::KEY_MAP;

if (isset($keyMap[$ch])) {
Expand Down
2 changes: 1 addition & 1 deletion examples/01-basic-hello-world/HelloCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function exec(): int {
// Special greeting for WebFiori
if (strtolower($name) === 'webfiori') {
$this->success("🎉 Hello, $name! Welcome to the CLI world!");
$this->info('You\'re using the WebFiori CLI library - great choice!');
$this->info('You\'re using the WebFiori CLI library.');
} else {
// Standard greeting
$this->println("Hello, $name! 👋");
Expand Down
Loading