]> Sergey Matveev's repositories - public-inbox.git/commitdiff
lei: various completion improvements
authorEric Wong <e@80x24.org>
Tue, 21 Sep 2021 07:41:55 +0000 (07:41 +0000)
committerEric Wong <e@80x24.org>
Tue, 21 Sep 2021 19:18:35 +0000 (19:18 +0000)
"lei export-kw" no longer completes for anonymous sources.

More commands use "lei refresh-mail-sync" as a basis for their
completion work, as well.

";AUTH=ANONYMOUS@" is stripped from completions since it was
preventing bash completion from working on AUTH=ANONYMOUS IMAP
URLs.  I'm not sure if there's a better way, but all of our code
works fine without specifying AUTH=ANONYMOUS as a command-line
arg.

Finally, we fallback to using more candidates if none can
be found, allowing multiple URLs to be completed.

lib/PublicInbox/LeiExportKw.pm
lib/PublicInbox/LeiExternal.pm
lib/PublicInbox/LeiForgetMailSync.pm
lib/PublicInbox/LeiImport.pm
lib/PublicInbox/LeiInspect.pm
lib/PublicInbox/LeiLcat.pm
lib/PublicInbox/LeiLsMailSource.pm
lib/PublicInbox/LeiMailSync.pm
lib/PublicInbox/LeiRefreshMailSync.pm
lib/PublicInbox/LeiTag.pm
lib/PublicInbox/SharedKV.pm

index d5533a2a0ae213fdcd0de873f05e279e23334272..cea9beeb569424315aaf57ff5536d0696148408a 100644 (file)
@@ -127,9 +127,13 @@ EOM
 
 sub _complete_export_kw {
        my ($lei, @argv) = @_;
-       my $lms = $lei->lms or return;
+       my $lms = $lei->lms or return ();
        my $match_cb = $lei->complete_url_prepare(\@argv);
-       map { $match_cb->($_) } $lms->folders;
+       # filter-out read-only sources:
+       my @k = grep(!m!(?://;AUTH=ANONYMOUS\@|\A(?:nntps?|s?news)://)!,
+                       $lms->folders($argv[-1], 1));
+       my @m = map { $match_cb->($_) } @k;
+       @m ? @m : @k;
 }
 
 no warnings 'once';
index d802f0e2b5060b03eab56a8e34dfea51e84b9c03..f8e610cacb2115156691693b0fbe357fa1204792 100644 (file)
@@ -241,6 +241,11 @@ sub complete_url_prepare {
                $re = quotemeta($re);
        }
        my $match_cb = sub {
+               # the "//;" here (for AUTH=ANONYMOUS) interacts badly with
+               # bash tab completion, strip it out for now since our commands
+               # work w/o it.  Not sure if there's a better solution...
+               $_[0] =~ s!//;AUTH=ANONYMOUS\@!//!i;
+               $_[0] =~ s!;!\\;!g;
                # only return the part specified on the CLI
                # don't duplicate if already 100% completed
                $_[0] =~ /\A$re(\Q$cur\E.*)/ ? ($cur eq $1 ? () : $1) : ()
index d85616cc425055aee16aee661b024cd59c77ca6e..762910ed5712a893a383fedeb0fc096f4e5736b3 100644 (file)
@@ -10,7 +10,7 @@
 package PublicInbox::LeiForgetMailSync;
 use strict;
 use v5.10.1;
-use PublicInbox::LeiExportKw;
+use PublicInbox::LeiRefreshMailSync;
 
 sub lei_forget_mail_sync {
        my ($lei, @folders) = @_;
@@ -20,6 +20,7 @@ sub lei_forget_mail_sync {
        $lms->forget_folders(@folders);
 }
 
-*_complete_forget_mail_sync = \&PublicInbox::LeiExportKw::_complete_export_kw;
+*_complete_forget_mail_sync =
+       \&PublicInbox::LeiRefreshMailSync::_complete_refresh_mail_sync;
 
 1;
index 3c30db8d2b1f093f24701dda6d13de7cacdc8027..397292d4c7878e4192aa5766a2fa7188166352bd 100644 (file)
@@ -121,12 +121,14 @@ sub lei_import { # the main "lei import" method
 
 sub _complete_import {
        my ($lei, @argv) = @_;
-       my $match_cb = $lei->complete_url_prepare(\@argv);
-       my @m = map { $match_cb->($_) } $lei->url_folder_cache->keys;
-       my %f = map { $_ => 1 } @m;
+       my ($re, $cur, $match_cb) = $lei->complete_url_prepare(\@argv);
+       my @k = $lei->url_folder_cache->keys($argv[-1], 1);
+       my @m = map { $match_cb->($_) } @k;
+       my %f = map { $_ => 1 } (@m ? @m : @k);
        if (my $lms = $lei->lms) {
-               @m = map { $match_cb->($_) } $lms->folders;
-               @f{@m} = @m;
+               @k = $lms->folders($argv[-1], 1);
+               @m = map { $match_cb->($_) } @k;
+               if (@m) { @f{@m} = @m } else { @f{@k} = @k }
        }
        keys %f;
 }
index 8e1285808fa35a3dd9093bbafa0984a38fac7d6c..2158b996a3a48654bef125ec1c990f8193ffb9e1 100644 (file)
@@ -269,10 +269,9 @@ no args allowed on command-line with --stdin
 }
 
 sub _complete_inspect {
-       my ($lei, @argv) = @_;
-       my $lms = $lei->lms or return;
-       my $match_cb = $lei->complete_url_prepare(\@argv);
-       map { $match_cb->($_) } $lms->folders;
+       require PublicInbox::LeiRefreshMailSync;
+       PublicInbox::LeiRefreshMailSync::_complete_refresh_mail_sync(@_);
+       # TODO: message-ids?, blobs? could get expensive...
 }
 
 1;
index 0902c213deee71a070c434e7c2948075ef444b75..c13e2153e88da0daa5b87d8978d85fff1d89a3ee 100644 (file)
@@ -164,10 +164,9 @@ no args allowed on command-line with --stdin
 }
 
 sub _complete_lcat {
-       my ($lei, @argv) = @_;
-       my $lms = $lei->lms or return;
-       my $match_cb = $lei->complete_url_prepare(\@argv);
-       map { $match_cb->($_) } $lms->folders;
+       require PublicInbox::LeiRefreshMailSync;
+       PublicInbox::LeiRefreshMailSync::_complete_refresh_mail_sync(@_);
+       # TODO: message-ids?, blobs? could get expensive...
 }
 
 1;
index 2265969a0d9631709de2dba2548e7ef0080188c4..1db15d5742b557966f41cce9ede496b49ced4380 100644 (file)
@@ -107,12 +107,13 @@ sub lei_ls_mail_source {
 sub _complete_ls_mail_source {
        my ($lei, @argv) = @_;
        my $match_cb = $lei->complete_url_prepare(\@argv);
-       my @m = map { $match_cb->($_) } $lei->url_folder_cache->keys;
-       my %f = map { $_ => 1 } @m;
+       my @k = $lei->url_folder_cache->keys($argv[-1], 1);
+       my @m = map { $match_cb->($_) } @k;
+       my %f = map { $_ => 1 } (@m ? @m : @k);
        if (my $lms = $lei->lms) {
-               @m = map { $match_cb->($_) } grep(
-                       m!\A(?:imaps?|nntps?|s?news)://!, $lms->folders);
-               @f{@m} = @m;
+               @k = $lms->folders($argv[-1], 1);
+               @m = map { $match_cb->($_) } grep(m!\A[a-z]+://!, @k);
+               if (@m) { @f{@m} = @m } else { @f{@k} = @k }
        }
        keys %f;
 }
index 522a5ebc865e3e3a6b0e5b89e83f91d72eb226ac..91cd1c934a1fa7889d293574d99df9878a53292f 100644 (file)
@@ -299,16 +299,19 @@ sub locations_for {
 
 # returns a list of folders used for completion
 sub folders {
-       my ($self, $pfx) = @_;
-       my $dbh = $self->{dbh} //= dbh_new($self);
+       my ($self, @pfx) = @_;
        my $sql = 'SELECT loc FROM folders';
-       my @pfx;
-       if (defined $pfx) {
+       if (defined($pfx[0])) {
                $sql .= ' WHERE loc LIKE ? ESCAPE ?';
-               @pfx = ($pfx, '\\');
+               my $anywhere = !!$pfx[1];
+               $pfx[1] = '\\';
                $pfx[0] =~ s/([%_\\])/\\$1/g; # glob chars
                $pfx[0] .= '%';
+               substr($pfx[0], 0, 0, '%') if $anywhere;
+       } else {
+               @pfx = (); # [0] may've been undef
        }
+       my $dbh = $self->{dbh} //= dbh_new($self);
        map { $_->[0] } @{$dbh->selectall_arrayref($sql, undef, @pfx)};
 }
 
index 51e89b23e1fa79870d8b33b69ddbb4ace3bf81c8..eb842843b51dece6664aad113e26efa4d22b4096 100644 (file)
@@ -7,7 +7,7 @@ package PublicInbox::LeiRefreshMailSync;
 use strict;
 use v5.10.1;
 use parent qw(PublicInbox::IPC PublicInbox::LeiInput);
-use PublicInbox::LeiExportKw;
+use PublicInbox::LeiImport;
 use PublicInbox::InboxWritable qw(eml_from_path);
 use PublicInbox::Import;
 
@@ -97,8 +97,16 @@ sub ipc_atfork_child { # needed for PublicInbox::LeiPmdir
        undef;
 }
 
+sub _complete_refresh_mail_sync {
+       my ($lei, @argv) = @_;
+       my $lms = $lei->lms or return ();
+       my $match_cb = $lei->complete_url_prepare(\@argv);
+       my @k = $lms->folders($argv[-1], 1);
+       my @m = map { $match_cb->($_) } @k;
+       @m ? @m : @k
+}
+
 no warnings 'once';
-*_complete_refresh_mail_sync = \&PublicInbox::LeiExportKw::_complete_export_kw;
 *net_merge_all_done = \&PublicInbox::LeiInput::input_only_net_merge_all_done;
 
 1;
index 9bbf0d79c391a7963f029117781334a7ae37bed5..817b87f81519aadcad426b5ead77b758d796787f 100644 (file)
@@ -74,7 +74,7 @@ sub ipc_atfork_child {
 # Workaround bash word-splitting s to ['kw', ':', 'keyword' ...]
 # Maybe there's a better way to go about this in
 # contrib/completion/lei-completion.bash
-sub _complete_mark_common ($) {
+sub _complete_tag_common ($) {
        my ($argv) = @_;
        # Workaround bash word-splitting URLs to ['https', ':', '//' ...]
        # Maybe there's a better way to go about this in
@@ -104,16 +104,18 @@ sub _complete_mark_common ($) {
 # FIXME: same problems as _complete_forget_external and similar
 sub _complete_tag {
        my ($self, @argv) = @_;
+       require PublicInbox::LeiImport;
+       my @in = PublicInbox::LeiImport::_complete_import(@_);
        my @L = eval { $self->_lei_store->search->all_terms('L') };
-       my @all = ((map { ("+kw:$_", "-kw:$_") } @PublicInbox::LeiInput::KW),
+       my @kwL = ((map { ("+kw:$_", "-kw:$_") } @PublicInbox::LeiInput::KW),
                (map { ("+L:$_", "-L:$_") } @L));
-       return @all if !@argv;
-       my ($cur, $re) = _complete_mark_common(\@argv);
-       map {
+       my ($cur, $re) = _complete_tag_common(\@argv);
+       my @m = map {
                # only return the part specified on the CLI
                # don't duplicate if already 100% completed
                /\A$re(\Q$cur\E.*)/ ? ($cur eq $1 ? () : $1) : ();
-       } grep(/$re\Q$cur/, @all);
+       } grep(/$re\Q$cur/, @kwL);
+       (@in, (@m ? @m : @kwL));
 }
 
 no warnings 'once'; # the following works even when LeiAuth is lazy-loaded
index 3487e82086f47e2049d29b7f7d74bb8a3806aa33..645bb57c90a63bb29521c9bde2be6ce6328bab1c 100644 (file)
@@ -84,12 +84,19 @@ SELECT k,v FROM kv
 }
 
 sub keys {
-       my ($self) = @_;
-       my $sth = $self->dbh->prepare_cached(<<'', undef, 1);
-SELECT k FROM kv
-
-       $sth->execute;
-       map { $_->[0] } @{$sth->fetchall_arrayref};
+       my ($self, @pfx) = @_;
+       my $sql = 'SELECT k FROM kv';
+       if (defined $pfx[0]) {
+               $sql .= ' WHERE k LIKE ? ESCAPE ?';
+               my $anywhere = !!$pfx[1];
+               $pfx[1] = '\\';
+               $pfx[0] =~ s/([%_\\])/\\$1/g; # glob chars
+               $pfx[0] .= '%';
+               substr($pfx[0], 0, 0, '%') if $anywhere;
+       } else {
+               @pfx = (); # [0] may've been undef
+       }
+       map { $_->[0] } @{$self->dbh->selectall_arrayref($sql, undef, @pfx)};
 }
 
 sub delete_by_val {