Skip to content
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

feat: add an open function #310

Merged
merged 1 commit into from Mar 6, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,7 @@
* Remove the default timeout of 60 seconds from the Context
* Add `bool` return type to `fingerprint()` function to indicate if the callable was run
* Add a `recursive` parameter to the `withData()` method of `Context` to allow recursive merging for nested arrays
* Add an `open()` function to open a file or URL in the default application

## 0.13.1 (2024-02-27)

Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Expand Up @@ -90,7 +90,7 @@ And run the tool to make your code compliant with
castor's static analysis checks:

```shell
tools/phpstan/vendor/bin/phpstan fix --config=phpstan.neon
tools/phpstan/vendor/bin/phpstan --configuration=phpstan.neon
```

## Update the Documentation
Expand Down
16 changes: 16 additions & 0 deletions doc/going-further/helpers/open.md
@@ -0,0 +1,16 @@
# Open URLs and files

Castor provides an `open()` function that will open one or more
URLs or files in the user's default application.

```php
use Castor\Attribute\AsTask;

use function Castor\open;

#[AsTask()]
function open()
{
open('https://castor.jolicode.com');
}
```
1 change: 1 addition & 0 deletions doc/reference.md
Expand Up @@ -27,6 +27,7 @@ Castor provides the following built-in functions:
- [`log`](going-further/interacting-with-castor/log.md#the-log-function)
- [`logger`](going-further/interacting-with-castor/log.md#the-logger-function)
- [`notify`](going-further/helpers/notify.md#the-notify-function)
- [`open`](going-further/helpers/open.md)
- [`output`](going-further/helpers/console-and-io.md#the-output-function)
- [`parallel`](going-further/helpers/parallel.md#the-parallel-function)
- [`request`](going-further/helpers/http-request.md#the-request-function)
Expand Down
19 changes: 19 additions & 0 deletions examples/open.php
@@ -0,0 +1,19 @@
<?php

namespace open;

use Castor\Attribute\AsTask;

use function Castor\open;

#[AsTask(description: 'Open Castor documentation in the default browser')]
function documentation(): void
{
open('https://castor.jolicode.com');
}

#[AsTask(description: 'Open an URL and a file in the default applications')]
function multiple(): void
{
open('https://castor.jolicode.com', 'examples/open.php');
}
2 changes: 1 addition & 1 deletion src/Exception/ExecutableNotFoundException.php
Expand Up @@ -7,6 +7,6 @@ class ExecutableNotFoundException extends \RuntimeException
public function __construct(
readonly string $executableName,
) {
parent::__construct("Executable {$executableName} not found. Please install it to use this feature.");
parent::__construct(sprintf('Executable "%s" not found. Please install it to use this feature.', $executableName));
}
}
23 changes: 23 additions & 0 deletions src/functions.php
Expand Up @@ -4,6 +4,7 @@

use Castor\Attribute\AsContextGenerator;
use Castor\Console\Application;
use Castor\Exception\ExecutableNotFoundException;
use Castor\Exception\MinimumVersionRequirementNotMetException;
use Castor\Exception\WaitFor\ExitedBeforeTimeoutException;
use Castor\Exception\WaitFor\TimeoutReachedException;
Expand All @@ -23,6 +24,7 @@
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\ExecutableFinder;
use Symfony\Component\Process\Process;
use Symfony\Component\Yaml\Yaml;
use Symfony\Contracts\Cache\CacheInterface;
Expand Down Expand Up @@ -1055,3 +1057,24 @@ function guard_min_version(string $minVersion): void
throw new MinimumVersionRequirementNotMetException($minVersion, $currentVersion);
}
}

function open(string ...$urls): void
{
$command = match (true) {
OsHelper::isMacOS() => 'open',
OsHelper::isWindows() => 'start',
default => 'xdg-open',
};

if (null === (new ExecutableFinder())->find($command)) {
throw new ExecutableNotFoundException($command);
}

$parallelCallbacks = [];

foreach ($urls as $url) {
$parallelCallbacks[] = fn () => run([$command, $url], quiet: true);
}

parallel(...$parallelCallbacks);
}
2 changes: 1 addition & 1 deletion tests/Examples/Generated/FilesystemFindTest.php.output.txt
@@ -1 +1 @@
Number of PHP files: 28
Number of PHP files: 29
2 changes: 2 additions & 0 deletions tests/Examples/Generated/ListTest.php.output.txt
Expand Up @@ -44,6 +44,8 @@ log:with-context Logs an "error
not-rename:renamed Task that was renamed
notify:notify-on-finish Sends a notification when the task finishes
notify:send-notify Sends a notification
open:documentation Open Castor documentation in the default browser
open:multiple Open an URL and a file in the default applications
output:output Plays with Symfony Style
parallel:exception Sleep and throw an exception
parallel:sleep Sleeps for 5, 7, and 10 seconds in parallel
Expand Down