my ($self, $p) = @_;
return $p if index($p, '/') == 0; # already absolute
my $pwd = $self->{env}->{PWD};
+ my $cwd;
if (defined $pwd) {
- my $cwd = $self->{3} // getcwd() // die "getcwd(PWD=$pwd): $!";
+ my $xcwd = $self->{3} //
+ ($cwd = getcwd() // die "getcwd(PWD=$pwd): $!");
if (my @st_pwd = stat($pwd)) {
- my @st_cwd = stat($cwd) or die "stat($cwd): $!";
+ my @st_cwd = stat($xcwd) or die "stat($xcwd): $!";
"@st_pwd[1,0]" eq "@st_cwd[1,0]" or
- $self->{env}->{PWD} = $pwd = $cwd;
+ $self->{env}->{PWD} = $pwd = undef;
} else { # PWD was invalid
- delete $self->{env}->{PWD};
- undef $pwd;
+ $self->{env}->{PWD} = $pwd = undef;
}
}
- $pwd //= $self->{env}->{PWD} = getcwd() // die "getcwd(PWD=$pwd): $!";
+ $pwd //= $self->{env}->{PWD} = $cwd // getcwd() // die "getcwd: $!";
File::Spec->rel2abs($p, $pwd);
}
-sub store_path ($) {
+sub share_path ($) { # $HOME/.local/share/lei/$FOO
my ($self) = @_;
rel2abs($self, ($self->{env}->{XDG_DATA_HOME} //
($self->{env}->{HOME} // '/nonexistent').'/.local/share')
- .'/lei/store');
+ .'/lei');
}
+sub store_path ($) { share_path($_[0]) . '/store' }
+
sub _config_path ($) {
my ($self) = @_;
rel2abs($self, ($self->{env}->{XDG_CONFIG_HOME} //
'q' => [ '--stdin|SEARCH_TERMS...', 'search for messages matching terms',
'stdin|', # /|\z/ must be first for lone dash
@lxs_opt,
- qw(save-as=s output|mfolder|o=s format|f=s dedupe|d=s threads|t+
+ qw(save output|mfolder|o=s format|f=s dedupe|d=s threads|t+
sort|s=s reverse|r offset=i pretty jobs|j=s globoff|g augment|a
import-before! lock=s@ rsyncable alert=s@ mua=s verbose|v+), @c_opt,
opt_dash('limit|n=i', '[0-9]+') ],
+'up' => [ 'SEARCH_TERMS...', 'update saved search',
+ qw(jobs|j=s lock=s@ alert=s@ mua=s verbose|v+), @c_opt ],
'blob' => [ 'OID', 'show a git blob, reconstructing from mail if necessary',
qw(git-dir=s@ cwd! verbose|v+ mail! oid-a|A=s path-a|a=s path-b|b=s),
'exclude further results from a publicinbox|extindex',
qw(prune), @c_opt ],
-'ls-query' => [ '[FILTER...]', 'list saved search queries',
- qw(name-only format|f=s), @c_opt ],
+'ls-search' => [ '[PREFIX]', 'list saved search queries',
+ qw(format|f=s pretty l ascii z|0), @c_opt ],
'rm-query' => [ 'QUERY_NAME', 'remove a saved search', @c_opt ],
'mv-query' => [ qw(OLD_NAME NEW_NAME), 'rename a saved search', @c_opt ],
'torsocks=s' => ['VAL|auto|no|yes',
'whether or not to wrap git and curl commands with torsocks'],
'no-torsocks' => 'alias for --torsocks=no',
-'save-as=s' => ['NAME', 'save a search terms by given name'],
+'save' => "save a search for `lei up'",
'import-remote!' => 'do not memoize remote messages into local store',
'type=s' => [ 'any|mid|git', 'disambiguate type' ],
'jobs|j=i add-external' => 'set parallelism when indexing after --mirror',
'in-format|F=s' => $stdin_formats,
-'format|f=s ls-query' => $ls_format,
+'format|f=s ls-search' => ['OUT|json|jsonl|concatjson',
+ 'listing output format' ],
+'l ls-search' => 'long listing format',
'format|f=s ls-external' => $ls_format,
'limit|n=i@' => ['NUM', 'limit on number of matches (default: 10000)' ],
'leistore.dir' => 'top-level storage location',
);
-my @WQ_KEYS = qw(lxs l2m imp mrr cnv p2q tag sol); # internal workers
+my @WQ_KEYS = qw(lxs l2m imp mrr cnv p2q tag sol lsss); # internal workers
sub _drop_wq {
my ($self) = @_;
@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);
+ if ($self->{sock}) { # lei(1) client process runs it
+ # restore terminal: echo $query | lei q -stdin --mua=...
+ my $io = [];
+ $io->[0] = $self->{1} if $self->{opt}->{stdin} && -t $self->{1};
+ send_exec_cmd($self, $io, \@cmd, {});
} elsif ($self->{oneshot}) {
my $pid = fork // die "fork: $!";
if ($pid > 0) { # original process
+ if ($self->{opt}->{stdin} && -t STDOUT) {
+ open STDIN, '+<&', \*STDOUT or die "dup2: $!";
+ }
exec(@cmd);
warn "exec @cmd: $!\n";
POSIX::_exit(1);
if ($self->{lxs} && $self->{au_done}) { # kick wait_startq
syswrite($self->{au_done}, 'q' x ($self->{lxs}->{jobs} // 0));
}
+ return unless -t $self->{2}; # XXX how to determine non-TUI MUAs?
$self->{opt}->{quiet} = 1;
delete $self->{-progress};
delete $self->{opt}->{verbose};