<?php
namespace App\Commands;
use App\Prompts\LiveSuggestPrompt;
use LaravelZero\Framework\Commands\Command;
class PijulSearchIntentTagsCommand extends Command
{
private const LIVE_RESULTS_SCROLL = 10;
/**
* @var string
*/
protected $signature = 'pijul:search-intent-tags
{query? : Text to search for in intent tags}
{--limit= : Number of recent log entries to scan}
{--exact : Match the whole tag instead of a substring}
{--repository= : Work with the repository at PATH}
{--channel= : Work with CHANNEL instead of the current channel}
{--no-prompt : Abort rather than prompt for input}';
/**
* @var string
*/
protected $description = 'Search intent tags extracted from pijul log messages';
/**
* @var array<int, string>
*/
protected $aliases = ['pijul-search-intent-tags'];
public function handle(PijulListIntentTagsCommand $listIntentTags): int
{
$query = trim((string) ($this->argument('query') ?? ''));
$tags = $listIntentTags->resolveTags(
limit: $this->option('limit'),
repository: $this->option('repository'),
channel: $this->option('channel'),
noPrompt: (bool) $this->option('no-prompt'),
);
if ($query === '' && $this->input->isInteractive()) {
$query = trim((string) (new LiveSuggestPrompt(
label: 'Search query',
options: fn (string $value): array => $this->suggestedTags($tags, $value),
placeholder: 'Type to filter intent tags...',
scroll: self::LIVE_RESULTS_SCROLL,
required: 'Please provide a search query.',
hint: 'Results update on each keypress. Use arrows to scroll, then press Enter.',
))->prompt());
}
if ($query === '') {
$this->error('Please provide a search query.');
return self::FAILURE;
}
$matches = array_values(array_filter(
$tags,
fn (string $tag): bool => $this->matchesQuery($tag, $query),
));
if ($matches === []) {
$this->warn('No matching intent tags found.');
return self::SUCCESS;
}
foreach ($matches as $match) {
$this->line($match);
}
return self::SUCCESS;
}
/**
* @param list<string> $tags
* @return list<string>
*/
private function suggestedTags(array $tags, string $query): array
{
$query = trim($query);
if ($query === '') {
return array_values($tags);
}
return array_values(array_filter(
$tags,
fn (string $tag): bool => str_contains(strtolower($tag), strtolower($query)),
));
}
private function matchesQuery(string $tag, string $query): bool
{
if ($this->option('exact')) {
return strcasecmp($tag, $query) === 0;
}
return str_contains(strtolower($tag), strtolower($query));
}
}