{"thread":{"id":"40795","subject":"[PATCH RFC] completion: add support for completing email aliases","startedAt":"2015-11-13T18:17:40Z","lastAt":"2015-11-13T18:17:40Z","messageCount":1,"participants":["Jacob Keller"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"273286","messageId":"1447438660-6115-1-git-send-email-jacob.e.keller@intel.com","threadId":"40795","inReplyTo":null,"subject":"[PATCH RFC] completion: add support for completing email aliases","fromName":"Jacob Keller","fromEmail":"jacob.e.keller@intel.com","sentAt":"2015-11-13T18:17:40Z","receivedAt":"2015-11-13T18:17:40Z","isPatch":true,"sender":{"key":"jacob.e.keller@intel.com","avatar":"https://avatars.githubusercontent.com/u/874719?v=4"},"body":"From: Jacob Keller <jacob.keller@gmail.com>\n\nExtract email aliases from the sendemail.aliasesfile according to the\nknown types. Implementation only extracts the alias name and does not\nattempt to complete email addresses.\n\nAdd a few tests for simple layouts of the currently supported alias\nfiletypes.\n\nSigned-off-by: Jacob Keller <jacob.keller@gmail.com>\n---\n\nLabeled this RFC because I have only been able to test the mutt format\nas this is what I use locally. I have a few (probably brittle) test\ncases for the files, but they are not \"real\" configuration files as per\nthe upstream tools, so they are essentially made to work with the simple\nextractors that I have now. I'd like some review on this to see if it's\nvaluable, but it definitely helps me type out aliases and see what is\navailable by just using TAB.\n\n contrib/completion/git-completion.bash | 69 ++++++++++++++++++++++++++\n t/t9902-completion.sh                  | 90 ++++++++++++++++++++++++++++++++++\n 2 files changed, 159 insertions(+)\n\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 482ca84b451b..9b786bb390ba 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -10,6 +10,7 @@\n #    *) local and remote tag names\n #    *) .git/remotes file names\n #    *) git 'subcommands'\n+#    *) git email aliases for git-send-email\n #    *) tree paths within 'ref:path/to/file' expressions\n #    *) file paths within current working directory and index\n #    *) common --long-options\n@@ -785,6 +786,56 @@ __git_aliased_command ()\n \tdone\n }\n \n+# Print aliases for email addresses from sendemail.aliasesfile\n+__git_email_aliases ()\n+{\n+\tlocal file=\"$(git --git-dir=\"$(__gitdir)\" config --path sendemail.aliasesfile)\"\n+\tlocal filetype=\"$(git --git-dir=\"$(__gitdir)\" config sendemail.aliasfiletype)\"\n+\n+\t# Only run awk if we find an actual file\n+\tif ! [ -f $file ]; then\n+\t\treturn\n+\tfi\n+\n+\tcase \"$filetype\" in\n+\t\t# Each file type needs to be parsed differently.\n+\t\tmutt|mailrc)\n+\t\t\t# Mutt and mailrc are simple and just put the alias in\n+\t\t\t# the 2nd field of the file.\n+\t\t\tawk '{print $2}' $file\n+\t\t\treturn\n+\t\t\t;;\n+\t\tsendmail)\n+\t\t\t# Skip new lines, lines without fields, and lines\n+\t\t\t# ending in '\\' then print the name minus the final :\n+\t\t\tawk 'NF && $1!~/^#/ && !/\\\\$/ {sub(/:$/, \"\", $1); print $1 }' $file\n+\t\t\treturn\n+\t\t\t;;\n+\t\tpine)\n+\t\t\t# According to spec, line continuations are any line\n+\t\t\t# which starts with whitespace, otherwise we can just\n+\t\t\t# use the normal separator and print the first field.\n+\t\t\tawk '/^\\S/ {print $1}' \"$file\"\n+\t\t\treturn\n+\t\t\t;;\n+\t\telm)\n+\t\t\t# Elm doesn't appear to allow newlines, and\n+\t\t\t# git-send-email only accepts one alias per line, so\n+\t\t\t# just print the first field.\n+\t\t\tawk '{print $1}' \"$file\"\n+\t\t\treturn\n+\t\t\t;;\n+\t\tgnus)\n+\t\t\t# The gnus format has the alias quoted, so we just use\n+\t\t\t# gsub to extract the alias from the quotes\n+\t\t\tawk '/define-mail-alias/ {gsub(/\"/, \"\", $2); print $2}' $file\n+\t\t\treturn\n+\t\t\t;;\n+\t\t*)\n+\t\t\treturn;;\n+\tesac\n+}\n+\n # __git_find_on_cmdline requires 1 argument\n __git_find_on_cmdline ()\n {\n@@ -1735,6 +1786,24 @@ _git_send_email ()\n \t\t\t\" \"\" \"${cur##--thread=}\"\n \t\treturn\n \t\t;;\n+\t--to=*)\n+\t\t__gitcomp \"\n+\t\t$(__git_email_aliases)\n+\t\t\" \"\" \"${cur##--to=}\"\n+\t\treturn\n+\t\t;;\n+\t--cc=*)\n+\t\t__gitcomp \"\n+\t\t$(__git_email_aliases)\n+\t\t\" \"\" \"${cur##--cc=}\"\n+\t\treturn\n+\t\t;;\n+\t--bcc=*)\n+\t\t__gitcomp \"\n+\t\t$(__git_email_aliases)\n+\t\t\" \"\" \"${cur##--bcc=}\"\n+\t\treturn\n+\t\t;;\n \t--*)\n \t\t__gitcomp \"--annotate --bcc --cc --cc-cmd --chain-reply-to\n \t\t\t--compose --confirm= --dry-run --envelope-sender\ndiff --git a/t/t9902-completion.sh b/t/t9902-completion.sh\nindex 2ba62fbc178e..0549f75e6e7c 100755\n--- a/t/t9902-completion.sh\n+++ b/t/t9902-completion.sh\n@@ -404,6 +404,96 @@ test_expect_success '__git_aliases' '\n \ttest_cmp expect actual\n '\n \n+test_expect_success '__git_email_aliases (mutt)' '\n+\tcat >aliases <<-EOF &&\n+\talias user1 Some User <user1@example.org>\n+\talias user2 random-user-foo@foo.garbage\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype mutt &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '__git_email_aliases (mailrc)' '\n+\tcat >aliases <<-EOF &&\n+\talias user1 Some User <user1@example.org>\n+\talias user2 random-user-foo@foo.garbage\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype mailrc &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '__git_email_aliases (sendmail)' '\n+\tcat >aliases <<-EOF &&\n+\tuser1: Some User <user1@example.org>\n+\tuser2: random-user-foo@foo.garbage\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype sendmail &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '__git_email_aliases (pine)' '\n+\tcat >aliases <<-EOF &&\n+\tuser1\tSome User\tuser1@example.org>\n+\tuser2\trandom-user-foo@foo.garbage\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype pine &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '__git_email_aliases (elm)' '\n+\tcat >aliases <<-EOF &&\n+\tuser1 = User; Someone = user1@example.org\n+\tuser2 = = user2@garbage.foo\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype elm &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '__git_email_aliases (gnus)' '\n+\tcat >aliases <<-EOF &&\n+\tdefine-mail-alias \"user1\" \"user1@example.org\"\n+\tdefine-mail-alias \"user2\" \"user2@arbitrary.foo\"\n+\tEOF\n+\tcat >expect <<-EOF &&\n+\tuser1\n+\tuser2\n+\tEOF\n+\ttest_config sendemail.aliasesfile aliases &&\n+\ttest_config sendemail.aliasfiletype gnus &&\n+\t__git_email_aliases >actual &&\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success 'basic' '\n \trun_completion \"git \" &&\n \t# built-in\n-- \n2.6.1.264.gbab76a9\n"}]}