From 2018db2a23ab1d949c757c264534f39dba338ccb Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 18 Apr 2021 08:40:14 +0000 Subject: lei ls-search: command to list saved searches Going forward, we'll probably support JSON for all the "ls-*" subcommands. This also provides the basis for "lei up" shell completion. --- lib/PublicInbox/LeiLsSearch.pm | 109 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 lib/PublicInbox/LeiLsSearch.pm (limited to 'lib/PublicInbox/LeiLsSearch.pm') 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 +# 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->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; -- cgit v1.2.3-24-ge0c7