]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/LeiLsSearch.pm
imap+nntp: share COMPRESS implementation
[public-inbox.git] / lib / PublicInbox / LeiLsSearch.pm
1 # Copyright (C) 2021 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # "lei ls-search" to display results saved via "lei q --save"
5 package PublicInbox::LeiLsSearch;
6 use strict;
7 use v5.10.1;
8 use PublicInbox::LeiSavedSearch;
9 use parent qw(PublicInbox::IPC);
10
11 sub do_ls_search_long {
12         my ($self, $pfx) = @_;
13         # TODO: share common JSON output code with LeiOverview
14         my $json = $self->{json}->new->utf8->canonical;
15         my $lei = $self->{lei};
16         $json->ascii(1) if $lei->{opt}->{ascii};
17         my $fmt = $lei->{opt}->{'format'};
18         $lei->{1}->autoflush(0);
19         my $ORS = "\n";
20         my $pretty = $lei->{opt}->{pretty};
21         my $EOR;  # TODO: compact pretty like "lei q"
22         if ($fmt =~ /\A(concat)?json\z/ && $pretty) {
23                 $EOR = ($1//'') eq 'concat' ? "\n}" : "\n},";
24         }
25         if ($fmt eq 'json') {
26                 $lei->out('[');
27                 $ORS = ",\n";
28         }
29         my @x = sort(grep(/\A\Q$pfx/, PublicInbox::LeiSavedSearch::list($lei)));
30         while (my $x = shift @x) {
31                 $ORS = '' if !scalar(@x);
32                 my $lss = PublicInbox::LeiSavedSearch->up($lei, $x) or next;
33                 my $cfg = $lss->{-cfg};
34                 my $ent = {
35                         q => $cfg->get_all('lei.q'),
36                         output => $cfg->{'lei.q.output'},
37                 };
38                 for my $k ($lss->ARRAY_FIELDS) {
39                         my $ary = $cfg->get_all("lei.q.$k") // next;
40                         $ent->{$k} = $ary;
41                 }
42                 for my $k ($lss->BOOL_FIELDS) {
43                         my $val = $cfg->{"lei.q.$k"} // next;
44                         $ent->{$k} = $val;
45                 }
46                 if (defined $EOR) { # pretty, but compact
47                         $EOR = "\n}" if !scalar(@x);
48                         my $buf = "{\n";
49                         $buf .= join(",\n", map {;
50                                 my $f = $_;
51                                 if (my $v = $ent->{$f}) {
52                                         $v = $json->encode([$v]);
53                                         qq{  "$f": }.substr($v, 1, -1);
54                                 } else {
55                                         ();
56                                 }
57                         # key order by importance
58                         } (qw(output q), $lss->ARRAY_FIELDS,
59                                 $lss->BOOL_FIELDS) );
60                         $lei->out($buf .= $EOR);
61                 } else {
62                         $lei->out($json->encode($ent), $ORS);
63                 }
64         }
65         if ($fmt eq 'json') {
66                 $lei->out("]\n");
67         } elsif ($fmt eq 'concatjson') {
68                 $lei->out("\n");
69         }
70 }
71
72 sub bg_worker ($$$) {
73         my ($lei, $pfx, $json) = @_;
74         my $self = bless { json => $json }, __PACKAGE__;
75         my ($op_c, $ops) = $lei->workers_start($self, 1);
76         $lei->{wq1} = $self;
77         $self->wq_io_do('do_ls_search_long', [], $pfx);
78         $self->wq_close;
79         $lei->wait_wq_events($op_c, $ops);
80 }
81
82 sub lei_ls_search {
83         my ($lei, $pfx) = @_;
84         my $fmt = $lei->{opt}->{'format'} // '';
85         if ($lei->{opt}->{l}) {
86                 $lei->{opt}->{'format'} //= $fmt = 'json';
87         }
88         my $json;
89         my $tty = -t $lei->{1};
90         $lei->start_pager if $tty;
91         if ($fmt =~ /\A(ldjson|ndjson|jsonl|(?:concat)?json)\z/) {
92                 $lei->{opt}->{pretty} //= $tty;
93                 $json = ref(PublicInbox::Config->json);
94         } elsif ($fmt ne '') {
95                 return $lei->fail("unknown format: $fmt");
96         }
97         my $ORS = "\n";
98         if ($lei->{opt}->{z}) {
99                 return $lei->fail('-z and --format do not mix') if $json;
100                 $ORS = "\0";
101         }
102         $pfx //= '';
103         return bg_worker($lei, $pfx, $json) if $json;
104         for (sort(grep(/\A\Q$pfx/, PublicInbox::LeiSavedSearch::list($lei)))) {
105                 $lei->out($_, $ORS);
106         }
107 }
108
109 1;