# Copyright (C) 2021 all contributors
# License: AGPL-3.0+
# "lei ls-search" to display results saved via "lei q --save"
package PublicInbox::LeiLsSearch;
use strict;
use v5.10.1;
use PublicInbox::LeiSavedSearch;
use parent qw(PublicInbox::IPC);
sub do_ls_search_long {
my ($self, $pfx) = @_;
# TODO: share common JSON output code with LeiOverview
my $json = $self->{json}->new->utf8->canonical;
my $lei = $self->{lei};
$json->ascii(1) if $lei->{opt}->{ascii};
my $fmt = $lei->{opt}->{'format'};
$lei->{1}->autoflush(0);
my $ORS = "\n";
my $pretty = $lei->{opt}->{pretty};
my $EOR; # TODO: compact pretty like "lei q"
if ($fmt =~ /\A(concat)?json\z/ && $pretty) {
$EOR = ($1//'') eq 'concat' ? "\n}" : "\n},";
}
if ($fmt eq 'json') {
$lei->out('[');
$ORS = ",\n";
}
my @x = sort(grep(/\A\Q$pfx/, PublicInbox::LeiSavedSearch::list($lei)));
while (my $x = shift @x) {
$ORS = '' if !scalar(@x);
my $lss = PublicInbox::LeiSavedSearch->up($lei, $x) or next;
my $cfg = $lss->{-cfg};
my $ent = {
q => $cfg->get_all('lei.q'),
output => $cfg->{'lei.q.output'},
};
for my $k ($lss->ARRAY_FIELDS) {
my $ary = $cfg->get_all("lei.q.$k") // next;
$ent->{$k} = $ary;
}
for my $k ($lss->BOOL_FIELDS) {
my $val = $cfg->{"lei.q.$k"} // next;
$ent->{$k} = $val;
}
if (defined $EOR) { # pretty, but compact
$EOR = "\n}" if !scalar(@x);
my $buf = "{\n";
$buf .= join(",\n", map {;
my $f = $_;
if (my $v = $ent->{$f}) {
$v = $json->encode([$v]);
qq{ "$f": }.substr($v, 1, -1);
} else {
();
}
# key order by importance
} (qw(output q), $lss->ARRAY_FIELDS,
$lss->BOOL_FIELDS) );
$lei->out($buf .= $EOR);
} else {
$lei->out($json->encode($ent), $ORS);
}
}
if ($fmt eq 'json') {
$lei->out("]\n");
} elsif ($fmt eq 'concatjson') {
$lei->out("\n");
}
}
sub bg_worker ($$$) {
my ($lei, $pfx, $json) = @_;
my $self = bless { json => $json }, __PACKAGE__;
my ($op_c, $ops) = $lei->workers_start($self, 1);
$lei->{wq1} = $self;
$self->wq_io_do('do_ls_search_long', [], $pfx);
$self->wq_close;
$lei->wait_wq_events($op_c, $ops);
}
sub lei_ls_search {
my ($lei, $pfx) = @_;
my $fmt = $lei->{opt}->{'format'} // '';
if ($lei->{opt}->{l}) {
$lei->{opt}->{'format'} //= $fmt = 'json';
}
my $json;
my $tty = -t $lei->{1};
$lei->start_pager if $tty;
if ($fmt =~ /\A(ldjson|ndjson|jsonl|(?:concat)?json)\z/) {
$lei->{opt}->{pretty} //= $tty;
$json = ref(PublicInbox::Config->json);
} elsif ($fmt ne '') {
return $lei->fail("unknown format: $fmt");
}
my $ORS = "\n";
if ($lei->{opt}->{z}) {
return $lei->fail('-z and --format do not mix') if $json;
$ORS = "\0";
}
$pfx //= '';
return bg_worker($lei, $pfx, $json) if $json;
for (sort(grep(/\A\Q$pfx/, PublicInbox::LeiSavedSearch::list($lei)))) {
$lei->out($_, $ORS);
}
}
1;