| # Copyright (C) 2021 all contributors <meta@public-inbox.org> |
| # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> |
| |
| # "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; |