user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
* [PATCH] lei q: add --mua-cmd switch
@ 2021-01-17  8:52 Eric Wong
  2021-01-17 10:19 ` Eric Wong
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Wong @ 2021-01-17  8:52 UTC (permalink / raw)
  To: meta

It can be convenient to invoke an MUA as search results
are being written to it, as an eager person may want to
start seeing results ASAP.  This lets Maildir users
see results in the MUA as we are writing them.  Users
of IMAP will eventually be able to take advantage of
them, too.

Since we don't support mbox locking (yet?), we'll only invoke
the MUA after results are done for mbox formats.
---
 lib/PublicInbox/LEI.pm        | 45 ++++++++++++++++++++++++++++-------
 lib/PublicInbox/LeiToMail.pm  |  4 ++++
 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 56254c45..ee5c26a8 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}) {

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] lei q: add --mua-cmd switch
  2021-01-17  8:52 [PATCH] lei q: add --mua-cmd switch Eric Wong
@ 2021-01-17 10:19 ` Eric Wong
  2021-01-17 10:28   ` Eric Wong
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Wong @ 2021-01-17 10:19 UTC (permalink / raw)
  To: meta

Eric Wong <e@80x24.org> wrote:
> @@ -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'" ],

I'm wondering if displaying "mutt" in a one-line help message is
showing unnecessary favoritism for a non-standard MUA.

Fwiw, "mailx -f" is POSIX, but only for mbox.  While both
Heirloom mailx and GNU mailutils mailx support Maildir, but
bsd-mailx (the default on Debian, AFAIK) does not...

FreeBSD mailx does not do Maildir, either (tested 12.1 and 11.4).

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] lei q: add --mua-cmd switch
  2021-01-17 10:19 ` Eric Wong
@ 2021-01-17 10:28   ` Eric Wong
  0 siblings, 0 replies; 3+ messages in thread
From: Eric Wong @ 2021-01-17 10:28 UTC (permalink / raw)
  To: meta

Eric Wong <e@80x24.org> wrote:
> Eric Wong <e@80x24.org> wrote:
> > @@ -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'" ],
> 
> I'm wondering if displaying "mutt" in a one-line help message is
> showing unnecessary favoritism for a non-standard MUA.
> 
> Fwiw, "mailx -f" is POSIX, but only for mbox.

Though git also favors less(1) (and lei follows suit),
despite more(1) being the POSIX pager.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-01-17 10:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-17  8:52 [PATCH] lei q: add --mua-cmd switch Eric Wong
2021-01-17 10:19 ` Eric Wong
2021-01-17 10:28   ` Eric Wong

Code repositories for project(s) associated with this inbox:

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).