{"thread":{"id":"48111","subject":"[PATCH] completion: add option completion for most builtin commands","startedAt":"2018-03-21T19:31:18Z","lastAt":"2018-03-25T00:59:36Z","messageCount":18,"participants":["Nguyễn Thái Ngọc Duy","Junio C Hamano","Duy Nguyen","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"342448","messageId":"20180321193039.19779-1-pclouds@gmail.com","threadId":"48111","inReplyTo":null,"subject":"[PATCH] completion: add option completion for most builtin commands","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-21T19:30:39Z","receivedAt":"2018-03-21T19:31:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"These commands can take options and use parse-options so it's quite\neasy to allow option completion. This does not pollute the command\nname completion though. \"git <tab>\" will show you the same set as\nbefore. This only kicks in when you type the correct command name.\n\nSome other builtin commands are not still added because either they\ndon't use parse-options, or they are deprecated, or they are those\n-helper commands that are used to move some logic back in C for\nsh-based commands.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 276 +++++++++++++++++++++++++\n 1 file changed, 276 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6da95b8095..0cd9180f48 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1202,6 +1202,15 @@ _git_bisect ()\n \tesac\n }\n \n+_git_blame() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin blame\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_branch ()\n {\n \tlocal i c=1 only_local_ref=\"n\" has_r=\"n\"\n@@ -1254,6 +1263,42 @@ _git_bundle ()\n \tesac\n }\n \n+_git_cat_file() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin cat-file\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_check_attr() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin check-attr\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_check_ignore() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin check-ignore\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_check_mailmap() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin check-mailmap\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_checkout ()\n {\n \t__git_has_doubledash && return\n@@ -1278,6 +1323,15 @@ _git_checkout ()\n \tesac\n }\n \n+_git_checkout_index() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin checkout-index\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_cherry ()\n {\n \t__git_complete_refs\n@@ -1326,6 +1380,15 @@ _git_clone ()\n \tesac\n }\n \n+_git_column() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin column\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n __git_untracked_file_modes=\"all no normal\"\n \n _git_commit ()\n@@ -1365,6 +1428,15 @@ _git_commit ()\n \tfi\n }\n \n+_git_count_objects() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin count-objects\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_describe ()\n {\n \tcase \"$cur\" in\n@@ -1446,6 +1518,15 @@ _git_difftool ()\n \t__git_complete_revlist_file\n }\n \n+_git_fast_export() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin fast-export\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n __git_fetch_recurse_submodules=\"yes on-demand no\"\n \n _git_fetch ()\n@@ -1573,6 +1654,15 @@ _git_grep ()\n \t__git_complete_refs\n }\n \n+_git_hash_object() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin hash-object\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_help ()\n {\n \tcase \"$cur\" in\n@@ -1590,6 +1680,15 @@ _git_help ()\n \t\t\"\n }\n \n+_git_index_pack() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin index-pack\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_init ()\n {\n \tcase \"$cur\" in\n@@ -1606,6 +1705,15 @@ _git_init ()\n \tesac\n }\n \n+_git_interpret_trailers() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin interpret-trailers\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_ls_files ()\n {\n \tcase \"$cur\" in\n@@ -1765,6 +1873,15 @@ _git_merge ()\n \t__git_complete_refs\n }\n \n+_git_merge_file() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin merge-file\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_mergetool ()\n {\n \tcase \"$cur\" in\n@@ -1790,6 +1907,15 @@ _git_merge_base ()\n \t__git_complete_refs\n }\n \n+_git_mktree() {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin mktree\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_mv ()\n {\n \tcase \"$cur\" in\n@@ -1853,6 +1979,46 @@ _git_notes ()\n \tesac\n }\n \n+_git_pack_objects ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin pack-objects\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_pack_refs ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin pack-refs\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_prune ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin prune\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_prune_packed ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin prune-packed\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_pull ()\n {\n \t__git_complete_strategy && return\n@@ -1925,6 +2091,16 @@ _git_push ()\n \t__git_complete_remote_or_refspec\n }\n \n+_git_read_tree ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin read-tree\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_rebase ()\n {\n \t__git_find_repo_path\n@@ -1974,6 +2150,16 @@ _git_reflog ()\n \tfi\n }\n \n+_git_repack ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin repack\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n __git_send_email_confirm_options=\"always never auto cc compose\"\n __git_send_email_suppresscc_options=\"author self cc bodycc sob cccmd body all\"\n \n@@ -2031,6 +2217,26 @@ _git_send_email ()\n \t__git_complete_revlist\n }\n \n+_git_send_pack ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin send-pack\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_show_ref ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin show-ref\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_stage ()\n {\n \t_git_add\n@@ -2082,6 +2288,26 @@ _git_status ()\n \t__git_complete_index_file \"$complete_opt\"\n }\n \n+_git_stripspace ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin stripspace\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_symbolic_ref ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin symbolic-ref\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n __git_config_get_set_variables ()\n {\n \tlocal prevword word config_file= c=$cword\n@@ -2998,6 +3224,46 @@ _git_tag ()\n \tesac\n }\n \n+_git_update_index ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin update-index\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_update_ref ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin update-ref\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_verify_commit ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin verify-commit\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n+_git_verify_tag ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin verify-tag\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n _git_whatchanged ()\n {\n \t_git_log\n@@ -3032,6 +3298,16 @@ _git_worktree ()\n \tfi\n }\n \n+_git_write_tree ()\n+{\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin write-tree\n+\t\treturn\n+\t\t;;\n+\tesac\n+}\n+\n __git_main ()\n {\n \tlocal i c=1 command __git_dir __git_repo_path\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342457","messageId":"xmqqd0zxno0j.fsf@gitster-ct.c.googlers.com","threadId":"48111","inReplyTo":"20180321193039.19779-1-pclouds@gmail.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-03-21T20:59:24Z","receivedAt":"2018-03-21T20:59:33Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> These commands can take options and use parse-options so it's quite\n> easy to allow option completion. This does not pollute the command\n> name completion though. \"git <tab>\" will show you the same set as\n> before. This only kicks in when you type the correct command name.\n>\n> Some other builtin commands are not still added because either they\n> don't use parse-options, or they are deprecated, or they are those\n> -helper commands that are used to move some logic back in C for\n> sh-based commands.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  contrib/completion/git-completion.bash | 276 +++++++++++++++++++++++++\n>  1 file changed, 276 insertions(+)\n\nWow, just wow.  It however looks a lot of boilerplates, e.g. looking\nat these, we notice ...\n\n> +_git_blame() {\n> +\tcase \"$cur\" in\n> +\t--*)\n> +\t\t__gitcomp_builtin blame\n> +\t\treturn\n> +\t\t;;\n> +\tesac\n> +}\n> +\n>  \n> +_git_cat_file() {\n> +\tcase \"$cur\" in\n> +\t--*)\n> +\t\t__gitcomp_builtin cat-file\n> +\t\treturn\n> +\t\t;;\n> +\tesac\n> +}\n> +\n> +_git_check_attr() {\n> +\tcase \"$cur\" in\n> +\t--*)\n> +\t\t__gitcomp_builtin check-attr\n> +\t\treturn\n> +\t\t;;\n> +\tesac\n> +}\n\n... the only thing we need for the above three is a table that says\n\"use blame for blame, cat-file for cat_file, and check-attr for\ncheck_attr\".\n\nAnd that pattern repeats throughout the patch.  I wonder if we can\nexpress the same a lot more concisely by updating the caller that\ncalls these command specific helpers?\n\n"},{"id":"342489","messageId":"CACsJy8CWWSixQpXDh+q108j4xF8vpm5gsj2u3gJEgW=2bnXQHA@mail.gmail.com","threadId":"48111","inReplyTo":"xmqqd0zxno0j.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-22T05:12:58Z","receivedAt":"2018-03-22T05:13:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Mar 21, 2018 at 9:59 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n>\n>> These commands can take options and use parse-options so it's quite\n>> easy to allow option completion. This does not pollute the command\n>> name completion though. \"git <tab>\" will show you the same set as\n>> before. This only kicks in when you type the correct command name.\n>>\n>> Some other builtin commands are not still added because either they\n>> don't use parse-options, or they are deprecated, or they are those\n>> -helper commands that are used to move some logic back in C for\n>> sh-based commands.\n>>\n>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>> ---\n>>  contrib/completion/git-completion.bash | 276 +++++++++++++++++++++++++\n>>  1 file changed, 276 insertions(+)\n>\n> Wow, just wow.  It however looks a lot of boilerplates, e.g. looking\n> at these, we notice ...\n>\n>> +_git_blame() {\n>> +     case \"$cur\" in\n>> +     --*)\n>> +             __gitcomp_builtin blame\n>> +             return\n>> +             ;;\n>> +     esac\n>> +}\n>> +\n>>\n>> +_git_cat_file() {\n>> +     case \"$cur\" in\n>> +     --*)\n>> +             __gitcomp_builtin cat-file\n>> +             return\n>> +             ;;\n>> +     esac\n>> +}\n>> +\n>> +_git_check_attr() {\n>> +     case \"$cur\" in\n>> +     --*)\n>> +             __gitcomp_builtin check-attr\n>> +             return\n>> +             ;;\n>> +     esac\n>> +}\n>\n> ... the only thing we need for the above three is a table that says\n> \"use blame for blame, cat-file for cat_file, and check-attr for\n> check_attr\".\n>\n> And that pattern repeats throughout the patch.  I wonder if we can\n> express the same a lot more concisely by updating the caller that\n> calls these command specific helpers?\n>\n\nYeah. I almost went to just generate and eval these functions. But we\nstill need to keep a list of \"bultin with --git-completion-helper\"\nsupport somewhere, and people may want to complete arguments without\ndouble dashes (e.g. read-tree should take a ref...) which can't be\nhelped by --git-completion-helper.\n-- \nDuy\n"},{"id":"342524","messageId":"xmqqy3ikkpba.fsf@gitster-ct.c.googlers.com","threadId":"48111","inReplyTo":"CACsJy8CWWSixQpXDh+q108j4xF8vpm5gsj2u3gJEgW=2bnXQHA@mail.gmail.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-03-22T17:11:53Z","receivedAt":"2018-03-22T17:12:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n>> And that pattern repeats throughout the patch.  I wonder if we can\n>> express the same a lot more concisely by updating the caller that\n>> calls these command specific helpers?\n>\n> Yeah. I almost went to just generate and eval these functions. But we\n> still need to keep a list of \"bultin with --git-completion-helper\"\n> support somewhere, and people may want to complete arguments without\n> double dashes (e.g. read-tree should take a ref...) which can't be\n> helped by --git-completion-helper.\n\nHmph, I actually did not have 'eval' in mind.\n\nRather, I was wondering if it is cleaner to update __git_main where\nit computes $completion_func by mangling $command and then calls\nit---instead call __gitcomp_builtin directly when the $command\nappears in such a \"list of builtins that knows --completion-helper\nand no custom completion\".\n\n"},{"id":"342526","messageId":"20180322173553.GA20984@duynguyen.home","threadId":"48111","inReplyTo":"xmqqy3ikkpba.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-22T17:35:54Z","receivedAt":"2018-03-22T17:36:05Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 22, 2018 at 10:11:53AM -0700, Junio C Hamano wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n> \n> >> And that pattern repeats throughout the patch.  I wonder if we can\n> >> express the same a lot more concisely by updating the caller that\n> >> calls these command specific helpers?\n> >\n> > Yeah. I almost went to just generate and eval these functions. But we\n> > still need to keep a list of \"bultin with --git-completion-helper\"\n> > support somewhere, and people may want to complete arguments without\n> > double dashes (e.g. read-tree should take a ref...) which can't be\n> > helped by --git-completion-helper.\n> \n> Hmph, I actually did not have 'eval' in mind.\n> \n> Rather, I was wondering if it is cleaner to update __git_main where\n> it computes $completion_func by mangling $command and then calls\n> it---instead call __gitcomp_builtin directly when the $command\n> appears in such a \"list of builtins that knows --completion-helper\n> and no custom completion\".\n\nAh. Something like this? Seems to work fine and definitely not as ugly\nas eval.\n\n-- 8< --\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 6da95b8095..960e26e09d 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -3032,6 +3032,32 @@ _git_worktree ()\n \tfi\n }\n \n+__git_main_with_parseopt_helper='\n+\tblame cat-file check-attr check-ignore\n+\tcheck-mailmap checkout-index column count-objects fast-export\n+\thash-object index-pack interpret-trailers merge-file mktree\n+\tpack-objects pack-refs prune prune-packed read-tree repack\n+\tsend-pack show-ref stripspace symbolic-ref update-index\n+\tupdate-ref verify-commit verify-tag write-tree\n+'\n+__git_complete_command() {\n+\tlocal command=\"$1\"\n+\tlocal completion_func=\"_git_${command//-/_}\"\n+\tif declare -f $completion_func >/dev/null 2>/dev/null; then\n+\t\t$completion_func\n+\telif echo $__git_main_with_parseopt_helper | git grep -w \"$command\" >/dev/null; then\n+\t\tcase \"$cur\" in\n+\t\t--*)\n+\t\t\t__gitcomp_builtin \"$command\"\n+\t\t\treturn 0\n+\t\t\t;;\n+\t\tesac\n+\t\treturn 0\n+\telse\n+\t\treturn 1\n+\tfi\n+}\n+\n __git_main ()\n {\n \tlocal i c=1 command __git_dir __git_repo_path\n@@ -3091,14 +3117,12 @@ __git_main ()\n \t\treturn\n \tfi\n \n-\tlocal completion_func=\"_git_${command//-/_}\"\n-\tdeclare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return\n+\t__git_complete_command \"$command\" && return\n \n \tlocal expansion=$(__git_aliased_command \"$command\")\n \tif [ -n \"$expansion\" ]; then\n \t\twords[1]=$expansion\n-\t\tcompletion_func=\"_git_${expansion//-/_}\"\n-\t\tdeclare -f $completion_func >/dev/null 2>/dev/null && $completion_func\n+\t\t__git_complete_command \"$expansion\"\n \tfi\n }\n \n-- 8< --\n\n"},{"id":"342532","messageId":"xmqqtvt8kn92.fsf@gitster-ct.c.googlers.com","threadId":"48111","inReplyTo":"20180322173553.GA20984@duynguyen.home","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2018-03-22T17:56:25Z","receivedAt":"2018-03-22T17:56:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> +__git_main_with_parseopt_helper='\n> +\tblame cat-file check-attr check-ignore\n> +\tcheck-mailmap checkout-index column count-objects fast-export\n> +\thash-object index-pack interpret-trailers merge-file mktree\n> +\tpack-objects pack-refs prune prune-packed read-tree repack\n> +\tsend-pack show-ref stripspace symbolic-ref update-index\n> +\tupdate-ref verify-commit verify-tag write-tree\n> +'\n> +__git_complete_command() {\n> +\tlocal command=\"$1\"\n> +\tlocal completion_func=\"_git_${command//-/_}\"\n> +\tif declare -f $completion_func >/dev/null 2>/dev/null; then\n> +\t\t$completion_func\n> +\telif echo $__git_main_with_parseopt_helper | git grep -w \"$command\" >/dev/null; then\n\n\"git grep\"???\n\nI imagined that you'd keep an associative shell array (we are not\nconstrained by POSIX here) that can be used like so\n\n\telif test -n \"${__git_main_with_parseopt_helper[$command]}\"; then\n\nOf course, a more traditional way to write it without spawning grep\nor pipe is\n\n\tcase \" $__git_main_with_parseopt_helper \" in\n\t*\" $command \"*)\n\t\t... Yes, $command is on the list ...\n\t\t;;\n\t*)\n\t\t... No, $command is not on the list ...\n\t\t;;\n\tesac\n"},{"id":"342533","messageId":"CACsJy8AbviwGqjWoq_SYDpLkM4PALcZOP432HBe0S1D=m16DLg@mail.gmail.com","threadId":"48111","inReplyTo":"xmqqtvt8kn92.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-22T18:01:51Z","receivedAt":"2018-03-22T18:02:37Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 22, 2018 at 6:56 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> +__git_main_with_parseopt_helper='\n>> +     blame cat-file check-attr check-ignore\n>> +     check-mailmap checkout-index column count-objects fast-export\n>> +     hash-object index-pack interpret-trailers merge-file mktree\n>> +     pack-objects pack-refs prune prune-packed read-tree repack\n>> +     send-pack show-ref stripspace symbolic-ref update-index\n>> +     update-ref verify-commit verify-tag write-tree\n>> +'\n>> +__git_complete_command() {\n>> +     local command=\"$1\"\n>> +     local completion_func=\"_git_${command//-/_}\"\n>> +     if declare -f $completion_func >/dev/null 2>/dev/null; then\n>> +             $completion_func\n>> +     elif echo $__git_main_with_parseopt_helper | git grep -w \"$command\" >/dev/null; then\n>\n> \"git grep\"???\n\nGIt has taught my fingers some bad habit.\n\n>\n> I imagined that you'd keep an associative shell array (we are not\n> constrained by POSIX here) that can be used like so\n>\n>         elif test -n \"${__git_main_with_parseopt_helper[$command]}\"; then\n>\n\nGreat. We could even kill two existing _git_xxx functions because they\nare too simple they could be replaced with this new code. I'll send\nout a series later.\n-- \nDuy\n"},{"id":"342821","messageId":"CACsJy8CxdGXUcqP5r2u6kcjrsftO+-CrNVaFy5wv85Mm3F8pPg@mail.gmail.com","threadId":"48111","inReplyTo":"xmqqtvt8kn92.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH] completion: add option completion for most builtin commands","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T13:38:19Z","receivedAt":"2018-03-24T13:38:55Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Mar 22, 2018 at 6:56 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> +__git_main_with_parseopt_helper='\n>> +     blame cat-file check-attr check-ignore\n>> +     check-mailmap checkout-index column count-objects fast-export\n>> +     hash-object index-pack interpret-trailers merge-file mktree\n>> +     pack-objects pack-refs prune prune-packed read-tree repack\n>> +     send-pack show-ref stripspace symbolic-ref update-index\n>> +     update-ref verify-commit verify-tag write-tree\n>> +'\n>> +__git_complete_command() {\n>> +     local command=\"$1\"\n>> +     local completion_func=\"_git_${command//-/_}\"\n>> +     if declare -f $completion_func >/dev/null 2>/dev/null; then\n>> +             $completion_func\n>> +     elif echo $__git_main_with_parseopt_helper | git grep -w \"$command\" >/dev/null; then\n>\n> \"git grep\"???\n>\n> I imagined that you'd keep an associative shell array (we are not\n> constrained by POSIX here) that can be used like so\n>\n>         elif test -n \"${__git_main_with_parseopt_helper[$command]}\"; then\n\nNope. We are not constrained by POSIX, but MacOS still runs the\nancient bash 3.x while associative arrays are in 4.x\n-- \nDuy\n"},{"id":"342843","messageId":"20180324203525.24159-1-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180321193039.19779-1-pclouds@gmail.com","subject":"[PATCH v2 0/8] completion: add option completion for most builtin commands","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:17Z","receivedAt":"2018-03-24T20:38:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This series adds option completion for many more commands. More\nimportantly it introduces a generic completion function\n__git_complete_common(). With --git-completion-helper providing more\nand more information in future, this function can start to replace\nmany other _git_xxx() in this file.\n\nNguyễn Thái Ngọc Duy (8):\n  git.c: move cmd_struct declaration up\n  git.c: add hidden option --list-parseopt-builtins\n  completion: mention the oldest version we need to support\n  completion: factor out _git_xxx calling code\n  completion: add --option completion for most builtin commands\n  completion: delete option-only completion commands\n  completion: use __gitcomp_builtin in _git_ls_tree\n  completion: use __gitcomp_builtin in _git_cherry\n\n contrib/completion/git-completion.bash |  75 +++++++++++----\n git.c                                  | 122 +++++++++++++------------\n t/t9902-completion.sh                  |   6 ++\n 3 files changed, 127 insertions(+), 76 deletions(-)\n\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342844","messageId":"20180324203525.24159-2-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 1/8] git.c: move cmd_struct declaration up","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:18Z","receivedAt":"2018-03-24T20:38:12Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"In a later patch we need access to one of these command option\nconstants near the top of this file. Move this block up so we will be\nable to access the command options.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n git.c | 34 +++++++++++++++++-----------------\n 1 file changed, 17 insertions(+), 17 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex ceaa58ef40..bc4a5459d3 100644\n--- a/git.c\n+++ b/git.c\n@@ -4,6 +4,23 @@\n #include \"help.h\"\n #include \"run-command.h\"\n \n+#define RUN_SETUP\t\t(1<<0)\n+#define RUN_SETUP_GENTLY\t(1<<1)\n+#define USE_PAGER\t\t(1<<2)\n+/*\n+ * require working tree to be present -- anything uses this needs\n+ * RUN_SETUP for reading from the configuration file.\n+ */\n+#define NEED_WORK_TREE\t\t(1<<3)\n+#define SUPPORT_SUPER_PREFIX\t(1<<4)\n+#define DELAY_PAGER_CONFIG\t(1<<5)\n+\n+struct cmd_struct {\n+\tconst char *cmd;\n+\tint (*fn)(int, const char **, const char *);\n+\tint option;\n+};\n+\n const char git_usage_string[] =\n \tN_(\"git [--version] [--help] [-C <path>] [-c <name>=<value>]\\n\"\n \t   \"           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\\n\"\n@@ -288,23 +305,6 @@ static int handle_alias(int *argcp, const char ***argv)\n \treturn ret;\n }\n \n-#define RUN_SETUP\t\t(1<<0)\n-#define RUN_SETUP_GENTLY\t(1<<1)\n-#define USE_PAGER\t\t(1<<2)\n-/*\n- * require working tree to be present -- anything uses this needs\n- * RUN_SETUP for reading from the configuration file.\n- */\n-#define NEED_WORK_TREE\t\t(1<<3)\n-#define SUPPORT_SUPER_PREFIX\t(1<<4)\n-#define DELAY_PAGER_CONFIG\t(1<<5)\n-\n-struct cmd_struct {\n-\tconst char *cmd;\n-\tint (*fn)(int, const char **, const char *);\n-\tint option;\n-};\n-\n static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n {\n \tint status, help;\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342845","messageId":"20180324203525.24159-3-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 2/8] git.c: add hidden option --list-parseopt-builtins","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:19Z","receivedAt":"2018-03-24T20:38:16Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is another step to help automate git-completion.bash. This option\ngives a list of all builtin commands that do use parse_options(),\nwhich supports another hidden option --git-completion-helper. The\noutput is prepared for easy consumption by git-completion.bash and\nseparates items by spaces instead of \\n\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n git.c | 90 ++++++++++++++++++++++++++++++++---------------------------\n 1 file changed, 49 insertions(+), 41 deletions(-)\n\ndiff --git a/git.c b/git.c\nindex bc4a5459d3..3a89893712 100644\n--- a/git.c\n+++ b/git.c\n@@ -14,11 +14,12 @@\n #define NEED_WORK_TREE\t\t(1<<3)\n #define SUPPORT_SUPER_PREFIX\t(1<<4)\n #define DELAY_PAGER_CONFIG\t(1<<5)\n+#define NO_PARSEOPT\t\t(1<<6) /* parse-options is not used */\n \n struct cmd_struct {\n \tconst char *cmd;\n \tint (*fn)(int, const char **, const char *);\n-\tint option;\n+\tunsigned int option;\n };\n \n const char git_usage_string[] =\n@@ -35,7 +36,7 @@ const char git_more_info_string[] =\n \n static int use_pager = -1;\n \n-static void list_builtins(void);\n+static void list_builtins(unsigned int exclude_option, char sep);\n \n static void commit_pager_choice(void) {\n \tswitch (use_pager) {\n@@ -223,7 +224,10 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)\n \t\t\t(*argv)++;\n \t\t\t(*argc)--;\n \t\t} else if (!strcmp(cmd, \"--list-builtins\")) {\n-\t\t\tlist_builtins();\n+\t\t\tlist_builtins(0, '\\n');\n+\t\t\texit(0);\n+\t\t} else if (!strcmp(cmd, \"--list-parseopt-builtins\")) {\n+\t\t\tlist_builtins(NO_PARSEOPT, ' ');\n \t\t\texit(0);\n \t\t} else {\n \t\t\tfprintf(stderr, _(\"unknown option: %s\\n\"), cmd);\n@@ -367,18 +371,18 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)\n static struct cmd_struct commands[] = {\n \t{ \"add\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"am\", cmd_am, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"annotate\", cmd_annotate, RUN_SETUP },\n+\t{ \"annotate\", cmd_annotate, RUN_SETUP | NO_PARSEOPT },\n \t{ \"apply\", cmd_apply, RUN_SETUP_GENTLY },\n \t{ \"archive\", cmd_archive, RUN_SETUP_GENTLY },\n \t{ \"bisect--helper\", cmd_bisect__helper, RUN_SETUP },\n \t{ \"blame\", cmd_blame, RUN_SETUP },\n \t{ \"branch\", cmd_branch, RUN_SETUP | DELAY_PAGER_CONFIG },\n-\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY },\n+\t{ \"bundle\", cmd_bundle, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"cat-file\", cmd_cat_file, RUN_SETUP },\n \t{ \"check-attr\", cmd_check_attr, RUN_SETUP },\n \t{ \"check-ignore\", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"check-mailmap\", cmd_check_mailmap, RUN_SETUP },\n-\t{ \"check-ref-format\", cmd_check_ref_format },\n+\t{ \"check-ref-format\", cmd_check_ref_format, NO_PARSEOPT  },\n \t{ \"checkout\", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"checkout-index\", cmd_checkout_index,\n \t\tRUN_SETUP | NEED_WORK_TREE},\n@@ -388,30 +392,30 @@ static struct cmd_struct commands[] = {\n \t{ \"clone\", cmd_clone },\n \t{ \"column\", cmd_column, RUN_SETUP_GENTLY },\n \t{ \"commit\", cmd_commit, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP },\n+\t{ \"commit-tree\", cmd_commit_tree, RUN_SETUP | NO_PARSEOPT },\n \t{ \"config\", cmd_config, RUN_SETUP_GENTLY | DELAY_PAGER_CONFIG },\n \t{ \"count-objects\", cmd_count_objects, RUN_SETUP },\n-\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY },\n+\t{ \"credential\", cmd_credential, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"describe\", cmd_describe, RUN_SETUP },\n-\t{ \"diff\", cmd_diff },\n-\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"diff-index\", cmd_diff_index, RUN_SETUP },\n-\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP },\n+\t{ \"diff\", cmd_diff, NO_PARSEOPT },\n+\t{ \"diff-files\", cmd_diff_files, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },\n+\t{ \"diff-index\", cmd_diff_index, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"diff-tree\", cmd_diff_tree, RUN_SETUP | NO_PARSEOPT },\n \t{ \"difftool\", cmd_difftool, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"fast-export\", cmd_fast_export, RUN_SETUP },\n \t{ \"fetch\", cmd_fetch, RUN_SETUP },\n-\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP },\n+\t{ \"fetch-pack\", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },\n \t{ \"fmt-merge-msg\", cmd_fmt_merge_msg, RUN_SETUP },\n \t{ \"for-each-ref\", cmd_for_each_ref, RUN_SETUP },\n \t{ \"format-patch\", cmd_format_patch, RUN_SETUP },\n \t{ \"fsck\", cmd_fsck, RUN_SETUP },\n \t{ \"fsck-objects\", cmd_fsck, RUN_SETUP },\n \t{ \"gc\", cmd_gc, RUN_SETUP },\n-\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id },\n+\t{ \"get-tar-commit-id\", cmd_get_tar_commit_id, NO_PARSEOPT },\n \t{ \"grep\", cmd_grep, RUN_SETUP_GENTLY },\n \t{ \"hash-object\", cmd_hash_object },\n \t{ \"help\", cmd_help },\n-\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY },\n+\t{ \"index-pack\", cmd_index_pack, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"init\", cmd_init_db },\n \t{ \"init-db\", cmd_init_db },\n \t{ \"interpret-trailers\", cmd_interpret_trailers, RUN_SETUP_GENTLY },\n@@ -419,27 +423,27 @@ static struct cmd_struct commands[] = {\n \t{ \"ls-files\", cmd_ls_files, RUN_SETUP },\n \t{ \"ls-remote\", cmd_ls_remote, RUN_SETUP_GENTLY },\n \t{ \"ls-tree\", cmd_ls_tree, RUN_SETUP },\n-\t{ \"mailinfo\", cmd_mailinfo, RUN_SETUP_GENTLY },\n-\t{ \"mailsplit\", cmd_mailsplit },\n+\t{ \"mailinfo\", cmd_mailinfo, RUN_SETUP_GENTLY | NO_PARSEOPT },\n+\t{ \"mailsplit\", cmd_mailsplit, NO_PARSEOPT },\n \t{ \"merge\", cmd_merge, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"merge-base\", cmd_merge_base, RUN_SETUP },\n \t{ \"merge-file\", cmd_merge_file, RUN_SETUP_GENTLY },\n-\t{ \"merge-index\", cmd_merge_index, RUN_SETUP },\n-\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP },\n-\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },\n-\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP },\n-\t{ \"mktag\", cmd_mktag, RUN_SETUP },\n+\t{ \"merge-index\", cmd_merge_index, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"merge-ours\", cmd_merge_ours, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"merge-recursive\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },\n+\t{ \"merge-recursive-ours\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },\n+\t{ \"merge-recursive-theirs\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },\n+\t{ \"merge-subtree\", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE | NO_PARSEOPT },\n+\t{ \"merge-tree\", cmd_merge_tree, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"mktag\", cmd_mktag, RUN_SETUP | NO_PARSEOPT },\n \t{ \"mktree\", cmd_mktree, RUN_SETUP },\n \t{ \"mv\", cmd_mv, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"name-rev\", cmd_name_rev, RUN_SETUP },\n \t{ \"notes\", cmd_notes, RUN_SETUP },\n \t{ \"pack-objects\", cmd_pack_objects, RUN_SETUP },\n-\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP },\n+\t{ \"pack-redundant\", cmd_pack_redundant, RUN_SETUP | NO_PARSEOPT },\n \t{ \"pack-refs\", cmd_pack_refs, RUN_SETUP },\n-\t{ \"patch-id\", cmd_patch_id, RUN_SETUP_GENTLY },\n+\t{ \"patch-id\", cmd_patch_id, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"pickaxe\", cmd_blame, RUN_SETUP },\n \t{ \"prune\", cmd_prune, RUN_SETUP },\n \t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n@@ -450,14 +454,14 @@ static struct cmd_struct commands[] = {\n \t{ \"receive-pack\", cmd_receive_pack },\n \t{ \"reflog\", cmd_reflog, RUN_SETUP },\n \t{ \"remote\", cmd_remote, RUN_SETUP },\n-\t{ \"remote-ext\", cmd_remote_ext },\n-\t{ \"remote-fd\", cmd_remote_fd },\n+\t{ \"remote-ext\", cmd_remote_ext, NO_PARSEOPT },\n+\t{ \"remote-fd\", cmd_remote_fd, NO_PARSEOPT },\n \t{ \"repack\", cmd_repack, RUN_SETUP },\n \t{ \"replace\", cmd_replace, RUN_SETUP },\n \t{ \"rerere\", cmd_rerere, RUN_SETUP },\n \t{ \"reset\", cmd_reset, RUN_SETUP },\n-\t{ \"rev-list\", cmd_rev_list, RUN_SETUP },\n-\t{ \"rev-parse\", cmd_rev_parse },\n+\t{ \"rev-list\", cmd_rev_list, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"rev-parse\", cmd_rev_parse, NO_PARSEOPT },\n \t{ \"revert\", cmd_revert, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"rm\", cmd_rm, RUN_SETUP },\n \t{ \"send-pack\", cmd_send_pack, RUN_SETUP },\n@@ -468,23 +472,23 @@ static struct cmd_struct commands[] = {\n \t{ \"stage\", cmd_add, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"status\", cmd_status, RUN_SETUP | NEED_WORK_TREE },\n \t{ \"stripspace\", cmd_stripspace },\n-\t{ \"submodule--helper\", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX},\n+\t{ \"submodule--helper\", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX | NO_PARSEOPT },\n \t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n \t{ \"tag\", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },\n-\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP },\n-\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n+\t{ \"unpack-file\", cmd_unpack_file, RUN_SETUP | NO_PARSEOPT },\n+\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP | NO_PARSEOPT },\n \t{ \"update-index\", cmd_update_index, RUN_SETUP },\n \t{ \"update-ref\", cmd_update_ref, RUN_SETUP },\n \t{ \"update-server-info\", cmd_update_server_info, RUN_SETUP },\n-\t{ \"upload-archive\", cmd_upload_archive },\n-\t{ \"upload-archive--writer\", cmd_upload_archive_writer },\n-\t{ \"var\", cmd_var, RUN_SETUP_GENTLY },\n+\t{ \"upload-archive\", cmd_upload_archive, NO_PARSEOPT },\n+\t{ \"upload-archive--writer\", cmd_upload_archive_writer, NO_PARSEOPT },\n+\t{ \"var\", cmd_var, RUN_SETUP_GENTLY | NO_PARSEOPT },\n \t{ \"verify-commit\", cmd_verify_commit, RUN_SETUP },\n \t{ \"verify-pack\", cmd_verify_pack },\n \t{ \"verify-tag\", cmd_verify_tag, RUN_SETUP },\n \t{ \"version\", cmd_version },\n \t{ \"whatchanged\", cmd_whatchanged, RUN_SETUP },\n-\t{ \"worktree\", cmd_worktree, RUN_SETUP },\n+\t{ \"worktree\", cmd_worktree, RUN_SETUP | NO_PARSEOPT },\n \t{ \"write-tree\", cmd_write_tree, RUN_SETUP },\n };\n \n@@ -504,11 +508,15 @@ int is_builtin(const char *s)\n \treturn !!get_builtin(s);\n }\n \n-static void list_builtins(void)\n+static void list_builtins(unsigned int exclude_option, char sep)\n {\n \tint i;\n-\tfor (i = 0; i < ARRAY_SIZE(commands); i++)\n-\t\tprintf(\"%s\\n\", commands[i].cmd);\n+\tfor (i = 0; i < ARRAY_SIZE(commands); i++) {\n+\t\tif (exclude_option &&\n+\t\t    (commands[i].option & exclude_option))\n+\t\t\tcontinue;\n+\t\tprintf(\"%s%c\", commands[i].cmd, sep);\n+\t}\n }\n \n #ifdef STRIP_EXTENSION\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342846","messageId":"20180324203525.24159-9-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 8/8] completion: use __gitcomp_builtin in _git_cherry","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:25Z","receivedAt":"2018-03-24T20:38:19Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 6 ++++++\n 1 file changed, 6 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2f16264413..0fe91d016f 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1282,6 +1282,12 @@ _git_checkout ()\n \n _git_cherry ()\n {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin cherry\n+\t\treturn\n+\tesac\n+\n \t__git_complete_refs\n }\n \n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342847","messageId":"20180324203525.24159-5-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 4/8] completion: factor out _git_xxx calling code","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:21Z","receivedAt":"2018-03-24T20:38:21Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 17 +++++++++++++----\n 1 file changed, 13 insertions(+), 4 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 9bef457792..b3a9ecfad0 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -3034,6 +3034,17 @@ _git_worktree ()\n \tfi\n }\n \n+__git_complete_command () {\n+\tlocal command=\"$1\"\n+\tlocal completion_func=\"_git_${command//-/_}\"\n+\tif declare -f $completion_func >/dev/null 2>/dev/null; then\n+\t\t$completion_func\n+\t\treturn 0\n+\telse\n+\t\treturn 1\n+\tfi\n+}\n+\n __git_main ()\n {\n \tlocal i c=1 command __git_dir __git_repo_path\n@@ -3093,14 +3104,12 @@ __git_main ()\n \t\treturn\n \tfi\n \n-\tlocal completion_func=\"_git_${command//-/_}\"\n-\tdeclare -f $completion_func >/dev/null 2>/dev/null && $completion_func && return\n+\t__git_complete_command \"$command\" && return\n \n \tlocal expansion=$(__git_aliased_command \"$command\")\n \tif [ -n \"$expansion\" ]; then\n \t\twords[1]=$expansion\n-\t\tcompletion_func=\"_git_${expansion//-/_}\"\n-\t\tdeclare -f $completion_func >/dev/null 2>/dev/null && $completion_func\n+\t\t__git_complete_command \"$expansion\"\n \tfi\n }\n \n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342848","messageId":"20180324203525.24159-8-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 7/8] completion: use __gitcomp_builtin in _git_ls_tree","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:24Z","receivedAt":"2018-03-24T20:38:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 7 +++++++\n 1 file changed, 7 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 0ee0ad7ac3..2f16264413 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1625,6 +1625,13 @@ _git_ls_remote ()\n \n _git_ls_tree ()\n {\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin ls-tree\n+\t\treturn\n+\t\t;;\n+\tesac\n+\n \t__git_complete_file\n }\n \n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342849","messageId":"20180324203525.24159-4-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 3/8] completion: mention the oldest version we need to support","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:20Z","receivedAt":"2018-03-24T20:38:25Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is more of a note for git-completion.bash contributors, not\nusers. The bash version is from MacOS [1]. Most Linux distros should\nbe 4.x at this point.\n\n[1] https://public-inbox.org/git/%3CCAPig+cQXT1ov4MjzSzqiLBzr4wN1XcP7aSxMP+_dhtWtYwhDAA@mail.gmail.com%3E/\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 2 ++\n 1 file changed, 2 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex c7957f0a90..9bef457792 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -29,6 +29,8 @@\n # tell the completion to use commit completion.  This also works with aliases\n # of form \"!sh -c '...'\".  For example, \"!sh -c ': git commit ; ... '\".\n #\n+# Compatible with bash 3.2.57.\n+#\n # You can set the following environment variables to influence the behavior of\n # the completion routines:\n #\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342850","messageId":"20180324203525.24159-7-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 6/8] completion: delete option-only completion commands","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:23Z","receivedAt":"2018-03-24T20:38:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The new function __git_complete_common can take over this job with\nless code to maintain.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 15 ---------------\n 1 file changed, 15 deletions(-)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex a90b0e8db4..0ee0ad7ac3 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -1501,16 +1501,6 @@ _git_fsck ()\n \tesac\n }\n \n-_git_gc ()\n-{\n-\tcase \"$cur\" in\n-\t--*)\n-\t\t__gitcomp_builtin gc\n-\t\treturn\n-\t\t;;\n-\tesac\n-}\n-\n _git_gitk ()\n {\n \t_gitk\n@@ -1810,11 +1800,6 @@ _git_mv ()\n \tfi\n }\n \n-_git_name_rev ()\n-{\n-\t__gitcomp_builtin name-rev\n-}\n-\n _git_notes ()\n {\n \tlocal subcommands='add append copy edit get-ref list merge prune remove show'\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342851","messageId":"20180324203525.24159-6-pclouds@gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-1-pclouds@gmail.com","subject":"[PATCH v2 5/8] completion: add --option completion for most builtin commands","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-24T20:35:22Z","receivedAt":"2018-03-24T20:38:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Many builtin commands use parseopt which supports expose the option\nlist via --git-completion-helper but do not have explicit support in\ngit-completion.bash. This patch detects those commands and uses\n__gitcomp_builtin for option completion.\n\nThis does not pollute the command name completion though. \"git <tab>\"\nwill show you the same set as before. This only kicks in when you type\nthe correct command name.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n contrib/completion/git-completion.bash | 28 ++++++++++++++++++++++++++\n t/t9902-completion.sh                  |  6 ++++++\n 2 files changed, 34 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex b3a9ecfad0..a90b0e8db4 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -3034,12 +3034,40 @@ _git_worktree ()\n \tfi\n }\n \n+__git_complete_common () {\n+\tlocal command=\"$1\"\n+\n+\tcase \"$cur\" in\n+\t--*)\n+\t\t__gitcomp_builtin \"$command\"\n+\t\t;;\n+\tesac\n+}\n+\n+__git_cmds_with_parseopt_helper=\n+__git_support_parseopt_helper () {\n+\ttest -n \"$__git_cmds_with_parseopt_helper\" ||\n+\t\t__git_cmds_with_parseopt_helper=\"$(__git --list-parseopt-builtins)\"\n+\n+\tcase \" $__git_cmds_with_parseopt_helper \" in\n+\t*\" $1 \"*)\n+\t\treturn 0\n+\t\t;;\n+\t*)\n+\t\treturn 1\n+\t\t;;\n+\tesac\n+}\n+\n __git_complete_command () {\n \tlocal command=\"$1\"\n \tlocal completion_func=\"_git_${command//-/_}\"\n \tif declare -f $completion_func >/dev/null 2>/dev/null; then\n \t\t$completion_func\n \t\treturn 0\n+\telif __git_support_parseopt_helper \"$command\"; then\n+\t\t__git_complete_common \"$command\"\n+\t\treturn 0\n \telse\n \t\treturn 1\n \tfi\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex e6485feb0a..d0a1e4c988 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -1454,6 +1454,12 @@ test_expect_success 'completion used <cmd> completion for alias: !f() { : git <c\n \tEOF\n '\n \n+test_expect_success 'completion without explicit _git_xxx function' '\n+\ttest_completion \"git version --\" <<-\\EOF\n+\t--build-options Z\n+\tEOF\n+'\n+\n test_expect_failure 'complete with tilde expansion' '\n \tgit init tmp && cd tmp &&\n \ttest_when_finished \"cd .. && rm -rf tmp\" &&\n-- \n2.17.0.rc0.348.gd5a49e0b6f\n\n"},{"id":"342857","messageId":"CAPig+cThH3mNTn2nR9XEsmAVaQ0-NfA7r5JwyjBd9wZiRzedhw@mail.gmail.com","threadId":"48111","inReplyTo":"20180324203525.24159-6-pclouds@gmail.com","subject":"Re: [PATCH v2 5/8] completion: add --option completion for most builtin commands","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-25T00:59:30Z","receivedAt":"2018-03-25T00:59:36Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Mar 24, 2018 at 4:35 PM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:\n> Many builtin commands use parseopt which supports expose the option\n\ns/expose/exposing/ maybe?\n\n> list via --git-completion-helper but do not have explicit support in\n> git-completion.bash. This patch detects those commands and uses\n> __gitcomp_builtin for option completion.\n>\n> This does not pollute the command name completion though. \"git <tab>\"\n> will show you the same set as before. This only kicks in when you type\n> the correct command name.\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n"}]}