{"thread":{"id":"36869","subject":"[PATCH] completion: Handle '!f() { ... }; f' aliases","startedAt":"2014-06-07T14:10:21Z","lastAt":"2014-06-12T18:49:29Z","messageCount":6,"participants":["Steffen Prohaska","Eric Sunshine","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"243596","messageId":"1402150221-25548-1-git-send-email-prohaska@zib.de","threadId":"36869","inReplyTo":null,"subject":"[PATCH] completion: Handle '!f() { ... }; f' aliases","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2014-06-07T14:10:21Z","receivedAt":"2014-06-07T14:10:21Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"'!f() { ... }; f' is a recommended pattern to declare more complex\naliases (see git wiki [1]).  This commit teaches the completion to\nhandle them.\n\nWhen determining which completion to use for an alias, the opening brace\nis now ignored in order to continue the search for a git command inside\nthe function body.  For example, the alias '!f() { git commit ... }' now\ntriggers commit completion.  Previously, the search stopped on '{', and\nthe completion tried it to determine how to complete, which obviously\nwas useless.\n\nFurthermore, the null command ':' is now skipped, so that it can be used\nas a workaround to declare the desired completion style.  For example,\nthe alias '!f() { : git commit ; if ...  ' now triggers commit\ncompletion.\n\n[1] https://git.wiki.kernel.org/index.php/Aliases\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n contrib/completion/git-completion.bash |  7 +++++++\n t/t9902-completion.sh                  | 20 ++++++++++++++++++++\n 2 files changed, 27 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2c59a76..aecb975 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -21,6 +21,11 @@\n #        source ~/.git-completion.sh\n #    3) Consider changing your PS1 to also show the current branch,\n #       see git-prompt.sh for details.\n+#\n+# If you use complex aliases of form '!f() { ... }; f', you can use the null\n+# command ':' as the first command in the function body to declare the desired\n+# completion style.  For example '!f() { : git commit ; ... }; f' will\n+# tell the completion to use commit completion.\n \n case \"$COMP_WORDBREAKS\" in\n *:*) : great ;;\n@@ -781,6 +786,8 @@ __git_aliased_command ()\n \t\t-*)\t: option ;;\n \t\t*=*)\t: setting env ;;\n \t\tgit)\t: git itself ;;\n+\t\t{)\t: skip start of shell helper function ;;\n+\t\t:)\t: skip null command ;;\n \t\t*)\n \t\t\techo \"$word\"\n \t\t\treturn\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 2d4beb5..ea48681 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -550,6 +550,26 @@ test_expect_success 'complete files' '\n \ttest_completion \"git add mom\" \"momified\"\n '\n \n+test_expect_success 'completion uses <cmd> completion for alias !f() { VAR=val git <cmd> ... }' '\n+\tgit config alias.co \"!f() { VAR=val git checkout ... ; } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF &&\n+\tmaster Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+\tgit config --unset alias.co\n+'\n+\n+test_expect_success 'completion used <cmd> completion for alias !f() { : git <cmd> ; ... }' '\n+\tgit config alias.co \"!f() { : git checkout ; if ... } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF &&\n+\tmaster Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+\tgit config --unset alias.co\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.0.0.244.g4e8e734\n"},{"id":"243599","messageId":"CAPig+cQKtVoc7X2SBE8L1pSpnwQxkmFF6pL2PL-7RUoFq5h8gw@mail.gmail.com","threadId":"36869","inReplyTo":"1402150221-25548-1-git-send-email-prohaska@zib.de","subject":"Re: [PATCH] completion: Handle '!f() { ... }; f' aliases","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2014-06-08T09:02:43Z","receivedAt":"2014-06-08T09:02:43Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sat, Jun 7, 2014 at 10:10 AM, Steffen Prohaska <prohaska@zib.de> wrote:\n> '!f() { ... }; f' is a recommended pattern to declare more complex\n> aliases (see git wiki [1]).  This commit teaches the completion to\n> handle them.\n>\n> When determining which completion to use for an alias, the opening brace\n> is now ignored in order to continue the search for a git command inside\n> the function body.  For example, the alias '!f() { git commit ... }' now\n> triggers commit completion.  Previously, the search stopped on '{', and\n> the completion tried it to determine how to complete, which obviously\n> was useless.\n>\n> Furthermore, the null command ':' is now skipped, so that it can be used\n> as a workaround to declare the desired completion style.  For example,\n> the alias '!f() { : git commit ; if ...  ' now triggers commit\n> completion.\n>\n> [1] https://git.wiki.kernel.org/index.php/Aliases\n>\n> Signed-off-by: Steffen Prohaska <prohaska@zib.de>\n> ---\n> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\n> index 2d4beb5..ea48681 100755\n> --- a/t/t9902-completion.sh\n> +++ b/t/t9902-completion.sh\n> @@ -550,6 +550,26 @@ test_expect_success 'complete files' '\n>         test_completion \"git add mom\" \"momified\"\n>  '\n>\n> +test_expect_success 'completion uses <cmd> completion for alias !f() { VAR=val git <cmd> ... }' '\n> +       git config alias.co \"!f() { VAR=val git checkout ... ; } f\" &&\n\ntest_config would be an appropriate replacement for \"git config\" +\n\"git config --unset\".\n\n> +       test_completion \"git co m\" <<-\\EOF &&\n> +       master Z\n> +       mybranch Z\n> +       mytag Z\n> +       EOF\n> +       git config --unset alias.co\n> +'\n> +\n> +test_expect_success 'completion used <cmd> completion for alias !f() { : git <cmd> ; ... }' '\n> +       git config alias.co \"!f() { : git checkout ; if ... } f\" &&\n\nDitto.\n\n> +       test_completion \"git co m\" <<-\\EOF &&\n> +       master Z\n> +       mybranch Z\n> +       mytag Z\n> +       EOF\n> +       git config --unset alias.co\n> +'\n> +\n>  test_expect_failure 'complete with tilde expansion' '\n>         git init tmp && cd tmp &&\n>         test_when_finished \"cd .. && rm -rf tmp\" &&\n> --\n> 2.0.0.244.g4e8e734\n"},{"id":"243621","messageId":"1402318493-29943-1-git-send-email-prohaska@zib.de","threadId":"36869","inReplyTo":"CAPig+cQKtVoc7X2SBE8L1pSpnwQxkmFF6pL2PL-7RUoFq5h8gw@mail.gmail.com","subject":"[PATCH v2] completion: Handle '!f() { ... }; f' aliases","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2014-06-09T12:54:53Z","receivedAt":"2014-06-09T12:54:53Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"'!f() { ... }; f' is a recommended pattern to declare more complex\naliases (see git wiki [1]).  This commit teaches the completion to\nhandle them.\n\nWhen determining which completion to use for an alias, the opening brace\nis now ignored in order to continue the search for a git command inside\nthe function body.  For example, the alias '!f() { git commit ... }' now\ntriggers commit completion.  Previously, the search stopped on '{', and\nthe completion tried it to determine how to complete, which obviously\nwas useless.\n\nFurthermore, the null command ':' is now skipped, so that it can be used\nas a workaround to declare the desired completion style.  For example,\nthe alias '!f() { : git commit ; if ...  ' now triggers commit\ncompletion.\n\n[1] https://git.wiki.kernel.org/index.php/Aliases\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n\nI changed the tests to use test_config, as Eric suggested.  Thanks.\n\n contrib/completion/git-completion.bash |  7 +++++++\n t/t9902-completion.sh                  | 18 ++++++++++++++++++\n 2 files changed, 25 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2c59a76..aecb975 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -21,6 +21,11 @@\n #        source ~/.git-completion.sh\n #    3) Consider changing your PS1 to also show the current branch,\n #       see git-prompt.sh for details.\n+#\n+# If you use complex aliases of form '!f() { ... }; f', you can use the null\n+# command ':' as the first command in the function body to declare the desired\n+# completion style.  For example '!f() { : git commit ; ... }; f' will\n+# tell the completion to use commit completion.\n \n case \"$COMP_WORDBREAKS\" in\n *:*) : great ;;\n@@ -781,6 +786,8 @@ __git_aliased_command ()\n \t\t-*)\t: option ;;\n \t\t*=*)\t: setting env ;;\n \t\tgit)\t: git itself ;;\n+\t\t{)\t: skip start of shell helper function ;;\n+\t\t:)\t: skip null command ;;\n \t\t*)\n \t\t\techo \"$word\"\n \t\t\treturn\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 2d4beb5..10ceb29 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -550,6 +550,24 @@ test_expect_success 'complete files' '\n \ttest_completion \"git add mom\" \"momified\"\n '\n \n+test_expect_success 'completion uses <cmd> completion for alias !f() { VAR=val git <cmd> ... }' '\n+\ttest_config alias.co \"!f() { VAR=val git checkout ... ; } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmaster Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success 'completion used <cmd> completion for alias !f() { : git <cmd> ; ... }' '\n+\ttest_config alias.co \"!f() { : git checkout ; if ... } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmaster Z\n+\tmybranch Z\n+\tmytag 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.0.0.244.g4e8e734\n"},{"id":"243702","messageId":"xmqq1tuxcp13.fsf@gitster.dls.corp.google.com","threadId":"36869","inReplyTo":"1402318493-29943-1-git-send-email-prohaska@zib.de","subject":"Re: [PATCH v2] completion: Handle '!f() { ... }; f' aliases","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2014-06-10T05:27:36Z","receivedAt":"2014-06-10T05:27:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Steffen Prohaska <prohaska@zib.de> writes:\n\n> '!f() { ... }; f' is a recommended pattern to declare more complex\n> aliases (see git wiki [1]).  This commit teaches the completion to\n> handle them.\n\nHmm, I've never endorsed nor recommended such a notation myself ;-)\nI tend to prefer writing it like so instead:\n\n    sh -c '...' -\n\nso that I won't clobber \"f\" (or any other name).  I wonder if you\ncan help users of this other pattern as well.\n\n> When determining which completion to use for an alias, the opening brace\n> is now ignored in order to continue the search for a git command inside\n> the function body.  For example, the alias '!f() { git commit ... }' now\n> triggers commit completion.\n\nI suspect that \"scanning\" is error-prone.  I like this one for its\ncuteness very much, though:\n\n> Furthermore, the null command ':' is now skipped, so that it can be used\n> as a workaround to declare the desired completion style.  For example,\n> the alias '!f() { : git commit ; if ...  ' now triggers commit\n> completion.\n\n\n\n> +test_expect_success 'completion uses <cmd> completion for alias !f() { VAR=val git <cmd> ... }' '\n> +\ttest_config alias.co \"!f() { VAR=val git checkout ... ; } f\" &&\n\nIs it only \"f\" that is completed, or can I spell it using another\narbitrary token, e.g.\n\n\ttest_config alias.co \"!co () { git checkout ... } co\"\n"},{"id":"244013","messageId":"62610ABB-4ED5-4CF1-B5B2-B89C9DD22FBD@zib.de","threadId":"36869","inReplyTo":"xmqq1tuxcp13.fsf@gitster.dls.corp.google.com","subject":"Re: [PATCH v2] completion: Handle '!f() { ... }; f' aliases","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2014-06-12T18:41:54Z","receivedAt":"2014-06-12T18:41:54Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"\nOn Jun 10, 2014, at 7:27 AM, Junio C Hamano <gitster@pobox.com> wrote:\n\n> Steffen Prohaska <prohaska@zib.de> writes:\n> \n> I tend to prefer writing it like so instead:\n> \n>    sh -c '...' -\n> \n> so that I won't clobber \"f\" (or any other name).  I wonder if you\n> can help users of this other pattern as well.\n\nI'll send an updated patch that handles it.\n\n\n>> +test_expect_success 'completion uses <cmd> completion for alias !f() { VAR=val git <cmd> ... }' '\n>> +\ttest_config alias.co \"!f() { VAR=val git checkout ... ; } f\" &&\n> \n> Is it only \"f\" that is completed, or can I spell it using another\n> arbitrary token, e.g.\n> \n> \ttest_config alias.co \"!co () { git checkout ... } co\"\n\nAny token that starts with ! already worked before. \n\nThe updated patch will also handle spaces before the parens.\n\n\tSteffen"},{"id":"244015","messageId":"1402598969-31401-1-git-send-email-prohaska@zib.de","threadId":"36869","inReplyTo":"62610ABB-4ED5-4CF1-B5B2-B89C9DD22FBD@zib.de","subject":"[PATCH v2] completion: Handle '!f() { ... }; f' and \"!sh -c '...'\" aliases","fromName":"Steffen Prohaska","fromEmail":"prohaska@zib.de","sentAt":"2014-06-12T18:49:29Z","receivedAt":"2014-06-12T18:49:29Z","isPatch":true,"sender":{"key":"prohaska@zib.de","avatar":"https://avatars.githubusercontent.com/u/217580?v=4"},"body":"'!f() { ... }; f' and \"!sh -c '....'\" are recommended patterns for\ndeclaring more complex aliases (see git wiki [1]).  This commit teaches\nthe completion to handle them.\n\nWhen determining which completion to use for an alias, an opening brace\nor single quote is now skipped, and the search for a git command is\ncontinued.  For example, the aliases '!f() { git commit ... }' or \"!sh\n-c 'git commit ...'\" now trigger commit completion.  Previously, the\nsearch stopped on the opening brace or quote, and the completion tried\nit to determine how to complete, which obviously was useless.\n\nThe null command ':' is now skipped, so that it can be used as\na workaround to declare the desired completion style.  For example, the\naliases '!f() { : git commit ; if ...  ' and \"!sh -c ': git commit; if\n...'\" now trigger commit completion.\n\nShell function declarations now work with or without space before\nthe parens, i.e. '!f() ...' and '!f () ...' both work.\n\n[1] https://git.wiki.kernel.org/index.php/Aliases\n\nSigned-off-by: Steffen Prohaska <prohaska@zib.de>\n---\n contrib/completion/git-completion.bash | 10 ++++++++++\n t/t9902-completion.sh                  | 27 +++++++++++++++++++++++++++\n 2 files changed, 37 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 2c59a76..575f8f7 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -21,6 +21,12 @@\n #        source ~/.git-completion.sh\n #    3) Consider changing your PS1 to also show the current branch,\n #       see git-prompt.sh for details.\n+#\n+# If you use complex aliases of form '!f() { ... }; f', you can use the null\n+# command ':' as the first command in the function body to declare the desired\n+# completion style.  For example '!f() { : git commit ; ... }; f' will\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 case \"$COMP_WORDBREAKS\" in\n *:*) : great ;;\n@@ -781,6 +787,10 @@ __git_aliased_command ()\n \t\t-*)\t: option ;;\n \t\t*=*)\t: setting env ;;\n \t\tgit)\t: git itself ;;\n+\t\t\\(\\))   : skip parens of shell function definition ;;\n+\t\t{)\t: skip start of shell helper function ;;\n+\t\t:)\t: skip null command ;;\n+\t\t\\'*)\t: skip opening quote after sh -c ;;\n \t\t*)\n \t\t\techo \"$word\"\n \t\t\treturn\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 2d4beb5..1d1c106 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -550,6 +550,33 @@ test_expect_success 'complete files' '\n \ttest_completion \"git add mom\" \"momified\"\n '\n \n+test_expect_success \"completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'\" '\n+\ttest_config alias.co \"!sh -c '\"'\"'git checkout ...'\"'\"'\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmaster Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success 'completion uses <cmd> completion for alias: !f () { VAR=val git <cmd> ... }' '\n+\ttest_config alias.co \"!f () { VAR=val git checkout ... ; } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmaster Z\n+\tmybranch Z\n+\tmytag Z\n+\tEOF\n+'\n+\n+test_expect_success 'completion used <cmd> completion for alias: !f() { : git <cmd> ; ... }' '\n+\ttest_config alias.co \"!f() { : git checkout ; if ... } f\" &&\n+\ttest_completion \"git co m\" <<-\\EOF\n+\tmaster Z\n+\tmybranch Z\n+\tmytag 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.0.0.244.g4e8e734\n"}]}