about summary refs log tree commit homepage
path: root/lib/PublicInbox/LeiLsSearch.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2021-04-18 08:40:14 +0000
committerEric Wong <e@80x24.org>2021-04-18 19:04:42 -0400
commit2018db2a23ab1d949c757c264534f39dba338ccb (patch)
tree86a06bda17018b97d760d579aa7214f68e1ab42e /lib/PublicInbox/LeiLsSearch.pm
parent3b7b5442c4321ae802867cbda9bd33235ab2a5a3 (diff)
downloadpublic-inbox-2018db2a23ab1d949c757c264534f39dba338ccb.tar.gz
Going forward, we'll probably support JSON for all the "ls-*"
subcommands.  This also provides the basis for "lei up" shell
completion.
Diffstat (limited to 'lib/PublicInbox/LeiLsSearch.pm')
-rw-r--r--lib/PublicInbox/LeiLsSearch.pm109
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/PublicInbox/LeiLsSearch.pm b/lib/PublicInbox/LeiLsSearch.pm
new file mode 100644
index 00000000..2aa457c0
--- /dev/null
+++ b/lib/PublicInbox/LeiLsSearch.pm
@@ -0,0 +1,109 @@
+# 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->new($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 { -wq_nr_workers => 1, json => $json }, __PACKAGE__;
+        my ($op_c, $ops) = $lei->workers_start($self, 'ls-search', 1);
+        $lei->{lsss} = $self;
+        $self->wq_io_do('do_ls_search_long', [], $pfx);
+        $self->wq_close(1);
+        $op_c->op_wait_event($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;