diff options
-rw-r--r-- | lib/PublicInbox/LEI.pm | 45 | ||||
-rw-r--r-- | lib/PublicInbox/LeiToMail.pm | 4 | ||||
-rw-r--r-- | lib/PublicInbox/LeiXSearch.pm | 4 |
3 files changed, 45 insertions, 8 deletions
diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm index c265971f..61f2a65b 100644 --- a/lib/PublicInbox/LEI.pm +++ b/lib/PublicInbox/LEI.pm @@ -83,7 +83,7 @@ sub _config_path ($) { our %CMD = ( # sorted in order of importance/use: 'q' => [ 'SEARCH_TERMS...', 'search for messages matching terms', qw( save-as=s output|mfolder|o=s format|f=s dedupe|d=s thread|t augment|a - sort|s=s reverse|r offset=i remote local! external! pretty + sort|s=s reverse|r offset=i remote local! external! pretty mua-cmd=s since|after=s until|before=s), opt_dash('limit|n=i', '[0-9]+') ], 'show' => [ 'MID|OID', 'show a given object (Message-ID or object ID)', @@ -192,6 +192,8 @@ my %OPTDESC = ( 'output|o=s' => [ 'DEST', "destination (e.g. `/path/to/Maildir', or `-' for stdout)" ], +'mua-cmd|mua=s' => [ 'COMMAND', + "MUA to run on --output Maildir or mbox (e.g. `mutt -f %f'" ], 'show format|f=s' => [ 'OUT|plain|raw|html|mboxrd|mboxcl2|mboxcl', 'message/object output format' ], @@ -635,6 +637,32 @@ sub lei_git { # support passing through random git commands dwaitpid($pid, \&reap_exec, $self); } +sub exec_buf ($$) { + my ($argv, $env) = @_; + my $argc = scalar @$argv; + my $buf = 'exec '.join("\0", scalar(@$argv), @$argv); + while (my ($k, $v) = each %$env) { $buf .= "\0$k=$v" }; + $buf; +} + +sub start_mua { + my ($self, $sock) = @_; + my $mua = $self->{opt}->{'mua-cmd'} // return; + my $mfolder = $self->{ovv}->{dst}; + require Text::ParseWords; + my $replaced; + my @cmd = Text::ParseWords::shellwords($mua); + # mutt uses '%f' for open-hook with compressed folders, so we use %f + @cmd = map { $_ eq '%f' ? ($replaced = $mfolder) : $_ } @cmd; + push @cmd, $mfolder unless defined($replaced); + $sock //= $self->{sock}; + if ($sock) { # lei(1) client process runs it + send($sock, exec_buf(\@cmd, {}), MSG_EOR); + } else { # oneshot + $self->{"mua.pid.$self.$$"} = spawn(\@cmd); + } +} + # caller needs to "-t $self->{1}" to check if tty sub start_pager { my ($self) = @_; @@ -644,19 +672,17 @@ sub start_pager { close($fh) or warn "`git var PAGER' error: \$?=$?"; return if $pager eq 'cat' || $pager eq ''; # TODO TIOCGWINSZ - my %new_env = (LESS => 'FRX', LV => '-c', COLUMNS => 80); - $new_env{MORE} = 'FRX' if $^O eq 'freebsd'; + my $new_env = { LESS => 'FRX', LV => '-c', COLUMNS => 80 }; + $new_env->{MORE} = 'FRX' if $^O eq 'freebsd'; pipe(my ($r, $wpager)) or return warn "pipe: $!"; my $rdr = { 0 => $r, 1 => $self->{1}, 2 => $self->{2} }; my $pgr = [ undef, @$rdr{1, 2}, $$ ]; if (my $sock = $self->{sock}) { # lei(1) process runs it - delete @new_env{keys %$env}; # only set iff unset - my $buf = "exec 1\0".$pager; - while (my ($k, $v) = each %new_env) { $buf .= "\0$k=$v" }; + delete @$new_env{keys %$env}; # only set iff unset my $fds = [ map { fileno($_) } @$rdr{0..2} ]; - $send_cmd->($sock, $fds, $buf, MSG_EOR); + $send_cmd->($sock, $fds, exec_buf([$pager], $new_env), MSG_EOR); } else { - $pgr->[0] = spawn([$pager], \%new_env, $rdr); + $pgr->[0] = spawn([$pager], $new_env, $rdr); } $self->{1} = $wpager; $self->{2} = $wpager if -t $self->{2}; @@ -892,6 +918,9 @@ sub DESTROY { my ($self) = @_; $self->{1}->autoflush(1) if $self->{1}; stop_pager($self); + if (my $mua_pid = delete $self->{"mua.pid.$self.$$"}) { + waitpid($mua_pid, 0); + } } 1; diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm index 744f331d..0e23b8da 100644 --- a/lib/PublicInbox/LeiToMail.pm +++ b/lib/PublicInbox/LeiToMail.pm @@ -418,4 +418,8 @@ sub post_augment { # fast (spawn compressor or mkdir), runs in main daemon $self->$m($lei); } +sub lock_free { + $_[0]->{base_type} =~ /\A(?:maildir|mh|imap|jmap)\z/ ? 1 : 0; +} + 1; diff --git a/lib/PublicInbox/LeiXSearch.pm b/lib/PublicInbox/LeiXSearch.pm index 9563ad63..91864cd0 100644 --- a/lib/PublicInbox/LeiXSearch.pm +++ b/lib/PublicInbox/LeiXSearch.pm @@ -172,6 +172,9 @@ sub git { sub query_done { # EOF callback my ($lei) = @_; $lei->{ovv}->ovv_end($lei); + if (my $l2m = $lei->{l2m}) { + $lei->start_mua unless $l2m->lock_free; + } $lei->dclose; } @@ -181,6 +184,7 @@ sub start_query { # always runs in main (lei-daemon) process $lei->{1} = $io->[1]; $l2m->post_augment($lei); $io->[1] = delete $lei->{1}; + $lei->start_mua($io->[3]) if $l2m->lock_free; } my $remotes = $self->{remotes} // []; if ($lei->{opt}->{thread}) { |