Git Product home page Git Product logo

click-completion's People

Contributors

a-detiste avatar anukul avatar epruesse avatar fuegofro avatar genesistms avatar glehmann avatar hemna avatar kbd avatar kianmeng avatar konubinix avatar littlemo avatar marlonrichert avatar segevfiner avatar ssbarnea avatar techalchemy avatar temporaer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

click-completion's Issues

Single function/command with options: no completion

Hi!
I have the following reduced example:

# file: xdummy
import click
import click_completion

click_completion.init()

@click.command()
@click.option('--upper/--lower', default=None, help="Change text to upper or lower case")
def echo(upper):
    click.echo(' foo ')

if __name__ == "__main__":
    echo()

When I try to complete

"xdummy "

(a single space after the name) I do not get any completions.

I would have expected to get "--upper" "--lower", and perhaps "--help" but I do not get anything.
What am I doing wrong?

Clarify whether this repo is deprecated or not

This repo appears to duplicate (and maybe pre-date?) the official Click completion functionality.

Is this the predecessor to that/was that rolled into Click core at some point? If so, it might be good to:

  • Indicate that this is deprecated/rolled into core at the top of the README.
  • Contact the authors of open bugs and PRs on this repo and suggest that they move their issues to Click core if they're still applicable.
  • Maybe archive this repository?

If this is not a dupe of the click core functionality, and is instead an alternative implementation (or internal implementation component of the Click core func), it would be good to indicate that prominently in the README.

Completion for file-paths/directories

Is it possible to do filename completion without having to load all files of a matching folder in the complete method? That strikes me as very expensive if there are a lot of files.

Currently, I have something like:

    def complete(self, ctx, incomplete):

        if incomplete.startswith("/"):
            path_orig = incomplete
        else:
            path_orig = os.path.join(os.getcwd(), incomplete)

        path, file_prefix = path_orig.rsplit("/", 1)

        result = []
        if not path:
            path = "/"

        for filename in os.listdir(path):

            if not file_prefix or filename.startswith(file_prefix):

                file_path = os.path.join(path, filename)
                if os.path.isdir(file_path):
                    filename += "/"

                if incomplete.startswith("/"):
                    result.append(os.path.join(path, filename))
                else:
                    result.append(filename)

        return result

  

This will complete a folder with an appended '/', but also a whitespace, and there's no way to complete on the content of this folder? Am I missing something? Thanks!

Publish "wheel" package in PyPI

I have a kind request to the author here (and happy to help if needed). Currently click-completion only publishes .tar.gz package which forces "building" of the package when installing it. It would be great if we have also the .whl package published (not dependent on platform) so that it can be installed without building the package (and without the need of 'wheel' package to be installed.

That would make it easier to use click-completion for standalone python application installed with pipx for example, because then just having a "bare" python and installing 'click-completion' would work - without having to have wheel package installed.

How to run install command after pip install ?

Question

How to run click_completion.core.install() command after pip install complete installing package?

Expected result

$ pip install my-click-app
#      Installing click app
#      Installing click app completion
#      Done
$ myapp g <TAB> <TAB>
$ myapp g
get    generate    ghost

Current situation

Since I could not find a way to run myapp --completion within pip install, I have to run it manually to enable completion. I'm looking for a way to install completion the setup.py of the project.

Current click app code

#!/usr/bin/env python3
"""CLI App module."""

from typing import Any

import click
import click_completion
from click.core import Context

from .delpoy import deploy
from .download import get
from .generator import gen
from .paths import path


def install_callback(ctx: Context, attr: Any, value: Any) -> None:
    """Shell competion function.

    Args:
        ctx (click.core.Context): Context
        attr: Attribute
        value: Value
    """
    if not value or ctx.resilient_parsing:
        return value
    shell, path = click_completion.core.install()
    click.echo("%s completion installed in %s." % (shell, path))
    click.echo("Use ", nl=False)
    click.secho(f". {path}", fg="green", bold=True, nl=False)
    click.echo(" to activate the completion.")
    exit(0)

click_completion.init()

@click.group()
@click.option(
    "-c",
    "--completion",
    is_flag=True,
    callback=install_callback,
    expose_value=False,
    help="Install completion for the current shell.",
)
def cli():
    """Commnadline Interface."""

cli.add_command(deploy)
cli.add_command(gen)
cli.add_command(path)
cli.add_command(get)

fish completion config fix

I noticed something that may be an error in the documentation.

In your documentation is states to put in ~/.config/fish/completions/foo-bar.fish

eval (_FOO_BAR_COMPLETE=source-fish foo-bar)

First, on my system it appears that ~/.config/fish/completions/ is not loaded in fish. Maybe you are using omf or some other scripts that load that subdir's scripts? I just have a plain fish install and it does not appear to look in the completions subdir (I'm on a mac and installed fish version 2.4.0 using brew) Secondly, the code you listed to load the completions raises following error when I try it:

Unsupported use of '='. To run 'foo-bar' with a modified environment, please use 'env _FOO_BAR_COMPLETE=source-fish foo-bar…' in command substitution

However, everything works if I put the following in ~/.config/fish/config.fish

eval (env _FOO_BAR_COMPLETE =source-fish foo-bar)

So I'm not sure if the documentation should be updated or if there is something weird on my system? Just thought I'd let you know.

Thanks for the nice work on this plugin. Once I made the above changes it works great.

'install_requires' must be a string or list of string

Hello,

I tried installing molecule using pip on centos7 but getting following error:

Collecting click-completion>=0.5.1 (from molecule==3.0a1)
Using cached https://files.pythonhosted.org/packages/77/fd/2d7ec2b86cd4d487abf0b13dce58e98413096c45b9645470be0cb8de6ff2/click-completion-0.5.1.tar.gz
ERROR: Command errored out with exit status 1:
command: /bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-RyPp9J/click-completion/setup.py'"'"'; file='"'"'/tmp/pip-install-RyPp9J/click-completion/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' egg_info --egg-base pip-egg-info
cwd: /tmp/pip-install-RyPp9J/click-completion/
Complete output (1 lines):
error in click-completion setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers
----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output

Any help would be appreciated

Thanks
Afroz Hussain

Not working for options defined for comma separated values

My usecase was to have a option which can take comma separated values
-c val1, val2

I followed what is suggested in stackoverflow

It seems when I use -c tab it doesn't suggest choices for such options. Is there a workaround for such a scenario?

I am testing it on Python 3.7.0 (Mac OS Catalina) and am using pyenv for virtualenv environment.

No completion for choices with whitespace.

Hi there,

Thanks for the fantastic library! 😃 Small bug report: I am encountering some issues with completing arguments that contain whitespace:

@click.command()
@click.option("--foo", type=click.Choice(["Foo Bar", "Foo Qux"]))
def cli(foo):
    print(foo)
λ cli --foo
<TAB>
λ cli --foo Foo\ 
<TAB>
(nothing changes and no options are displayed)

click-completion: 0.5.2
shell: fish

My suspicion was that the .endswith check here could be culprit:

args = split_args(commandline)[1:]
if args and not commandline.endswith(' '):
incomplete = args[-1]
args = args[:-1]
else:
incomplete = ''
I patched split_args to return an (args, incomplete) tuple, but that did not cut it (edit: see below). Given that the changes got rather messy at this point, I stopped here hoping there might be an easier fix. :)

zsh: command not found: #compdef

Apparently click-completion fails under zsh, as I tested with two different tools that use click-completion, molecule and pipenv, and I got similar errors.

pipenv

ssbarnea@imac: ~
$ _PIPENV_COMPLETE=source pipenv                                                                                                                                                                 #compdef pipenv
_pipenv() {
  eval $(env COMMANDLINE="${words[1,$CURRENT]}" _PIPENV_COMPLETE=complete-zsh  pipenv)
}
if [[ "$(basename -- ${(%):-%x})" != "_pipenv" ]]; then
  autoload -U compinit && compinit
  compdef _pipenv pipenv
fi

ssbarnea@imac: ~
$ $(_PIPENV_COMPLETE=source pipenv)                                                                                                                                                              zsh: command not found: #compdef
FAIL: 127

##molecule

ssbarnea@imac: ~
$ _MOLECULE_COMPLETE=source molecule                                                                                                                                                             #compdef molecule
_molecule() {
  eval $(env COMMANDLINE="${words[1,$CURRENT]}" _MOLECULE_COMPLETE=complete-zsh  molecule)
}
if [[ "$(basename -- ${(%):-%x})" != "_molecule" ]]; then
  compdef _molecule molecule

zsh: command not found: ^[[0m#compdef

I can assure that compdef exists:

$ which compdef                                                                                                                                                                                  [10:16:59]
compdef () {
	local opt autol type func delete eval new i ret=0 cmd svc
	local -a match mbegin mend
	emulate -L zsh
	setopt extendedglob
	if (( ! $# ))
	then
		print -u2 "$0: I need arguments"
		return 1
	fi
	while getopts "anpPkKde" opt
	do
		case "$opt" in
			(a) autol=yes  ;;
			(n) new=yes  ;;
			([pPkK]) if [[ -n "$type" ]]
				then
					print -u2 "$0: type already set to $type"
					return 1
				fi
				if [[ "$opt" = p ]]
				then
					type=pattern
				elif [[ "$opt" = P ]]
				then
					type=postpattern
				elif [[ "$opt" = K ]]
				then
					type=widgetkey
				else
					type=key
				fi ;;
			(d) delete=yes  ;;
			(e) eval=yes  ;;
		esac
	done
	shift OPTIND-1
	if (( ! $# ))
	then
		print -u2 "$0: I need arguments"
		return 1
	fi
	if [[ -z "$delete" ]]
	then
		if [[ -z "$eval" ]] && [[ "$1" = *\=* ]]
		then
			while (( $# ))
			do
				if [[ "$1" = *\=* ]]
				then
					cmd="${1%%\=*}"
					svc="${1#*\=}"
					func="$_comps[${_services[(r)$svc]:-$svc}]"
					[[ -n ${_services[$svc]} ]] && svc=${_services[$svc]}
					[[ -z "$func" ]] && func="${${_patcomps[(K)$svc][1]}:-${_postpatcomps[(K)$svc][1]}}"
					if [[ -n "$func" ]]
					then
						_comps[$cmd]="$func"
						_services[$cmd]="$svc"
					else
						print -u2 "$0: unknown command or service: $svc"
						ret=1
					fi
				else
					print -u2 "$0: invalid argument: $1"
					ret=1
				fi
				shift
			done
			return ret
		fi
		func="$1"
		[[ -n "$autol" ]] && autoload -Uz "$func"
		shift
		case "$type" in
			(widgetkey) while [[ -n $1 ]]
				do
					if [[ $# -lt 3 ]]
					then
						print -u2 "$0: compdef -K requires <widget> <comp-widget> <key>"
						return 1
					fi
					[[ $1 = _* ]] || 1="_$1"
					[[ $2 = .* ]] || 2=".$2"
					[[ $2 = .menu-select ]] && zmodload -i zsh/complist
					zle -C "$1" "$2" "$func"
					if [[ -n $new ]]
					then
						bindkey "$3" | IFS=$' \t' read -A opt
						[[ $opt[-1] = undefined-key ]] && bindkey "$3" "$1"
					else
						bindkey "$3" "$1"
					fi
					shift 3
				done ;;
			(key) if [[ $# -lt 2 ]]
				then
					print -u2 "$0: missing keys"
					return 1
				fi
				if [[ $1 = .* ]]
				then
					[[ $1 = .menu-select ]] && zmodload -i zsh/complist
					zle -C "$func" "$1" "$func"
				else
					[[ $1 = menu-select ]] && zmodload -i zsh/complist
					zle -C "$func" ".$1" "$func"
				fi
				shift
				for i
				do
					if [[ -n $new ]]
					then
						bindkey "$i" | IFS=$' \t' read -A opt
						[[ $opt[-1] = undefined-key ]] || continue
					fi
					bindkey "$i" "$func"
				done ;;
			(*) while (( $# ))
				do
					if [[ "$1" = -N ]]
					then
						type=normal
					elif [[ "$1" = -p ]]
					then
						type=pattern
					elif [[ "$1" = -P ]]
					then
						type=postpattern
					else
						case "$type" in
							(pattern) if [[ $1 = (#b)(*)=(*) ]]
								then
									_patcomps[$match[1]]="=$match[2]=$func"
								else
									_patcomps[$1]="$func"
								fi ;;
							(postpattern) if [[ $1 = (#b)(*)=(*) ]]
								then
									_postpatcomps[$match[1]]="=$match[2]=$func"
								else
									_postpatcomps[$1]="$func"
								fi ;;
							(*) if [[ "$1" = *\=* ]]
								then
									cmd="${1%%\=*}"
									svc=yes
								else
									cmd="$1"
									svc=
								fi
								if [[ -z "$new" || -z "${_comps[$1]}" ]]
								then
									_comps[$cmd]="$func"
									[[ -n "$svc" ]] && _services[$cmd]="${1#*\=}"
								fi ;;
						esac
					fi
					shift
				done ;;
		esac
	else
		case "$type" in
			(pattern) unset "_patcomps[$^@]" ;;
			(postpattern) unset "_postpatcomps[$^@]" ;;
			(key) print -u2 "$0: cannot restore key bindings"
				return 1 ;;
			(*) unset "_comps[$^@]" ;;
		esac
	fi
}

Please tag 0.5.0

The 0.5.0 version is released on PyPI but not tagged in git / on GitHub.

Problem with completion

Hi, so in my CLI, I have some callbacks with complex functionality. One of them checks for a specific file in the current directory, and exits with an error printed to sys.stdout. The problem is that the shell tries to evaluate that printed string. I am not sure what this is happening, don't know much about shells and autocompletion. I'm using ZSH, and you can easily replicate this error in one of the examples of this repository.

At examples/click-completion-callback, line 15, add this print statement:

def install_callback(ctx, attr, value):
    print("Hello World")  # add this
    if not value or ctx.resilient_parsing:
        return value
    shell, path = click_completion.core.install()
    click.echo('%s completion installed in %s' % (shell, path))
    exit(0)

If you try to complete this with TAB cli echo <TAB>', it produces this error

cli echo (eval):1: command not found: Hello
(eval):1: command not found: Hello
(eval):1: command not found: Hello
cli

Install fails when running PowerShell from emulated terminal cmder

First of all, thank you for this library - it's great.

When running PowerShell, cmder by default invoke's the shell with a few parameters:

*PowerShell -ExecutionPolicy Bypass -NoLogo -NoProfile -NoExit -Command "Invoke-Expression '. ''%ConEmuDir%\..\profile.ps1'''"

(these can be found in the cmder Settings)

These parameters affect click-completion install a couple of ways:

  1. The above command sets the ExecutionPolicy on the Process scope to Bypass. When click-completion's install command runs, it tries to set the ExecutionPolicy to Unrestricted on the CurrentUser scope. We end up with this:
Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more
specific scope.  Due to the override, your shell will retain its current effective execution policy of Bypass. Type "Get-ExecutionPolicy -List" to
view your execution policy settings. For more information please see "Get-Help Set-ExecutionPolicy".
At line:1 char:1
+ Set-ExecutionPolicy Unrestricted -Scope CurrentUser
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException
    + FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand
Traceback (most recent call last):

...
  File "c:\code\click-completion\click_completion\core.py", line 353, in install
    subprocess.check_call(['powershell', 'Set-ExecutionPolicy Unrestricted -Scope CurrentUser'])
  File "c:\users\pstephenson.aa\appdata\local\programs\python\python37-32\lib\subprocess.py", line 328, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['powershell', 'Set-ExecutionPolicy Unrestricted -Scope CurrentUser']' returned non-zero exit status 1.
  1. cmder also defines its own user_profile.ps1 file that, by default, does not load the PowerShell profile defined in $profile. This has been noted in some GitHub issues, but it's also relevant for this project because it means that while the completion code gets added to the $profile file, you won't get the expected behavior without dot sourcing $profile each time you load a new cmder window.

I am happy to submit some documentation for cmder users to look out for these things. However, I wanted to ask your thoughts on the first issue: One thing to consider might be to before setting the execution policy, you could first check the execution policy on the Process scope to see if it's anything other than Undefined or Unrestricted: https://github.com/click-contrib/click-completion/blob/master/click_completion/core.py#L353. If that is the case, maybe we throw an exception and display a helpful error message to the user indicating the issue? What are your thoughts?

psutil remains should be removed

psutil is a soft-dependency of click-completion so it must be listed as an setup.cfg/setup.py extra, so users that want this functionality can install the package with extra.

Also the fact that psutil is not even listed it also means that is not tested, so users would never know which version range is safe to use.

zsh completion with "inner" substrings

I have a Choice option with the following values: "kotlin-rest-spring-boot-local", "kotlin-rest-spring-boot", "java-rest-spring-boot"

@click.option('--template', "template_key", type=click.Choice(["kotlin-rest-spring-boot-local", "kotlin-rest-spring-boot", "java-rest-spring-boot"]))
def create(template_key=None):
    pass

when I hit 'tab'for the first time at

compdummy --template <tab>

I get

compdummy --template -rest-spring

because '-rest-spring' is a common substring. Hitting 'tab' again, nothing happens because:

def choice_complete(self, ctx, incomplete):
    return [c for c in self.choices if c.startswith(incomplete)]

only checks for 'startswith'.

If I replace the above code with:

def choice_complete(self, ctx, incomplete):
    return [c for c in self.choices if incomplete in c]

everything works fine

Click's completion system has been rewritten

See pallets/click#1484 and pallets/click#1622. The documentation can be found here for now: https://click.palletsprojects.com/en/8.0.x/shell-completion/. In the new system:

  • Each shell can provide completion is a completely different way if needed.
  • It's possible to register support for other shells.
  • Every core object (command, group, chained group, argument, option, type) provides a shell_complete method that provides completions at that level and can be overridden. Parameters additionally accept a shell_complete function in __init__ to override or extend the type's completion.
  • Values for choice, file, path, and directories are completed. Path support is handled by the shell rather than emulated in Click.
  • Arbitrary metadata can be attached to completions, which shell support could use however it likes in the completion script.

However, Click doesn't provide these features:

  • Built-in PowerShell support. This could be added to Click, but my preference right now is for an extension to provide other shell support.
  • An install command. This is probably out of scope for Click.
  • Shell detection. This is out of scope for Click since it relies on an external dependency. I didn't consider implementing it because the method for loading the completion differs between shells anyway, so it's not any extra work to add the shell to the instruction.

Due to all these changes, the click-completion won't work with the next release of Click. We've talked about merging this project into Click before, but I think we pretty much have what we want in core at this point. One option is to make a release that specifies click<8 in install_requires, then have the next version specify click>=8 and continue to support the parts that Click doesn't provide.

cannot get powershell completion not working

I tried following the example, but I am unable to get click-completion working with powershell. I could not get the example scripts to work, because they are not directly executable in powershell. Is there a simple example for powershell that I can follow? (By the way, completion seems to be activated but just not working. When I enter a tab after my command, the help text gets inserted but the commands are not selected and completed correctly.)

Error when loading completion from zsh

Under zsh, you run the following code:

if [[ "$(basename ${(%):-%x})" != "..." ]]; then

Under a login shell, the shell executable begins with a dash (eg. '-zsh'), so basename fails with:

$ eval "$(pipenv --completion)"
basename: illegal option -- z
usage: basename string [suffix]
       basename [-a] [-s suffix] string [...]

(pipenv uses click_completion internally.) To fix this, you can do:

basename -- ${(%):-%x}

Adding -- stops anything starting with - from being parsed as an argument.

setup.py relies on old-style extras syntax

This isn't a huge deal, but the format of conditional dependency declaration has changed somewhat (I am in the process of updating our vendored dependencies in pipenv which is why I caught this)

Before:

    install_requires=[
        'click',
        'jinja2',
        'six',
        'shellingham',
    ],
    extras_require={
        ":python_version < '3'": ["enum34"],
},

After:

    install_requires=[
        'click',
        'jinja2',
        'six',
        'shellingham',
        'enum34; python_version<"3"'
    ],

click 8.0 compatible code?

I just asked the click folks if they had a mechanism for automatically showing the shell completion code and installing it, like click-completion has. They said there are no plans to add any mechanism for it. Sad. You can see the issue here:
pallets/click#2127

Is there an update to click-completion that outputs click 8.0 compatible shell completion eval code that works?
I'm using click 8.0.3 and the completion code generated doesn't work.

Here is a sample

└─> aprsd completion show
#compdef aprsd
_aprsd() {
  eval $(env COMMANDLINE="${words[1,$CURRENT]}" _APRSD_COMPLETE=complete-zsh  aprsd)
}
if [[ "$(basename -- ${(%):-%x})" != "_aprsd" ]]; then
  compdef _aprsd aprsd
fi
╭─aprsd on  master [$!?] via 🐍 v3.8.5 (.venv) ❯
└─> aprsd completion install
zsh completion installed in /Users/i530566/.zshrc

Unfortunately that doesn't work with click 8.0.
I updated the code in my ~/.zshrc

eval "$(_APRSD_COMPLETE=zsh_source aprsd)"

and that works.

No support for PowerShell 7 (PowerShell Core)

> python examples\click-completion-command install
Error: pwsh is not supported.
> powershell
Windows PowerShell
[...]
PS > python examples\click-completion-command install
powershell completion installed in b'C:\\Users\\thorsten\\Documents\\WindowsPowerShell\\Microsoft.PowerShell_profile.ps1'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.