diff --git a/argcomplete/bash_completion.d/_python-argcomplete b/argcomplete/bash_completion.d/_python-argcomplete index cdb60a9..ccf9b53 100644 --- a/argcomplete/bash_completion.d/_python-argcomplete +++ b/argcomplete/bash_completion.d/_python-argcomplete @@ -1,10 +1,15 @@ -#compdef -P * +#compdef -default- # Copyright 2012-2023, Andrey Kislyuk and argcomplete contributors. # Licensed under the Apache License. See https://github.com/kislyuk/argcomplete for more info. # Note: both the leading underscore in the name of this file and the first line (compdef) are required by zsh +# In zsh, this file is autoloaded and used as the default completer (_default). +# There are many other special contexts we don't want to override +# (as would be the case with `#compdef -P *`). +# https://zsh.sourceforge.io/Doc/Release/Completion-System.html + # Copy of __expand_tilde_by_ref from bash-completion # ZSH implementation added __python_argcomplete_expand_tilde_by_ref () { @@ -237,8 +242,7 @@ if [[ -z "${ZSH_VERSION-}" ]]; then complete -o default -o bashdefault -D -F _python_argcomplete_global else autoload is-at-least - # Replace only the default completer (_default). - # There are many other special contexts we don't want to override. - # https://zsh.sourceforge.io/Doc/Release/Completion-System.html - compdef _python_argcomplete_global -default- + # The comment at the top of this file causes zsh to invoke this script directly, + # so we must explicitly call the global completion function. + _python_argcomplete_global fi diff --git a/test/test.py b/test/test.py index 2498526..bae9ece 100755 --- a/test/test.py +++ b/test/test.py @@ -80,7 +80,6 @@ def bash_repl(command="bash"): def zsh_repl(command="zsh"): sh = _repl_sh(command, ["--no-rcs", "-V"], non_printable_insert="%(!..)") - sh.run_command("autoload compinit; compinit -u") # Require two tabs to print all options (some tests rely on this). sh.run_command("setopt BASH_AUTO_LIST") return sh @@ -1251,6 +1250,7 @@ def test_comp_point(self): class TestBashZshBase(TestShellBase): maxDiff = None + init_cmd = None # 'dummy' argument unused; checks multi-command registration works # by passing 'prog' as the second argument. install_cmd = 'eval "$(register-python-argcomplete dummy prog)"' @@ -1262,8 +1262,12 @@ def setUp(self): path = ":".join([os.path.join(BASE_DIR, "scripts"), TEST_DIR, "$PATH"]) sh.run_command("export PATH={0}".format(path)) sh.run_command("export PYTHONPATH={0}".format(BASE_DIR)) - output = sh.run_command(self.install_cmd) - self.assertEqual(output, "") + if self.init_cmd is not None: + output = sh.run_command(self.init_cmd) + self.assertEqual(output, "") + if self.install_cmd is not None: + output = sh.run_command(self.install_cmd) + self.assertEqual(output, "") # Register a dummy completion with an external argcomplete script # to ensure this doesn't overwrite our previous registration. output = sh.run_command('eval "$(register-python-argcomplete dummy --external-argcomplete-script dummy)"') @@ -1311,6 +1315,8 @@ def test_nounset(self): class TestZsh(TestBashZshBase, unittest.TestCase): + init_cmd = "autoload compinit; compinit -u" + skipped = [ "test_parse_special_characters", "test_parse_special_characters_dollar", @@ -1404,7 +1410,13 @@ class TestBashGlobal(TestBash, TestBashZshGlobalBase): class TestZshGlobal(TestZsh, TestBashZshGlobalBase): - pass + # In zsh, the file is not sourced directly; + # it is added to fpath and autoloaded by the completion system. + # Running `eval "$(activate-global-python-argcomplete --dest=-)"` + # as in bash does *not* work in zsh! + zsh_fpath = os.path.join(os.path.abspath(os.path.dirname(argcomplete.__file__)), "bash_completion.d") + init_cmd = f'fpath=( {zsh_fpath} "${{fpath[@]}}" ); autoload compinit; compinit -u' + install_cmd = None class Shell: