+sub start_mua {
+ my ($self) = @_;
+ my $mua = $self->{opt}->{'mua-cmd'} // return;
+ my $mfolder = $self->{ovv}->{dst};
+ my (@cmd, $replaced);
+ if ($mua =~ /\A(?:mutt|mailx|mail|neomutt)\z/) {
+ @cmd = ($mua, '-f');
+ # TODO: help wanted: other common FOSS MUAs
+ } else {
+ require Text::ParseWords;
+ my @cmd = Text::ParseWords::shellwords($mua);
+ # mutt uses '%f' for open-hook with compressed mbox, we follow
+ @cmd = map { $_ eq '%f' ? ($replaced = $mfolder) : $_ } @cmd;
+ }
+ push @cmd, $mfolder unless defined($replaced);
+ if (my $sock = $self->{sock}) { # lei(1) client process runs it
+ send($sock, exec_buf(\@cmd, {}), MSG_EOR);
+ } elsif ($self->{oneshot}) {
+ $self->{"mua.pid.$self.$$"} = spawn(\@cmd);
+ }
+ delete $self->{-progress};
+}
+
+# caller needs to "-t $self->{1}" to check if tty
+sub start_pager {
+ my ($self) = @_;
+ my $env = $self->{env};
+ my $fh = popen_rd([qw(git var GIT_PAGER)], $env);
+ chomp(my $pager = <$fh> // '');
+ 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';
+ 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 $fds = [ map { fileno($_) } @$rdr{0..2} ];
+ $send_cmd->($sock, $fds, exec_buf([$pager], $new_env), MSG_EOR);
+ } elsif ($self->{oneshot}) {
+ $pgr->[0] = spawn([$pager], $new_env, $rdr);
+ $pgr->[3] = $$; # ew'll reap it
+ } else {
+ die 'BUG: start_pager w/o socket';
+ }
+ $self->{1} = $wpager;
+ $self->{2} = $wpager if -t $self->{2};
+ $env->{GIT_PAGER_IN_USE} = 'true'; # we may spawn git
+ $self->{pgr} = $pgr;
+}
+
+sub stop_pager {
+ my ($self) = @_;
+ my $pgr = delete($self->{pgr}) or return;
+ $self->{2} = $pgr->[2];
+ # do not restore original stdout, just close it so we error out
+ close(delete($self->{1})) if $self->{1};
+ my $pid = $pgr->[0];
+ dwaitpid($pid) if $pid && ($pgr->[3] // 0) == $$;