* [PATCH] lei: improve bash completion involving colons
@ 2023-03-23 21:45 7% Eric Wong
0 siblings, 0 replies; 1+ results
From: Eric Wong @ 2023-03-23 21:45 UTC (permalink / raw)
To: meta
This fixes completions of labels (`+L:' for `lei import' and
`L:' for `lei q') so they can appear anywhere in the
command-line.
I mainly wanted this for `lei import $URL +L:label', but
this also fixes `lei forget-external' completions for URLs
(which involve colons).
---
contrib/completion/lei-completion.bash | 15 ++++++++-----
lib/PublicInbox/LeiExternal.pm | 31 +++++++++++---------------
lib/PublicInbox/LeiForgetExternal.pm | 8 ++-----
lib/PublicInbox/LeiImport.pm | 22 +++++++++++-------
lib/PublicInbox/LeiQuery.pm | 2 ++
5 files changed, 40 insertions(+), 38 deletions(-)
diff --git a/contrib/completion/lei-completion.bash b/contrib/completion/lei-completion.bash
index 5c137e68..b86afa2c 100644
--- a/contrib/completion/lei-completion.bash
+++ b/contrib/completion/lei-completion.bash
@@ -1,16 +1,19 @@
-# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
# preliminary bash completion support for lei (Local Email Interface)
# Needs a lot of work, see `lei__complete' in lib/PublicInbox::LEI.pm
_lei() {
local wordlist="$(lei _complete ${COMP_WORDS[@]})"
- case $wordlist in
- *':'* | *'='* | '//'*) compopt -o nospace ;;
- *) compopt +o nospace ;; # the default
- esac
wordlist="${wordlist//;/\\\\;}" # escape ';' for ';UIDVALIDITY' and such
- COMPREPLY=($(compgen -W "$wordlist" -- "${COMP_WORDS[COMP_CWORD]}"))
+
+ local word="${COMP_WORDS[COMP_CWORD]}"
+ if test "$word" = ':' && test $COMP_CWORD -ge 1
+ then
+ COMPREPLY=($(compgen -W "$wordlist" --))
+ else
+ COMPREPLY=($(compgen -W "$wordlist" -- "$word"))
+ fi
return 0
}
complete -o default -o bashdefault -F _lei lei
diff --git a/lib/PublicInbox/LeiExternal.pm b/lib/PublicInbox/LeiExternal.pm
index 3e2a2288..31b9bd1e 100644
--- a/lib/PublicInbox/LeiExternal.pm
+++ b/lib/PublicInbox/LeiExternal.pm
@@ -86,39 +86,34 @@ sub canonicalize_excludes {
# returns an anonymous sub which returns an array of potential results
sub complete_url_prepare {
my $argv = $_[-1]; # $_[0] may be $lei
- # Workaround bash word-splitting URLs to ['https', ':', '//' ...]
- # Maybe there's a better way to go about this in
- # contrib/completion/lei-completion.bash
- my $re = '';
- my $cur = pop(@$argv) // '';
+ # Workaround bash default COMP_WORDBREAKS splitting URLs to
+ # ['https', ':', '//', ...]. COMP_WORDBREAKS is global for all
+ # completions loaded, not just ours, so we can't change it.
+ # cf. contrib/completion/lei-completion.bash
+ my ($pfx, $cur) = ('', pop(@$argv) // '');
if (@$argv) {
my @x = @$argv;
- if ($cur eq ':' && @x) {
+ if ($cur =~ /\A[:;=]\z/) { # COMP_WORDBREAKS + URL union
push @x, $cur;
$cur = '';
}
- while (@x > 2 && $x[0] !~ /\A(?:http|nntp|imap)s?\z/i &&
- $x[1] ne ':') {
- shift @x;
+ while (@x && $pfx !~ m!\A(?: (?:[\+\-]?(?:L|kw):) |
+ (?:(?:imap|nntp|http)s?:) |
+ (?:--\w?\z)|(?:-\w?\z) )!x) {
+ $pfx = pop(@x).$pfx;
}
- if (@x >= 2) { # qw(https : hostname : 443) or qw(http :)
- $re = join('', @x);
- } else { # just filter out the flags and hope for the best
- $re = join('', grep(!/^-/, @$argv));
- }
- $re = quotemeta($re);
}
+ my $re = qr!\A\Q$pfx\E(\Q$cur\E.*)!;
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) : ()
+ $_[0] =~ $re ? ($cur eq $1 ? () : $1) : ()
};
- wantarray ? ($re, $cur, $match_cb) : $match_cb;
+ wantarray ? ($pfx, $cur, $match_cb) : $match_cb;
}
1;
diff --git a/lib/PublicInbox/LeiForgetExternal.pm b/lib/PublicInbox/LeiForgetExternal.pm
index 07f0ac80..39bfc60b 100644
--- a/lib/PublicInbox/LeiForgetExternal.pm
+++ b/lib/PublicInbox/LeiForgetExternal.pm
@@ -32,14 +32,10 @@ sub lei_forget_external {
sub _complete_forget_external {
my ($lei, @argv) = @_;
my $cfg = $lei->_lei_cfg or return ();
- my ($cur, $re, $match_cb) = $lei->complete_url_prepare(\@argv);
- # FIXME: bash completion off "http:" or "https:" when the last
- # character is a colon doesn't work properly even if we're
- # returning "//$HTTP_HOST/$PATH_INFO/", not sure why, could
- # be a bash issue.
+ my ($pfx, $cur, $match_cb) = $lei->complete_url_prepare(\@argv);
map {
$match_cb->(substr($_, length('external.')));
- } grep(/\Aexternal\.$re\Q$cur/, @{$cfg->{-section_order}});
+ } grep(/\Aexternal\.\Q$pfx$cur/, @{$cfg->{-section_order}});
}
1;
diff --git a/lib/PublicInbox/LeiImport.pm b/lib/PublicInbox/LeiImport.pm
index 2d91e4c4..9053048a 100644
--- a/lib/PublicInbox/LeiImport.pm
+++ b/lib/PublicInbox/LeiImport.pm
@@ -115,18 +115,24 @@ sub lei_import { # the main "lei import" method
sub _complete_import {
my ($lei, @argv) = @_;
- my ($re, $cur, $match_cb) = $lei->complete_url_prepare(\@argv);
- my @k = $lei->url_folder_cache->keys($argv[-1] // undef, 1);
+ my $has_arg = @argv;
+ my ($pfx, $cur, $match_cb) = $lei->complete_url_prepare(\@argv);
+ my @try = $has_arg ? ($pfx.$cur, $argv[-1]) : ($argv[-1]);
+ push(@try, undef) if defined $try[-1];
+ my (@f, @k);
+ for (@try) {
+ @k = $lei->url_folder_cache->keys($_, 1) and last;
+ }
my @L = eval { $lei->_lei_store->search->all_terms('L') };
push(@k, map { "+L:$_" } @L);
- my @m = map { $match_cb->($_) } @k;
- my %f = map { $_ => 1 } (@m ? @m : @k);
if (my $lms = $lei->lms) {
- @k = $lms->folders($argv[-1] // undef, 1);
- @m = map { $match_cb->($_) } @k;
- if (@m) { @f{@m} = @m } else { @f{@k} = @k }
+ for (@try) {
+ @f = $lms->folders($_, 1) and last;
+ }
+ push @k, @f;
}
- keys %f;
+ my @m = map { $match_cb->($_) } @k;
+ @m ? @m : @k;
}
no warnings 'once';
diff --git a/lib/PublicInbox/LeiQuery.pm b/lib/PublicInbox/LeiQuery.pm
index 358574ea..3337e5d4 100644
--- a/lib/PublicInbox/LeiQuery.pm
+++ b/lib/PublicInbox/LeiQuery.pm
@@ -173,6 +173,8 @@ no query allowed on command-line with --stdin
# shell completion helper called by lei__complete
sub _complete_q {
my ($self, @argv) = @_;
+ join('', @argv) =~ /\bL:\S*\z/ and
+ return eval { $self->_lei_store->search->all_terms('L') };
my @cur;
my $cb = $self->lazy_cb(qw(forget-external _complete_));
while (@argv) {
^ permalink raw reply related [relevance 7%]
Results 1-1 of 1 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2023-03-23 21:45 7% [PATCH] lei: improve bash completion involving colons Eric Wong
Code repositories for project(s) associated with this public 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).