Re: [PATCH] git add -i: allow list (un)selection by regexp
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Dec 2, 2014, 17:26 UTC
- Message-ID
- <xmqq8uiqm081.fsf@gitster.dls.corp.google.com>
- In-Reply-To
- <DB3PR04MB2509E51F1DE708549483845EB7A0@DB3PR04MB250.eurprd04.prod.outlook.com>
Aarni Koskela <aarni.koskela@andersinnovations.com> writes:
Show 5 quoted lines
> From 9096652a71666920ae8d59dd4317d536ba974d5b Mon Sep 17 00:00:00 2001 > From: Aarni Koskela <akx@iki.fi> > Date: Tue, 2 Dec 2014 13:56:15 +0200 > Subject: [PATCH] git-add--interactive: allow list (un)selection by regular > expression
Remove the three lines from the top, move the content on Subject: to the subject of the e-mail.
Other than that, everything I see in this message is very well done.
Thanks, will queue.
Show 126 quoted lines
>
> Teach `list_and_choose` to allow `/regexp` and `-/regexp` syntax to
> select items based on regular expression match.
>
> This feature works in all list menus in `git-add--interactive`, and is not
> limited to file menus only.
>
> For instance, in file lists, `/\.c$` will select all files whose extension
> is `.c`. In option menus, such as the main menu, `/pa` could be used to
> choose the `patch` option.
>
> Signed-off-by: Aarni Koskela <akx@iki.fi>
> ---
>
> Thank you for the insightful comments, Junio, and sorry for the confusion
> regarding email-patch formatting. Hoping I get it right this time.
>
>> Usually the responsibility to ensure correctness lies on the person who
>> proposes a change, not those who relies on the continued correct operation
>> of the existing code.
>
> You're of course absolutely right. My point was that I can't think of an use
> case where one would need to otherwise have "/" or "-/" as the first characters
> of input in a list_and_choose situation, but someone else might.
>
>> [...] but is this about the selection that happens after showing you a
>> list of filenames to choose from?
>
> I clarified this in the commit message. Selection by regexp works in all
> list_and_choose situations, including the main menu of `git add -i`, hence "option".
>
> Regarding the unchoose quantifier -- yes, silly me.
>
> And regarding error checking for the regular expression, you're right -- the
> program promptly blew up when entering an invalid regexp. I incorporated your
> suggestion for error checking, with the addition of using the `error_msg` sub
> for colorized error reporting.
>
> Best regards,
>
> Aarni Koskela
>
> git-add--interactive.perl | 49 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 49 insertions(+)
>
> diff --git a/git-add--interactive.perl b/git-add--interactive.perl
> index 1fadd69..28e4c2d 100755
> --- a/git-add--interactive.perl
> +++ b/git-add--interactive.perl
> @@ -483,6 +483,8 @@ sub is_valid_prefix {
> !($prefix =~ /[\s,]/) && # separators
> !($prefix =~ /^-/) && # deselection
> !($prefix =~ /^\d+/) && # selection
> + !($prefix =~ /^\//) && # regexp selection
> + !($prefix =~ /^-\//) && # regexp unselection
> ($prefix ne '*') && # "all" wildcard
> ($prefix ne '?'); # prompt help
> }
> @@ -585,6 +587,50 @@ sub list_and_choose {
> prompt_help_cmd();
> next TOPLOOP;
> }
> + if ($line =~ /^(-)?\/(.+)$/) {
> + # The first capture group ("-") being missing means "choose" is
> + # requested. If the first group exists at all, "unchoose" is
> + # requested.
> + my $choose = !(defined $1);
> +
> + # Validate the regular expression and complain if compilation failed.
> + my $re = eval { qr/$2/ };
> + if (!$re) {
> + error_msg "Invalid regular expression:\n $@\n";
> + next TOPLOOP;
> + }
> +
> + my $found = 0;
> + for ($i = 0; $i < @stuff; $i++) {
> + my $val = $stuff[$i];
> +
> + # Figure out the display value for $val.
> + # Some lists passed to list_and_choose contain
> + # items other than strings; in order to match
> + # regexps against them, we need to extract the
> + # displayed string. The logic here is approximately
> + # equivalent to the display logic above.
> +
> + my $ref = ref $val;
> + if ($ref eq 'ARRAY') {
> + $val = $val->[0];
> + }
> + elsif ($ref eq 'HASH') {
> + $val = $val->{VALUE};
> + }
> +
> + # Match the string value against the regexp,
> + # then act accordingly.
> +
> + if ($val =~ $re) {
> + $chosen[$i] = $choose;
> + $found = $found || $choose;
> + last if $choose && $opts->{SINGLETON};
> + }
> + }
> + last if $found && ($opts->{IMMEDIATE});
> + next TOPLOOP;
> + }
> for my $choice (split(/[\s,]+/, $line)) {
> my $choose = 1;
> my ($bottom, $top);
> @@ -635,6 +681,7 @@ sub singleton_prompt_help_cmd {
> Prompt help:
> 1 - select a numbered item
> foo - select item based on unique prefix
> +/regexp - select item based on regular expression
> - (empty) select nothing
> EOF
> }
> @@ -648,6 +695,8 @@ Prompt help:
> foo - select item based on unique prefix
> -... - unselect specified items
> * - choose all items
> +/regexp - select items based on regular expression
> +-/regexp - unselect items based on regular expression
> - (empty) finish selecting
> EOF
> }