{"id":7978,"date":"2015-11-14T08:47:41","date_gmt":"2015-11-14T08:47:41","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2015\/11\/14\/how-does-argparse-and-the-deprecated-optparse-respond-to-tab-keypress-after-python-program-name-in-bash-open-source-projects-scottjehl-respond\/"},"modified":"2015-11-14T08:47:41","modified_gmt":"2015-11-14T08:47:41","slug":"how-does-argparse-and-the-deprecated-optparse-respond-to-tab-keypress-after-python-program-name-in-bash-open-source-projects-scottjehl-respond","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2015\/11\/14\/how-does-argparse-and-the-deprecated-optparse-respond-to-tab-keypress-after-python-program-name-in-bash-open-source-projects-scottjehl-respond\/","title":{"rendered":"How does argparse (and the deprecated optparse) respond to &#39;tab&#39; keypress after python program name, in bash?-open source projects scottjehl\/Respond"},"content":{"rendered":"<p>To understand what&#8217;s happening here, let&#8217;s check what that bash function actually does:<\/p>\n<pre><code>COMPREPLY=( $( \\\n    COMP_LINE=$COMP_LINE  COMP_POINT=$COMP_POINT \\\n    COMP_WORDS=\"${COMP_WORDS[*]}\"  COMP_CWORD=$COMP_CWORD \\\n    OPTPARSE_AUTO_COMPLETE=1 $1 ) )\n<\/code><\/pre>\n<p>See the <code>$1<\/code> at the end? That means that it actually calls the Python file we want to execute with special environment variables set! To trace what&#8217;s happening, let&#8217;s prepare a little script to intercept what <code>optcomplete.autocomplete<\/code> does:<\/p>\n<pre><code>#!\/usr\/bin\/env python2\nimport os, sys\nimport optparse, optcomplete\nfrom cStringIO import StringIO\n\nif __name__ == '__main__':    \n    parser = optparse.OptionParser()\n\n    parser.add_option('-s', '--simple', action='store_true',\n                      help=\"Simple really simple option without argument.\")\n\n    parser.add_option('-o', '--output', action='store',\n                      help=\"Option that requires an argument.\")\n\n    opt = parser.add_option('-p', '--script', action='store',\n                            help=\"Option that takes python scripts args only.\")\n    opt.completer = optcomplete.RegexCompleter('.*\\.py')\n\n    # debug env variables\n    sys.stderr.write(\"\\ncalled with args: %s\\n\" % repr(sys.argv))\n    for k, v in sorted(os.environ.iteritems()):\n        sys.stderr.write(\"  %s: %s\\n\" % (k, v))\n\n    # setup capturing the actions of `optcomplete.autocomplete`\n    def fake_exit(i):\n      sys.stderr.write(\"autocomplete tried to exit with status %d\\n\" % i)\n    sys.stdout = StringIO()\n    sys.exit = fake_exit\n\n    # Support completion for the command-line of this script.\n    optcomplete.autocomplete(parser, ['.*\\.tar.*'])\n\n    sys.stderr.write(\"autocomplete tried to write to STDOUT:\\n\")\n    sys.stderr.write(sys.stdout.getvalue())\n    sys.stderr.write(\"\\n\")\n\n    opts, args = parser.parse_args()\n<\/code><\/pre>\n<p>This gives us the following when we try to autocomplete it:<\/p>\n<pre><code>$ .\/test.py [tab]\ncalled with args: ['.\/test.py']\n  ...\n  COMP_CWORD: 1\n  COMP_LINE: .\/test.py \n  COMP_POINT: 10\n  COMP_WORDS: .\/test.py \n  ...\n  OPTPARSE_AUTO_COMPLETE: 1\n  ...\nautocomplete tried to exit with status 1\nautocomplete tried to write to STDOUT:\n-o -h -s -p --script --simple --help --output\n<\/code><\/pre>\n<p>So <code>optcomplete.autocomplete<\/code> just reads the environment, prepares the matches, writes them to STDOUT and exits. The result <code>-o -h -s -p --script --simple --help --output<\/code> is then put into a bash array (<code>COMPREPLY=( ... )<\/code>) and returned to bash to present the choices to the user. No magic involved \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To understand what&#8217;s happening here, let&#8217;s check what that bash function actually does: COMPREPLY=( $( \\ COMP_LINE=$COMP_LINE COMP_POINT=$COMP_POINT \\ COMP_WORDS=&#8221;${COMP_WORDS[*]}&#8221; COMP_CWORD=$COMP_CWORD \\ OPTPARSE_AUTO_COMPLETE=1 $1 ) ) See the $1 at the end? That means that it actually calls the Python file we want to execute with special environment variables set! To trace what&#8217;s happening, let&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7978","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7978","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=7978"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/7978\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=7978"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=7978"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=7978"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}