feat(pijul-qol:move-to-zero): two new commands, to try make intent-tag discovery easier

Chasesomero
Mar 6, 2026, 3:50 PM
WNLMHTPQCWCZD7URTMIATDAT2HJZJPF77C2CN22S43DRKCHUI3HAC

Dependencies

  • [2] 32ICZXL4 init laravel zero for fun
  • [3] 3JSFZAT5 bit of copilot proofreading and editing
  • [4] ZHWYHIOH feat(pijul-qol): have copilot make script to show change messages beside changes, in pijul credit output
  • [5] F435FWSF feat(pijul-qol:move-to-zero): move to laravel zero, why not?

Change contents

  • file addition: PijulSearchIntentTagsCommandTest.php (----------)
    [2.1888]
    <?php
    use Illuminate\Process\PendingProcess;
    use Illuminate\Support\Facades\Process;
    it('searches intent tags using the list command logic and passes through the limit', function () {
    Process::fake(function (PendingProcess $process) {
    return match ($process->command) {
    ['pijul', 'log', '--output-format', 'json', '--limit', '50'] => Process::result(json_encode([
    ['message' => 'feat(pijul-qol): first'],
    ['message' => 'feat(pijul-qol:move-to-zero): second'],
    ['message' => 'fix(cli): third'],
    ], JSON_THROW_ON_ERROR)),
    default => Process::result('', 'Unexpected command.', 1),
    };
    });
    $this->artisan('pijul:search-intent-tags', [
    'query' => 'zero',
    '--limit' => '50',
    ])
    ->expectsOutput('feat(pijul-qol:move-to-zero)')
    ->assertExitCode(0);
    Process::assertRanTimes(fn (PendingProcess $process) => $process->command === [
    'pijul',
    'log',
    '--output-format',
    'json',
    '--limit',
    '50',
    ], 1);
    });
    it('can search for an exact tag match', function () {
    Process::fake(function (PendingProcess $process) {
    return match ($process->command) {
    ['pijul', 'log', '--output-format', 'json'] => Process::result(json_encode([
    ['message' => 'feat(pijul-qol): first'],
    ['message' => 'feat(pijul-qol:move-to-zero): second'],
    ], JSON_THROW_ON_ERROR)),
    default => Process::result('', 'Unexpected command.', 1),
    };
    });
    $this->artisan('pijul:search-intent-tags', [
    'query' => 'feat(pijul-qol)',
    '--exact' => true,
    ])
    ->expectsOutput('feat(pijul-qol)')
    ->assertExitCode(0);
    });
  • replacement in tests/Feature/PijulRecordWithIntentTagsCommandTest.php at line 9
    [5.295][5.295:402]()
    ['pijul', 'log', '--limit', '500', '--output-format', 'json'] => Process::result(json_encode([
    [5.295]
    [5.402]
    ['pijul', 'log', '--output-format', 'json', '--limit', '500'] => Process::result(json_encode([
  • replacement in tests/Feature/PijulRecordWithIntentTagsCommandTest.php at line 31
    [5.1247][5.1247:1354]()
    ['pijul', 'log', '--limit', '500', '--output-format', 'json'] => Process::result(json_encode([
    [5.1247]
    [5.1354]
    ['pijul', 'log', '--output-format', 'json', '--limit', '500'] => Process::result(json_encode([
  • replacement in tests/Feature/PijulRecordWithIntentTagsCommandTest.php at line 50
    [5.2183][5.2183:2290]()
    ['pijul', 'log', '--limit', '500', '--output-format', 'json'] => Process::result(json_encode([
    [5.2183]
    [5.2290]
    ['pijul', 'log', '--output-format', 'json', '--limit', '500'] => Process::result(json_encode([
  • file addition: PijulListIntentTagsCommandTest.php (----------)
    [2.1888]
    <?php
    use Illuminate\Process\PendingProcess;
    use Illuminate\Support\Facades\Process;
    it('lists unique intent tags and respects the limit option', function () {
    Process::fake(function (PendingProcess $process) {
    return match ($process->command) {
    ['pijul', 'log', '--output-format', 'json', '--limit', '2'] => Process::result(json_encode([
    ['message' => 'feat(pijul-qol): first'],
    ['message' => 'feat(init): second'],
    ['message' => 'feat(pijul-qol): duplicate'],
    ['message' => 'plain message'],
    ], JSON_THROW_ON_ERROR)),
    default => Process::result('', 'Unexpected command.', 1),
    };
    });
    $this->artisan('pijul:list-intent-tags', ['--limit' => '2'])
    ->expectsOutput('feat(pijul-qol)')
    ->expectsOutput('feat(init)')
    ->assertExitCode(0);
    });
  • file addition: PijulSearchIntentTagsCommand.php (----------)
    [2.310659]
    <?php
    namespace App\Commands;
    use LaravelZero\Framework\Commands\Command;
    class PijulSearchIntentTagsCommand extends Command
    {
    /**
    * @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') ?? ''));
    if ($query === '' && $this->input->isInteractive()) {
    $query = trim((string) $this->ask('Search query'));
    }
    if ($query === '') {
    $this->error('Please provide a search query.');
    return self::FAILURE;
    }
    $tags = $listIntentTags->resolveTags(
    limit: $this->option('limit'),
    repository: $this->option('repository'),
    channel: $this->option('channel'),
    noPrompt: (bool) $this->option('no-prompt'),
    );
    $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;
    }
    private function matchesQuery(string $tag, string $query): bool
    {
    if ($this->option('exact')) {
    return strcasecmp($tag, $query) === 0;
    }
    return str_contains(strtolower($tag), strtolower($query));
    }
    }
  • edit in app/Commands/PijulRecordWithIntentTagsCommand.php at line 6
    [5.8404][5.8404:8423]()
    use JsonException;
  • replacement in app/Commands/PijulRecordWithIntentTagsCommand.php at line 44
    [5.10163][5.10163:10242]()
    /**
    * @throws JsonException
    */
    public function handle(): int
    [5.10163]
    [5.10242]
    public function handle(PijulListIntentTagsCommand $listIntentTags): int
  • replacement in app/Commands/PijulRecordWithIntentTagsCommand.php at line 46
    [5.10248][5.10248:10292]()
    $tags = $this->collectIntentTags();
    [5.10248]
    [5.10292]
    $tags = $listIntentTags->resolveTags(
    limit: (string) $this->option('tag-limit'),
    repository: $this->option('repository'),
    channel: $this->option('channel'),
    noPrompt: (bool) $this->option('no-prompt'),
    );
  • edit in app/Commands/PijulRecordWithIntentTagsCommand.php at line 95
    [5.11473][5.11473:11784]()
    /**
    * @return list<string>
    *
    * @throws JsonException
    */
    private function collectIntentTags(): array
    {
    $arguments = [
    'log',
    '--limit',
    (string) $this->option('tag-limit'),
    '--output-format',
    'json',
    ];
  • edit in app/Commands/PijulRecordWithIntentTagsCommand.php at line 96
    [5.11785][5.11785:12637]()
    foreach (['repository', 'channel'] as $option) {
    $value = $this->option($option);
    if ($value !== null) {
    $arguments[] = sprintf('--%s', $option);
    $arguments[] = (string) $value;
    }
    }
    if ($this->option('no-prompt')) {
    $arguments[] = '--no-prompt';
    }
    $result = $this->runPijul($arguments);
    $changes = json_decode($result->output(), true, 512, JSON_THROW_ON_ERROR);
    $tags = [];
    foreach ($changes as $change) {
    $message = $change['message'] ?? null;
    if (! is_string($message) || preg_match('/^([A-Za-z0-9_-]+\([^)]*\))/', $message, $matches) !== 1) {
    continue;
    }
    $tags[$matches[1]] = true;
    }
    return array_keys($tags);
    }
  • file addition: PijulListIntentTagsCommand.php (----------)
    [2.310659]
    <?php
    namespace App\Commands;
    use App\Commands\Concerns\InteractsWithPijul;
    use JsonException;
    use LaravelZero\Framework\Commands\Command;
    class PijulListIntentTagsCommand extends Command
    {
    use InteractsWithPijul;
    /**
    * @var string
    */
    protected $signature = 'pijul:list-intent-tags
    {--limit= : Number of recent log entries to scan}
    {--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 = 'List unique intent tags from pijul log messages';
    /**
    * @var array<int, string>
    */
    protected $aliases = ['pijul-list-intent-tags'];
    /**
    * @throws JsonException
    */
    public function handle(): int
    {
    foreach ($this->resolveTags(
    limit: $this->option('limit'),
    repository: $this->option('repository'),
    channel: $this->option('channel'),
    noPrompt: (bool) $this->option('no-prompt'),
    ) as $tag) {
    $this->line($tag);
    }
    return self::SUCCESS;
    }
    /**
    * @return list<string>
    *
    * @throws JsonException
    */
    public function resolveTags(
    ?string $limit = null,
    ?string $repository = null,
    ?string $channel = null,
    bool $noPrompt = false,
    ): array {
    $arguments = ['log', '--output-format', 'json'];
    if ($limit !== null && $limit !== '') {
    $arguments[] = '--limit';
    $arguments[] = $limit;
    }
    if ($repository !== null && $repository !== '') {
    $arguments[] = '--repository';
    $arguments[] = $repository;
    }
    if ($channel !== null && $channel !== '') {
    $arguments[] = '--channel';
    $arguments[] = $channel;
    }
    if ($noPrompt) {
    $arguments[] = '--no-prompt';
    }
    $changes = json_decode(
    $this->runPijul($arguments)->output(),
    true,
    512,
    JSON_THROW_ON_ERROR,
    );
    $tags = [];
    foreach ($changes as $change) {
    $message = $change['message'] ?? null;
    if (! is_string($message) || preg_match('/^([A-Za-z0-9_-]+\([^)]*\))/', $message, $matches) !== 1) {
    continue;
    }
    $tags[$matches[1]] = true;
    }
    return array_keys($tags);
    }
    }
  • edit in README.md at line 32
    [4.227]
    [4.227]
    ## Pijul intent tag listing and search
    Use `./pijultester pijul:list-intent-tags` to print one unique intent tag per line, which makes it easy to pipe into shell tools.
    Use `./pijultester pijul:search-intent-tags` for built-in substring search over those tags.
    Examples:
  • edit in README.md at line 41
    [4.228]
    [3.0]
    ```bash
    ./pijultester pijul:list-intent-tags
    ./pijultester pijul:list-intent-tags --limit=50 | fzf
    ./pijultester pijul:search-intent-tags zero --limit=50
    ./pijultester pijul:search-intent-tags 'feat(pijul-qol)' --exact
    ```