{"thread":{"id":"10959","subject":"[PATCH] Highlight keyboard shortcuts in git-add--interactive","startedAt":"2007-11-21T14:27:58Z","lastAt":"2007-12-03T08:09:43Z","messageCount":17,"participants":["Wincent Colaiuta","Matthieu Moy","Jeff King","Dan Zwell","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"60516","messageId":"1195655278-19535-1-git-send-email-win@wincent.com","threadId":"10959","inReplyTo":null,"subject":"[PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-11-21T14:27:58Z","receivedAt":"2007-11-21T14:27:58Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The user interface provided by the command loop in git-add--interactive\ngives the impression that subcommands can only be launched by entering\nan integer identifier from 1 through 8.\n\nA \"hidden\" feature is that any string can be entered, and an anchored\nregex search is used to find the first matching option.\n\nThis patch makes this feature a little more obvious by highlighting the\nfirst character of each subcommand (for example \"patch\" is displayed as\n\"[p]atch\"). The mechanism for doing this is to add an optional third\nelement to the array defining each subcommand; if present, it will be\nused for display purposes, while the actual name of the subcommand (the\nfirst element) is still used for matching purposes.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n\nAnd another thought: if the colorization for git-add--interactive goes\nahead, we could drop the square brackets used here in favor of underline\nor boldface, if people find that more attractive.\n\n git-add--interactive.perl |   18 +++++++++---------\n 1 files changed, 9 insertions(+), 9 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 0317ad9..2b1c55a 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -179,7 +179,7 @@ sub list_and_choose {\n \t\t\tmy $print = $stuff[$i];\n \t\t\tif (ref $print) {\n \t\t\t\tif ((ref $print) eq 'ARRAY') {\n-\t\t\t\t\t$print = $print->[0];\n+\t\t\t\t\t$print = $print->[2] || $print->[0];\n \t\t\t\t}\n \t\t\t\telse {\n \t\t\t\t\t$print = $print->{PRINT};\n@@ -774,14 +774,14 @@ EOF\n }\n \n sub main_loop {\n-\tmy @cmd = ([ 'status', \\&status_cmd, ],\n-\t\t   [ 'update', \\&update_cmd, ],\n-\t\t   [ 'revert', \\&revert_cmd, ],\n-\t\t   [ 'add untracked', \\&add_untracked_cmd, ],\n-\t\t   [ 'patch', \\&patch_update_cmd, ],\n-\t\t   [ 'diff', \\&diff_cmd, ],\n-\t\t   [ 'quit', \\&quit_cmd, ],\n-\t\t   [ 'help', \\&help_cmd, ],\n+\tmy @cmd = ([ 'status', \\&status_cmd, '[s]tatus', ],\n+\t\t   [ 'update', \\&update_cmd, '[u]date', ],\n+\t\t   [ 'revert', \\&revert_cmd, '[r]evert', ],\n+\t\t   [ 'add untracked', \\&add_untracked_cmd, '[a]dd untracked', ],\n+\t\t   [ 'patch', \\&patch_update_cmd, '[p]atch', ],\n+\t\t   [ 'diff', \\&diff_cmd, '[d]iff', ],\n+\t\t   [ 'quit', \\&quit_cmd, '[q]uit', ],\n+\t\t   [ 'help', \\&help_cmd, '[h]elp', ],\n \t);\n \twhile (1) {\n \t\tmy ($it) = list_and_choose({ PROMPT => 'What now',\n-- \n1.5.3.6.866.g67e44\n"},{"id":"60517","messageId":"vpqr6ijfz4c.fsf@bauges.imag.fr","threadId":"10959","inReplyTo":"1195655278-19535-1-git-send-email-win@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2007-11-21T14:32:19Z","receivedAt":"2007-11-21T14:32:19Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Wincent Colaiuta <win@wincent.com> writes:\n\n> +\t\t   [ 'update', \\&update_cmd, '[u]date', ],\n                                                 ^\n\"p\" missing in \"update\".\n\n-- \nMatthieu\n"},{"id":"60528","messageId":"20071121152817.GA27144@sigill.intra.peff.net","threadId":"10959","inReplyTo":"1195655278-19535-1-git-send-email-win@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-11-21T15:28:17Z","receivedAt":"2007-11-21T15:28:17Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Nov 21, 2007 at 03:27:58PM +0100, Wincent Colaiuta wrote:\n\n> The user interface provided by the command loop in git-add--interactive\n> gives the impression that subcommands can only be launched by entering\n> an integer identifier from 1 through 8.\n> \n> A \"hidden\" feature is that any string can be entered, and an anchored\n> regex search is used to find the first matching option.\n> \n> This patch makes this feature a little more obvious by highlighting the\n> first character of each subcommand (for example \"patch\" is displayed as\n> \"[p]atch\"). The mechanism for doing this is to add an optional third\n\nI think this is reasonable. It is also a candidate for colorization in\nDan Zwell's patches. Dan, any progress on the next revision of the patch\nseries?\n\n-Peff\n"},{"id":"60574","messageId":"4744B8A2.6020503@zwell.net","threadId":"10959","inReplyTo":"20071121152817.GA27144@sigill.intra.peff.net","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Dan Zwell","fromEmail":"dzwell@gmail.com","sentAt":"2007-11-21T23:00:50Z","receivedAt":"2007-11-21T23:00:50Z","isPatch":true,"sender":{"key":"dzwell@gmail.com","avatar":null},"body":"Jeff King wrote:\n > Dan, any progress on the next revision of the patch\n > series?\n >\n\nYeah, I've been busy with school work, but Thanksgiving break has just \nstarted. I hope to have something to send tonight, though it probably \nwill not be the final draft, as it has quite a bit of changes from the \nlast version.\n\nDan\n"},{"id":"61331","messageId":"7vmysx2ac8.fsf@gitster.siamese.dyndns.org","threadId":"10959","inReplyTo":"1195655278-19535-1-git-send-email-win@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-11-28T23:56:23Z","receivedAt":"2007-11-28T23:56:23Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Wincent Colaiuta <win@wincent.com> writes:\n\n> @@ -774,14 +774,14 @@ EOF\n>  }\n>  \n>  sub main_loop {\n> -\tmy @cmd = ([ 'status', \\&status_cmd, ],\n> -\t\t   [ 'update', \\&update_cmd, ],\n> -\t\t   [ 'revert', \\&revert_cmd, ],\n> -\t\t   [ 'add untracked', \\&add_untracked_cmd, ],\n> -\t\t   [ 'patch', \\&patch_update_cmd, ],\n> -\t\t   [ 'diff', \\&diff_cmd, ],\n> -\t\t   [ 'quit', \\&quit_cmd, ],\n> -\t\t   [ 'help', \\&help_cmd, ],\n> +\tmy @cmd = ([ 'status', \\&status_cmd, '[s]tatus', ],\n> +\t\t   [ 'update', \\&update_cmd, '[u]date', ],\n> +\t\t   [ 'revert', \\&revert_cmd, '[r]evert', ],\n> +\t\t   [ 'add untracked', \\&add_untracked_cmd, '[a]dd untracked', ],\n> +\t\t   [ 'patch', \\&patch_update_cmd, '[p]atch', ],\n> +\t\t   [ 'diff', \\&diff_cmd, '[d]iff', ],\n> +\t\t   [ 'quit', \\&quit_cmd, '[q]uit', ],\n> +\t\t   [ 'help', \\&help_cmd, '[h]elp', ],\n>  \t);\n\nI like the general idea of making it more obvious that you can use the\nunique prefix, but I think you should make list_and_choose do this\nautomatically without adding a redundant element in the command array.\n\nIf you do so, the same highlighting will automatically appear when you\nare picking which paths to update in the update subcommand, for example.\n"},{"id":"61349","messageId":"9FA2CBB3-DD98-4349-8001-8F6B2E47F0DC@wincent.com","threadId":"10959","inReplyTo":"7vmysx2ac8.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-11-29T01:08:07Z","receivedAt":"2007-11-29T01:08:07Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 29/11/2007, a las 0:56, Junio C Hamano escribió:\n\n> Wincent Colaiuta <win@wincent.com> writes:\n>\n>> @@ -774,14 +774,14 @@ EOF\n>> }\n>>\n>> sub main_loop {\n>> -\tmy @cmd = ([ 'status', \\&status_cmd, ],\n>> -\t\t   [ 'update', \\&update_cmd, ],\n>> -\t\t   [ 'revert', \\&revert_cmd, ],\n>> -\t\t   [ 'add untracked', \\&add_untracked_cmd, ],\n>> -\t\t   [ 'patch', \\&patch_update_cmd, ],\n>> -\t\t   [ 'diff', \\&diff_cmd, ],\n>> -\t\t   [ 'quit', \\&quit_cmd, ],\n>> -\t\t   [ 'help', \\&help_cmd, ],\n>> +\tmy @cmd = ([ 'status', \\&status_cmd, '[s]tatus', ],\n>> +\t\t   [ 'update', \\&update_cmd, '[u]date', ],\n>> +\t\t   [ 'revert', \\&revert_cmd, '[r]evert', ],\n>> +\t\t   [ 'add untracked', \\&add_untracked_cmd, '[a]dd untracked', ],\n>> +\t\t   [ 'patch', \\&patch_update_cmd, '[p]atch', ],\n>> +\t\t   [ 'diff', \\&diff_cmd, '[d]iff', ],\n>> +\t\t   [ 'quit', \\&quit_cmd, '[q]uit', ],\n>> +\t\t   [ 'help', \\&help_cmd, '[h]elp', ],\n>> \t);\n>\n> I like the general idea of making it more obvious that you can use the\n> unique prefix, but I think you should make list_and_choose do this\n> automatically without adding a redundant element in the command array.\n>\n> If you do so, the same highlighting will automatically appear when you\n> are picking which paths to update in the update subcommand, for  \n> example.\n\n\nYes, I did consider that, and it's very easy when all the options have  \na unique, single-letter prefix, as is the case with the main command  \nloop. But what to do if you've got a bunch of paths with lengthy  \ncommon prefixes? eg. what would you highlight here?\n\nlib/ssl/crypto/foo.c\nlib/ssl/crypto/bar.c\nlib/ssl/crypto/baz.c\n\nHighlighting \"lib/ssl/crypto/f\", \"lib/ssl/crypto/bar\" and \"lib/ssl/ \ncrypto/baz\" doesn't sound like much help... Maybe there should be some  \nlimit: if you need to go more than 3 characters deep in order to  \ndifferentiate unique prefixes then perhaps highlighting should be  \nomitted in that case. What do you think of that idea?\n\nCheers,\nWincent\n"},{"id":"61391","messageId":"1196337638-45972-1-git-send-email-win@wincent.com","threadId":"10959","inReplyTo":"7vmysx2ac8.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-11-29T12:00:38Z","receivedAt":"2007-11-29T12:00:38Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The user interface provided by the command loop in git-add--interactive\ngives the impression that subcommands can only be launched by entering\nan integer identifier from 1 through 8.\n\nA \"hidden\" feature is that any string can be entered, and an anchored\nregex search is used to find the first matching option.\n\nThis patch makes this feature a little more obvious by highlighting the\nfirst character of each subcommand (for example \"patch\" is displayed as\n\"[p]atch\").\n\nA new function is added to detect the shortest unique prefix and this\nis used to decide what to highlight. Highlighting is also applied when\nchoosing files.\n\nIn the case where the common prefix may be unreasonably large\nhighlighting is omitted; in this patch the soft limit (above which the\nhighlighting will be omitted for a particular item) is 0 (in other words,\nthere is no soft limit) and the hard limit (above which highlighting will\nbe omitted for all items) is 3, but this can be tweaked.\n\nThe actual highlighting is done by the highlight_prefix function, which\nwill enable us to implement ANSI color code-based highlighting (most\nlikely using underline or boldface) in the future.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n git-add--interactive.perl |   87 ++++++++++++++++++++++++++++++++++++++++++---\n 1 files changed, 82 insertions(+), 5 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex fb1e92a..6e5781b 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -44,7 +44,6 @@ my $status_fmt = '%12s %12s %s';\n my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \n # Returns list of hashes, contents of each of which are:\n-# PRINT:\tprint message\n # VALUE:\tpathname\n # BINARY:\tis a binary path\n # INDEX:\tis index different from HEAD?\n@@ -122,8 +121,6 @@ sub list_modified {\n \t\t}\n \t\tpush @return, +{\n \t\t\tVALUE => $_,\n-\t\t\tPRINT => (sprintf $status_fmt,\n-\t\t\t\t  $it->{INDEX}, $it->{FILE}, $_),\n \t\t\t%$it,\n \t\t};\n \t}\n@@ -159,10 +156,82 @@ sub find_unique {\n \treturn $found;\n }\n \n+# inserts string into trie and updates count for each character\n+sub update_trie {\n+\tmy ($trie, $string) = @_;\n+\tforeach (split //, $string) {\n+\t\t$trie = $trie->{$_} ||= {COUNT => 0};\n+\t\t$trie->{COUNT}++;\n+\t}\n+}\n+\n+# returns an array of tuples (prefix, remainder)\n+sub find_unique_prefixes {\n+\tmy @stuff = @_;\n+\tmy @return = ();\n+\n+\t# any single prefix exceeding the soft limit is omitted\n+\t# if any prefix exceeds the hard limit all are omitted\n+\t# 0 indicates no limit\n+\tmy $soft_limit = 0;\n+\tmy $hard_limit = 3;\n+\n+\t# build a trie modelling all possible options\n+\tmy %trie;\n+\tforeach my $print (@stuff) {\n+\t\tif ((ref $print) eq 'ARRAY') {\n+\t\t\t$print = $print->[0];\n+\t\t}\n+\t\telse {\n+\t\t\t$print = $print->{VALUE};\n+\t\t}\n+\t\tupdate_trie(\\%trie, $print);\n+\t\tpush @return, $print;\n+\t}\n+\n+\t# use the trie to find the unique prefixes\n+\tfor (my $i = 0; $i < @return; $i++) {\n+\t\tmy $ret = $return[$i];\n+\t\tmy @letters = split //, $ret;\n+\t\tmy %search = %trie;\n+\t\tmy ($prefix, $remainder);\n+\t\tmy $j;\n+\t\tfor ($j = 0; $j < @letters; $j++) {\n+\t\t\tmy $letter = $letters[$j];\n+\t\t\tif ($search{$letter}{COUNT} == 1) {\n+\t\t\t\t$prefix = substr $ret, 0, $j + 1;\n+\t\t\t\t$remainder = substr $ret, $j + 1;\n+\t\t\t\tlast;\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tmy $prefix = substr $ret, 0, $j;\n+\t\t\t\treturn ()\n+\t\t\t\t    if ($hard_limit && $j + 1 > $hard_limit);\n+\t\t\t}\n+\t\t\t%search = %{$search{$letter}};\n+\t\t}\n+\t\tif ($soft_limit && $j + 1 > $soft_limit) {\n+\t\t\t$prefix = undef;\n+\t\t\t$remainder = $ret;\n+\t\t}\n+\t\t$return[$i] = [$prefix, $remainder];\n+\t}\n+\treturn @return;\n+}\n+\n+# given a prefix/remainder tuple return a string with the prefix highlighted\n+# for now use square brackets; later might use ANSI colors (underline, bold)\n+sub highlight_prefix {\n+\tmy $prefix = shift;\n+\tmy $remainder = shift;\n+\t$prefix ? \"[$prefix]$remainder\" : $remainder;\n+}\n+\n sub list_and_choose {\n \tmy ($opts, @stuff) = @_;\n \tmy (@chosen, @return);\n \tmy $i;\n+\tmy @prefixes = find_unique_prefixes(@stuff) unless $opts->{LIST_ONLY};\n \n       TOPLOOP:\n \twhile (1) {\n@@ -179,10 +248,18 @@ sub list_and_choose {\n \t\t\tmy $print = $stuff[$i];\n \t\t\tif (ref $print) {\n \t\t\t\tif ((ref $print) eq 'ARRAY') {\n-\t\t\t\t\t$print = $print->[0];\n+\t\t\t\t\t$print = @prefixes ?\n+\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n+\t\t\t\t\t    $print->[0];\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\t$print = $print->{PRINT};\n+\t\t\t\t\tmy $value = @prefixes ?\n+\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n+\t\t\t\t\t    $print->{VALUE};\n+\t\t\t\t\t$print = sprintf($status_fmt,\n+\t\t\t\t\t    $print->{INDEX},\n+\t\t\t\t\t    $print->{FILE},\n+\t\t\t\t\t    $value);\n \t\t\t\t}\n \t\t\t}\n \t\t\tprintf(\"%s%2d: %s\", $chosen, $i+1, $print);\n-- \n1.5.3.6.953.gdffc\n"},{"id":"61400","messageId":"20071129145139.GC32670@coredump.intra.peff.net","threadId":"10959","inReplyTo":"1196337638-45972-1-git-send-email-win@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2007-11-29T14:51:39Z","receivedAt":"2007-11-29T14:51:39Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Nov 29, 2007 at 01:00:38PM +0100, Wincent Colaiuta wrote:\n\n> A new function is added to detect the shortest unique prefix and this\n> is used to decide what to highlight. Highlighting is also applied when\n> choosing files.\n\nI think this is very nicely implemented.\n\nAcked-by: Jeff King <peff@peff.net>\n\n> +# returns an array of tuples (prefix, remainder)\n> +sub find_unique_prefixes {\n> +\tmy @stuff = @_;\n\nI know we generally use this more C-ish argument convention to document\n\"here are the arguments to this function\", but it does actually make a\ncopy of the @_ array (and using @_ implies a potentially large number of\narguments).\n\nIt probably doesn't matter here, though, since add--interactive is not\nperformance critical, and you probably can't have more than a few dozen\nentries before it becomes unreadable anyway.\n\n-Peff\n"},{"id":"61545","messageId":"7vy7cf87jz.fsf@gitster.siamese.dyndns.org","threadId":"10959","inReplyTo":"1196337638-45972-1-git-send-email-win@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-01T02:36:48Z","receivedAt":"2007-12-01T02:36:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Wincent Colaiuta <win@wincent.com> writes:\n\n> A \"hidden\" feature is that any string can be entered, and an anchored\n> regex search is used to find the first matching option.\n\nI'd run s/the first/the uniquely/ here.\n\nWhen list_and_choose() function is letting you choose more than one\nitems, its prompt becomes \">> \", instead of \"> \" that is used for a\nsingleton choice.  To that prompt, you can say \"3-7\" (Add these 5 items\nto the choice), \"*\" (I want all of them), \"-2-4\" (exclude 2 and 3 and 4\nfrom the set I have chosen so far).  These are also \"hidden\", and need\nto be documented, but that would be a separate patch.\n\n> +# given a prefix/remainder tuple return a string with the prefix highlighted\n> +# for now use square brackets; later might use ANSI colors (underline, bold)\n> +sub highlight_prefix {\n> +\tmy $prefix = shift;\n> +\tmy $remainder = shift;\n> +\t$prefix ? \"[$prefix]$remainder\" : $remainder;\n> +}\n\nI'd rewrite the last line to:\n\n\treturn (defined $prefix) ? \"[$prefix]$remainder\" : $remainder;\n\njust in case the unique prefix is \"0\".  Otherwise you would lose the\nfirst letter from \"00ReadMe\" and show remainder \"0ReadMe\" alone.\n"},{"id":"61579","messageId":"71367167-E94C-4229-9A29-3B6C2DDC75DC@wincent.com","threadId":"10959","inReplyTo":"7vy7cf87jz.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-01T13:58:30Z","receivedAt":"2007-12-01T13:58:30Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"\nEl 1/12/2007, a las 3:36, Junio C Hamano escribió:\n\n> Wincent Colaiuta <win@wincent.com> writes:\n>\n>> A \"hidden\" feature is that any string can be entered, and an anchored\n>> regex search is used to find the first matching option.\n>\n> I'd run s/the first/the uniquely/ here.\n>\n> When list_and_choose() function is letting you choose more than one\n> items, its prompt becomes \">> \", instead of \"> \" that is used for a\n> singleton choice.  To that prompt, you can say \"3-7\" (Add these 5  \n> items\n> to the choice), \"*\" (I want all of them), \"-2-4\" (exclude 2 and 3  \n> and 4\n> from the set I have chosen so far).  These are also \"hidden\", and need\n> to be documented, but that would be a separate patch.\n\nAgreed that it belongs in a separate patch.\n\nBut I'm glad you brought this up as it reminds me of the need to watch  \nout for those characters which have special meaning for  \nlist_and_choose().\n\n> I'd rewrite the last line to:\n>\n> \treturn (defined $prefix) ? \"[$prefix]$remainder\" : $remainder;\n>\n> just in case the unique prefix is \"0\".  Otherwise you would lose the\n> first letter from \"00ReadMe\" and show remainder \"0ReadMe\" alone.\n\nExcellent catch. Crazy old perl; I didn't realize that \"0\" (the  \nstring, not the number) would evaluate to false.\n\nWill send a separate mail with a revised, squashed patch with these  \nchanges:\n\n- \"s/the first/the uniquely/\" in the commit message as you suggest\n\n- filter out prefixes which contain characters with special meaning  \nfor list_and_choose()\n\n- check \"defined $prefix\" rather than just \"$prefix\"\n\n- also fixes a problem discovered while playing with this; it didn't  \nplay nicely with untracked files\n\nCheers,\nWincent\n"},{"id":"61581","messageId":"1196518040-85584-1-git-send-email-win@wincent.com","threadId":"10959","inReplyTo":"7vy7cf87jz.fsf@gitster.siamese.dyndns.org","subject":"[PATCH 1/2] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-01T14:07:19Z","receivedAt":"2007-12-01T14:07:19Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The user interface provided by the command loop in git-add--interactive\ngives the impression that subcommands can only be launched by entering\nan integer identifier from 1 through 8.\n\nA \"hidden\" feature is that any string can be entered, and an anchored\nregex search is used to find the uniquely matching option.\n\nThis patch makes this feature a little more obvious by highlighting the\nfirst character of each subcommand (for example \"patch\" is displayed as\n\"[p]atch\").\n\nA new function is added to detect the shortest unique prefix and this\nis used to decide what to highlight. Highlighting is also applied when\nchoosing files.\n\nIn the case where the common prefix may be unreasonably large\nhighlighting is omitted; in this patch the soft limit (above which the\nhighlighting will be omitted for a particular item) is 0 (in other words,\nthere is no soft limit) and the hard limit (above which highlighting will\nbe omitted for all items) is 3, but this can be tweaked.\n\nThe actual highlighting is done by the highlight_prefix function, which\nwill enable us to implement ANSI color code-based highlighting (most\nlikely using underline or boldface) in the future.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n\nThree things to note:\n\n1. I don't actually find the \"[p]atch\" highlighting using brackets all\nthat attractive, especially when highlighting paths. This is\nespecially true when the common prefix is lengthy. This is why I've\nset the \"hard limit\" to a very low 3 in this patch. I am basically\nwaiting on the stalled \"color\" series; once that's in \"next\" then I'd\nlike to switch to a highlight style that uses underlining.\n\n2. The follow-up patch tweaks this so that the \"Add untracked\"\nsubcommand can benefit from it as well. Junio, you might want to squash\nthe two patches into one seeing as the second patch just refactors\nsomething in the first patch; but I wanted to send them to the list as\ntwo separate patches, at least for the purposes of review, because they\nreally are two separate behaviours.\n\n3. I tried to find the patch that Junio sent out earlier allowing\nmultiple selection in the \"Patch\" subcommand, to see how this interplays\nwith that, but I couldn't locate it.\n\n git-add--interactive.perl |   97 ++++++++++++++++++++++++++++++++++++++++++--\n 1 files changed, 92 insertions(+), 5 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex fb1e92a..0fb808f 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -44,7 +44,6 @@ my $status_fmt = '%12s %12s %s';\n my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \n # Returns list of hashes, contents of each of which are:\n-# PRINT:\tprint message\n # VALUE:\tpathname\n # BINARY:\tis a binary path\n # INDEX:\tis index different from HEAD?\n@@ -122,8 +121,6 @@ sub list_modified {\n \t\t}\n \t\tpush @return, +{\n \t\t\tVALUE => $_,\n-\t\t\tPRINT => (sprintf $status_fmt,\n-\t\t\t\t  $it->{INDEX}, $it->{FILE}, $_),\n \t\t\t%$it,\n \t\t};\n \t}\n@@ -159,10 +156,92 @@ sub find_unique {\n \treturn $found;\n }\n \n+# inserts string into trie and updates count for each character\n+sub update_trie {\n+\tmy ($trie, $string) = @_;\n+\tforeach (split //, $string) {\n+\t\t$trie = $trie->{$_} ||= {COUNT => 0};\n+\t\t$trie->{COUNT}++;\n+\t}\n+}\n+\n+# returns an array of tuples (prefix, remainder)\n+sub find_unique_prefixes {\n+\tmy @stuff = @_;\n+\tmy @return = ();\n+\n+\t# any single prefix exceeding the soft limit is omitted\n+\t# if any prefix exceeds the hard limit all are omitted\n+\t# 0 indicates no limit\n+\tmy $soft_limit = 0;\n+\tmy $hard_limit = 3;\n+\n+\t# build a trie modelling all possible options\n+\tmy %trie;\n+\tforeach my $print (@stuff) {\n+\t\tif ((ref $print) eq 'ARRAY') {\n+\t\t\t$print = $print->[0];\n+\t\t}\n+\t\telsif ((ref $print) eq 'HASH') {\n+\t\t\t$print = $print->{VALUE};\n+\t\t}\n+\t\tupdate_trie(\\%trie, $print);\n+\t\tpush @return, $print;\n+\t}\n+\n+\t# use the trie to find the unique prefixes\n+\tfor (my $i = 0; $i < @return; $i++) {\n+\t\tmy $ret = $return[$i];\n+\t\tmy @letters = split //, $ret;\n+\t\tmy %search = %trie;\n+\t\tmy ($prefix, $remainder);\n+\t\tmy $j;\n+\t\tfor ($j = 0; $j < @letters; $j++) {\n+\t\t\tmy $letter = $letters[$j];\n+\t\t\tif ($search{$letter}{COUNT} == 1) {\n+\t\t\t\t$prefix = substr $ret, 0, $j + 1;\n+\t\t\t\t$remainder = substr $ret, $j + 1;\n+\t\t\t\tlast;\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tmy $prefix = substr $ret, 0, $j;\n+\t\t\t\treturn ()\n+\t\t\t\t    if ($hard_limit && $j + 1 > $hard_limit);\n+\t\t\t}\n+\t\t\t%search = %{$search{$letter}};\n+\t\t}\n+\t\tif ($soft_limit && $j + 1 > $soft_limit) {\n+\t\t\t$prefix = undef;\n+\t\t\t$remainder = $ret;\n+\t\t}\n+\t\t$return[$i] = [$prefix, $remainder];\n+\t}\n+\treturn @return;\n+}\n+\n+# filters out prefixes which have special meaning to list_and_choose()\n+sub is_valid_prefix {\n+\tmy $prefix = shift;\n+\tmy $valid = (defined $prefix) &&\n+\t    !($prefix =~ /[\\s,]/) && # separators\n+\t    !($prefix =~ /^-/) &&    # deselection\n+\t    !($prefix =~ /^\\d+/) &&  # selection\n+\t    ($prefix ne '*');        # \"all\" wildcard\n+}\n+\n+# given a prefix/remainder tuple return a string with the prefix highlighted\n+# for now use square brackets; later might use ANSI colors (underline, bold)\n+sub highlight_prefix {\n+\tmy $prefix = shift;\n+\tmy $remainder = shift;\n+\tis_valid_prefix($prefix) ? \"[$prefix]$remainder\" : $remainder;\n+}\n+\n sub list_and_choose {\n \tmy ($opts, @stuff) = @_;\n \tmy (@chosen, @return);\n \tmy $i;\n+\tmy @prefixes = find_unique_prefixes(@stuff) unless $opts->{LIST_ONLY};\n \n       TOPLOOP:\n \twhile (1) {\n@@ -179,10 +258,18 @@ sub list_and_choose {\n \t\t\tmy $print = $stuff[$i];\n \t\t\tif (ref $print) {\n \t\t\t\tif ((ref $print) eq 'ARRAY') {\n-\t\t\t\t\t$print = $print->[0];\n+\t\t\t\t\t$print = @prefixes ?\n+\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n+\t\t\t\t\t    $print->[0];\n \t\t\t\t}\n \t\t\t\telse {\n-\t\t\t\t\t$print = $print->{PRINT};\n+\t\t\t\t\tmy $value = @prefixes ?\n+\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n+\t\t\t\t\t    $print->{VALUE};\n+\t\t\t\t\t$print = sprintf($status_fmt,\n+\t\t\t\t\t    $print->{INDEX},\n+\t\t\t\t\t    $print->{FILE},\n+\t\t\t\t\t    $value);\n \t\t\t\t}\n \t\t\t}\n \t\t\tprintf(\"%s%2d: %s\", $chosen, $i+1, $print);\n-- \n1.5.3.6.953.gdffc\n"},{"id":"61582","messageId":"1196518040-85584-2-git-send-email-win@wincent.com","threadId":"10959","inReplyTo":"1196518040-85584-1-git-send-email-win@wincent.com","subject":"[PATCH 2/2] Teach git-add--interactive to highlight untracked file prefixes","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-01T14:07:20Z","receivedAt":"2007-12-01T14:07:20Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"Tweak the list_and_choose function so that untracked files will\nuse the automatic prefix detection machinery.\n\nThis works because while previously we handled arrays (command\nmenus), hashes (patch subcommand) now we explicitly handle strings\n(add untracked subcommand).\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n git-add--interactive.perl |   30 +++++++++++++++---------------\n 1 files changed, 15 insertions(+), 15 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 0fb808f..a1aee21 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -256,21 +256,21 @@ sub list_and_choose {\n \t\tfor ($i = 0; $i < @stuff; $i++) {\n \t\t\tmy $chosen = $chosen[$i] ? '*' : ' ';\n \t\t\tmy $print = $stuff[$i];\n-\t\t\tif (ref $print) {\n-\t\t\t\tif ((ref $print) eq 'ARRAY') {\n-\t\t\t\t\t$print = @prefixes ?\n-\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n-\t\t\t\t\t    $print->[0];\n-\t\t\t\t}\n-\t\t\t\telse {\n-\t\t\t\t\tmy $value = @prefixes ?\n-\t\t\t\t\t    highlight_prefix(@{$prefixes[$i]}) :\n-\t\t\t\t\t    $print->{VALUE};\n-\t\t\t\t\t$print = sprintf($status_fmt,\n-\t\t\t\t\t    $print->{INDEX},\n-\t\t\t\t\t    $print->{FILE},\n-\t\t\t\t\t    $value);\n-\t\t\t\t}\n+\t\t\tmy $ref = ref $print;\n+\t\t\tmy $highlighted = highlight_prefix(@{$prefixes[$i]})\n+\t\t\t    if @prefixes;\n+\t\t\tif ($ref eq 'ARRAY') {\n+\t\t\t\t$print = $highlighted || $print->[0];\n+\t\t\t}\n+\t\t\telsif ($ref eq 'HASH') {\n+\t\t\t\tmy $value = $highlighted || $print->{VALUE};\n+\t\t\t\t$print = sprintf($status_fmt,\n+\t\t\t\t    $print->{INDEX},\n+\t\t\t\t    $print->{FILE},\n+\t\t\t\t    $value);\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\t$print = $highlighted || $print;\n \t\t\t}\n \t\t\tprintf(\"%s%2d: %s\", $chosen, $i+1, $print);\n \t\t\tif (($opts->{LIST_FLAT}) &&\n-- \n1.5.3.6.953.gdffc\n"},{"id":"61584","messageId":"697AB37F-784D-4374-A290-0E6290712B29@wincent.com","threadId":"10959","inReplyTo":"1196518040-85584-1-git-send-email-win@wincent.com","subject":"Re: [PATCH 1/2] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-01T14:15:33Z","receivedAt":"2007-12-01T14:15:33Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 1/12/2007, a las 15:07, Wincent Colaiuta escribió:\n\n> +# filters out prefixes which have special meaning to  \n> list_and_choose()\n> +sub is_valid_prefix {\n> +\tmy $prefix = shift;\n> +\tmy $valid = (defined $prefix) &&\n> +\t    !($prefix =~ /[\\s,]/) && # separators\n> +\t    !($prefix =~ /^-/) &&    # deselection\n> +\t    !($prefix =~ /^\\d+/) &&  # selection\n> +\t    ($prefix ne '*');        # \"all\" wildcard\n> +}\n\nDoh, that's supposed to be:\n\n\treturn (defined $prefix)...\n\nNot:\n\n\tmy $valid = (defined $prefix)...\n\nIt actually works as is, but I had changed the \"return\" while working  \non the patch (for debugging) and forgot to change it back afterwards.\n\nAnd yes, I did proofread the patch before sending it. I just didn't  \nnotice the first time around.\n\nCheers,\nWincent\n"},{"id":"61585","messageId":"1196519351-86280-1-git-send-email-win@wincent.com","threadId":"10959","inReplyTo":"697AB37F-784D-4374-A290-0E6290712B29@wincent.com","subject":"[REPLACEMENT PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-01T14:29:11Z","receivedAt":"2007-12-01T14:29:11Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"The user interface provided by the command loop in git-add--interactive\ngives the impression that subcommands can only be launched by entering\nan integer identifier from 1 through 8.\n\nA \"hidden\" feature is that any string can be entered, and an anchored\nregex search is used to find the uniquely matching option.\n\nThis patch makes this feature a little more obvious by highlighting the\nfirst character of each subcommand (for example \"patch\" is displayed as\n\"[p]atch\").\n\nA new function is added to detect the shortest unique prefix and this\nis used to decide what to highlight. Highlighting is also applied when\nchoosing files.\n\nIn the case where the common prefix may be unreasonably large\nhighlighting is omitted; in this patch the soft limit (above which the\nhighlighting will be omitted for a particular item) is 0 (in other words,\nthere is no soft limit) and the hard limit (above which highlighting will\nbe omitted for all items) is 3, but this can be tweaked.\n\nThe actual highlighting is done by the highlight_prefix function, which\nwill enable us to implement ANSI color code-based highlighting (most\nlikely using underline or boldface) in the future.\n\nSigned-off-by: Wincent Colaiuta <win@wincent.com>\n---\n\nI will go now and crawl under a rock.\n\n git-add--interactive.perl |  110 ++++++++++++++++++++++++++++++++++++++++----\n 1 files changed, 100 insertions(+), 10 deletions(-)\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex fb1e92a..0e358b5 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -44,7 +44,6 @@ my $status_fmt = '%12s %12s %s';\n my $status_head = sprintf($status_fmt, 'staged', 'unstaged', 'path');\n \n # Returns list of hashes, contents of each of which are:\n-# PRINT:\tprint message\n # VALUE:\tpathname\n # BINARY:\tis a binary path\n # INDEX:\tis index different from HEAD?\n@@ -122,8 +121,6 @@ sub list_modified {\n \t\t}\n \t\tpush @return, +{\n \t\t\tVALUE => $_,\n-\t\t\tPRINT => (sprintf $status_fmt,\n-\t\t\t\t  $it->{INDEX}, $it->{FILE}, $_),\n \t\t\t%$it,\n \t\t};\n \t}\n@@ -159,10 +156,95 @@ sub find_unique {\n \treturn $found;\n }\n \n+# inserts string into trie and updates count for each character\n+sub update_trie {\n+\tmy ($trie, $string) = @_;\n+\tforeach (split //, $string) {\n+\t\t$trie = $trie->{$_} ||= {COUNT => 0};\n+\t\t$trie->{COUNT}++;\n+\t}\n+}\n+\n+# returns an array of tuples (prefix, remainder)\n+sub find_unique_prefixes {\n+\tmy @stuff = @_;\n+\tmy @return = ();\n+\n+\t# any single prefix exceeding the soft limit is omitted\n+\t# if any prefix exceeds the hard limit all are omitted\n+\t# 0 indicates no limit\n+\tmy $soft_limit = 0;\n+\tmy $hard_limit = 3;\n+\n+\t# build a trie modelling all possible options\n+\tmy %trie;\n+\tforeach my $print (@stuff) {\n+\t\tif ((ref $print) eq 'ARRAY') {\n+\t\t\t$print = $print->[0];\n+\t\t}\n+\t\telsif ((ref $print) eq 'HASH') {\n+\t\t\t$print = $print->{VALUE};\n+\t\t}\n+\t\tupdate_trie(\\%trie, $print);\n+\t\tpush @return, $print;\n+\t}\n+\n+\t# use the trie to find the unique prefixes\n+\tfor (my $i = 0; $i < @return; $i++) {\n+\t\tmy $ret = $return[$i];\n+\t\tmy @letters = split //, $ret;\n+\t\tmy %search = %trie;\n+\t\tmy ($prefix, $remainder);\n+\t\tmy $j;\n+\t\tfor ($j = 0; $j < @letters; $j++) {\n+\t\t\tmy $letter = $letters[$j];\n+\t\t\tif ($search{$letter}{COUNT} == 1) {\n+\t\t\t\t$prefix = substr $ret, 0, $j + 1;\n+\t\t\t\t$remainder = substr $ret, $j + 1;\n+\t\t\t\tlast;\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tmy $prefix = substr $ret, 0, $j;\n+\t\t\t\treturn ()\n+\t\t\t\t    if ($hard_limit && $j + 1 > $hard_limit);\n+\t\t\t}\n+\t\t\t%search = %{$search{$letter}};\n+\t\t}\n+\t\tif ($soft_limit && $j + 1 > $soft_limit) {\n+\t\t\t$prefix = undef;\n+\t\t\t$remainder = $ret;\n+\t\t}\n+\t\t$return[$i] = [$prefix, $remainder];\n+\t}\n+\treturn @return;\n+}\n+\n+# filters out prefixes which have special meaning to list_and_choose()\n+sub is_valid_prefix {\n+\tmy $prefix = shift;\n+\treturn (defined $prefix) &&\n+\t    !($prefix =~ /[\\s,]/) && # separators\n+\t    !($prefix =~ /^-/) &&    # deselection\n+\t    !($prefix =~ /^\\d+/) &&  # selection\n+\t    ($prefix ne '*');        # \"all\" wildcard\n+}\n+\n+# given a prefix/remainder tuple return a string with the prefix highlighted\n+# for now use square brackets; later might use ANSI colors (underline, bold)\n+sub highlight_prefix {\n+\tmy $prefix = shift;\n+\tmy $remainder = shift;\n+\treturn $remainder unless defined $prefix;\n+\treturn is_valid_prefix($prefix) ?\n+\t    \"[$prefix]$remainder\" :\n+\t    \"$prefix$remainder\";\n+}\n+\n sub list_and_choose {\n \tmy ($opts, @stuff) = @_;\n \tmy (@chosen, @return);\n \tmy $i;\n+\tmy @prefixes = find_unique_prefixes(@stuff) unless $opts->{LIST_ONLY};\n \n       TOPLOOP:\n \twhile (1) {\n@@ -177,13 +259,21 @@ sub list_and_choose {\n \t\tfor ($i = 0; $i < @stuff; $i++) {\n \t\t\tmy $chosen = $chosen[$i] ? '*' : ' ';\n \t\t\tmy $print = $stuff[$i];\n-\t\t\tif (ref $print) {\n-\t\t\t\tif ((ref $print) eq 'ARRAY') {\n-\t\t\t\t\t$print = $print->[0];\n-\t\t\t\t}\n-\t\t\t\telse {\n-\t\t\t\t\t$print = $print->{PRINT};\n-\t\t\t\t}\n+\t\t\tmy $ref = ref $print;\n+\t\t\tmy $highlighted = highlight_prefix(@{$prefixes[$i]})\n+\t\t\t    if @prefixes;\n+\t\t\tif ($ref eq 'ARRAY') {\n+\t\t\t\t$print = $highlighted || $print->[0];\n+\t\t\t}\n+\t\t\telsif ($ref eq 'HASH') {\n+\t\t\t\tmy $value = $highlighted || $print->{VALUE};\n+\t\t\t\t$print = sprintf($status_fmt,\n+\t\t\t\t    $print->{INDEX},\n+\t\t\t\t    $print->{FILE},\n+\t\t\t\t    $value);\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\t$print = $highlighted || $print;\n \t\t\t}\n \t\t\tprintf(\"%s%2d: %s\", $chosen, $i+1, $print);\n \t\t\tif (($opts->{LIST_FLAT}) &&\n-- \n1.5.3.6.953.gdffc\n"},{"id":"61642","messageId":"5B4BC281-10BD-437F-A956-EEB73F40A76C@wincent.com","threadId":"10959","inReplyTo":"7vy7cf87jz.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-02T14:11:24Z","receivedAt":"2007-12-02T14:11:24Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 1/12/2007, a las 3:36, Junio C Hamano escribió:\n\n> When list_and_choose() function is letting you choose more than one\n> items, its prompt becomes \">> \", instead of \"> \" that is used for a\n> singleton choice.  To that prompt, you can say \"3-7\" (Add these 5  \n> items\n> to the choice), \"*\" (I want all of them), \"-2-4\" (exclude 2 and 3  \n> and 4\n> from the set I have chosen so far).  These are also \"hidden\", and need\n> to be documented, but that would be a separate patch.\n\nI was just about to prepare some documentation for this when I saw  \nthat it is already documented, and by none other than you, Junio! (see  \n6a5ad23d).\n\nUnless by \"documentation\" you meant to somehow expose these in the  \ninterface at runtime... something like this? (applied on top of the  \npatch I just sent to the list):\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 32fb9ea..e7b07ee 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -237,7 +237,8 @@ sub is_valid_prefix {\n  \t    !($prefix =~ /[\\s,]/) && # separators\n  \t    !($prefix =~ /^-/) &&    # deselection\n  \t    !($prefix =~ /^\\d+/) &&  # selection\n-\t    ($prefix ne '*');        # \"all\" wildcard\n+\t    ($prefix ne '*') &&      # \"all\" wildcard\n+\t    ($prefix ne '?');        # prompt help\n  }\n\n  # given a prefix/remainder tuple return a string with the prefix  \nhighlighted\n@@ -308,7 +309,7 @@ sub list_and_choose {\n  \t\t\tprint \"> \";\n  \t\t}\n  \t\telse {\n-\t\t\tprint \">> \";\n+\t\t\tprint \" (?)>> \";\n  \t\t}\n  \t\tmy $line = <STDIN>;\n  \t\tif (!$line) {\n@@ -318,6 +319,10 @@ sub list_and_choose {\n  \t\t}\n  \t\tchomp $line;\n  \t\tlast if $line eq '';\n+\t\tif ($line eq '?' && !$opts->{SINGLETON}) {\n+\t\t\tprompt_help_cmd();\n+\t\t\tnext TOPLOOP;\n+\t\t}\n  \t\tfor my $choice (split(/[\\s,]+/, $line)) {\n  \t\t\tmy $choose = 1;\n  \t\t\tmy ($bottom, $top);\n@@ -363,6 +368,19 @@ sub list_and_choose {\n  \treturn @return;\n  }\n\n+sub prompt_help_cmd {\n+\tprint <<\\EOF ;\n+Prompt help:\n+1          - select a single item\n+3-5        - select a range of items\n+2-3,6-9    - select multiple ranges\n+foo        - select item based on unique prefix\n+-...       - unselect specified items\n+*          - choose all items\n+           - (empty) finish selecting\n+EOF\n+}\n+\n  sub status_cmd {\n  \tlist_and_choose({ LIST_ONLY => 1, HEADER => $status_head },\n  \t\t\tlist_modified());\n\n\nCheers,\nWincent\n"},{"id":"61672","messageId":"7veje4ykzg.fsf@gitster.siamese.dyndns.org","threadId":"10959","inReplyTo":"5B4BC281-10BD-437F-A956-EEB73F40A76C@wincent.com","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-02T19:06:43Z","receivedAt":"2007-12-02T19:06:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Wincent Colaiuta <win@wincent.com> writes:\n\n> Unless by \"documentation\" you meant to somehow expose these in the  \n> interface at runtime... something like this? (applied on top of the  \n> patch I just sent to the list):\n\nI did not recall (and was too lazy to check) if they were documented\nalready, but as you suggest, I think letting people type ? at the prompt\nto get a help is always a good idea.  So, instead of doing this part:\n\n> @@ -308,7 +309,7 @@ sub list_and_choose {\n>   \t\t\tprint \"> \";\n>   \t\t}\n>   \t\telse {\n> -\t\t\tprint \">> \";\n> +\t\t\tprint \" (?)>> \";\n\nI'd prefer accepting '?'  as a valid \"help me\" input and showing\nappropriate help for _both_ singleton select and multiple select,\nwithout mentioning \" (?)\".  For this, your prompt_help_cmd needs to be\nenhanced to limit the help to singleton case, though.\n"},{"id":"61748","messageId":"5BE6088E-22F0-4154-BAE5-22F3229D0782@wincent.com","threadId":"10959","inReplyTo":"7veje4ykzg.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Highlight keyboard shortcuts in git-add--interactive","fromName":"Wincent Colaiuta","fromEmail":"win@wincent.com","sentAt":"2007-12-03T08:09:43Z","receivedAt":"2007-12-03T08:09:43Z","isPatch":true,"sender":{"key":"greg@hurrell.net","avatar":"https://avatars.githubusercontent.com/u/7074?v=4"},"body":"El 2/12/2007, a las 20:06, Junio C Hamano escribió:\n\n> Wincent Colaiuta <win@wincent.com> writes:\n>\n>> Unless by \"documentation\" you meant to somehow expose these in the\n>> interface at runtime... something like this? (applied on top of the\n>> patch I just sent to the list):\n>\n> I did not recall (and was too lazy to check) if they were documented\n> already, but as you suggest, I think letting people type ? at the  \n> prompt\n> to get a help is always a good idea.  So, instead of doing this part:\n>\n>> @@ -308,7 +309,7 @@ sub list_and_choose {\n>>  \t\t\tprint \"> \";\n>>  \t\t}\n>>  \t\telse {\n>> -\t\t\tprint \">> \";\n>> +\t\t\tprint \" (?)>> \";\n>\n> I'd prefer accepting '?'  as a valid \"help me\" input and showing\n> appropriate help for _both_ singleton select and multiple select,\n> without mentioning \" (?)\".  For this, your prompt_help_cmd needs to be\n> enhanced to limit the help to singleton case, though.\n\n\nThat's actually the way I did it the first time, but then decided that  \nthe singleton prompt help had so little to say that I doubted about  \nincluding it. Something like this, once again on top of the patch I  \nposted yesterday (\"Fixes for automatic prefix highlighting\"):\n\ndiff --git a/git-add--interactive.perl b/git-add--interactive.perl\nindex 32fb9ea..335c2c6 100755\n--- a/git-add--interactive.perl\n+++ b/git-add--interactive.perl\n@@ -237,7 +237,8 @@ sub is_valid_prefix {\n  \t    !($prefix =~ /[\\s,]/) && # separators\n  \t    !($prefix =~ /^-/) &&    # deselection\n  \t    !($prefix =~ /^\\d+/) &&  # selection\n-\t    ($prefix ne '*');        # \"all\" wildcard\n+\t    ($prefix ne '*') &&      # \"all\" wildcard\n+\t    ($prefix ne '?');        # prompt help\n  }\n\n  # given a prefix/remainder tuple return a string with the prefix  \nhighlighted\n@@ -318,6 +319,12 @@ sub list_and_choose {\n  \t\t}\n  \t\tchomp $line;\n  \t\tlast if $line eq '';\n+\t\tif ($line eq '?') {\n+\t\t\t$opts->{SINGLETON} ?\n+\t\t\t    singleton_prompt_help_cmd() :\n+\t\t\t    prompt_help_cmd();\n+\t\t\tnext TOPLOOP;\n+\t\t}\n  \t\tfor my $choice (split(/[\\s,]+/, $line)) {\n  \t\t\tmy $choose = 1;\n  \t\t\tmy ($bottom, $top);\n@@ -363,6 +370,28 @@ sub list_and_choose {\n  \treturn @return;\n  }\n\n+sub singleton_prompt_help_cmd {\n+\tprint <<\\EOF ;\n+Prompt help:\n+1          - select a numbered item\n+foo        - select item based on unique prefix\n+           - (empty) select nothing\n+EOF\n+}\n+\n+sub prompt_help_cmd {\n+\tprint <<\\EOF ;\n+Prompt help:\n+1          - select a single item\n+3-5        - select a range of items\n+2-3,6-9    - select multiple ranges\n+foo        - select item based on unique prefix\n+-...       - unselect specified items\n+*          - choose all items\n+           - (empty) finish selecting\n+EOF\n+}\n+\n  sub status_cmd {\n  \tlist_and_choose({ LIST_ONLY => 1, HEADER => $status_head },\n  \t\t\tlist_modified());\n\n\n\nCheers,\nWincent\n"}]}