Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completion for file-paths/directories #6

Closed
makkus opened this issue Mar 26, 2018 · 3 comments
Closed

Completion for file-paths/directories #6

makkus opened this issue Mar 26, 2018 · 3 comments

Comments

@makkus
Copy link

makkus commented Mar 26, 2018

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!

@glehmann
Copy link
Collaborator

glehmann commented Apr 5, 2018

I don't think there is currently a great way to do that. That definitely something that would be nice, if someone wants to give it a try!

For now, in our private application, we are completing with both the directory name and the directory name with a trailing slash:

$ myapp d<tab>
dir1
dir1/
dir2
dir2/

because there are two entries that begin exactly the same, the completion is done up to the full dir name, without the slash, and without space, so it is possilbe to continue the completion process.
Obviously the drawback is that the completion list is polluted by twice the amount of entries…

@makkus
Copy link
Author

makkus commented Apr 6, 2018

Ah, nice workaround, thanks! Will use that for now.

@makkus makkus closed this as completed Apr 6, 2018
@flokno
Copy link

flokno commented Jul 4, 2019

Hi @makkus and @glehmann , could you give a more complete example on how def complete .. is used to perform filename completion?

I use the fish shell and the autocompletion is currently useless to me since filenames are not completed :/

p.s. It seems that

from glob import glob
import click

complete_filenames = click.Choice(glob("**", recursive=True))

...
@click.argument("filename", type=complete_filenames)
...

does the job for me. Anyway if you have other suggestions, please let me know. Thanks!

p.p.s it does only when the directory tree is too large.

p.p.p.s this seems to be sufficient and doesn't require glob or anything:

complete_filenames = click.Path(exists=True)

p.p.p.p.s. only on fish 2.2.0 though, I noticed. I tried to understand changes in the fish completion API after 2.2.0, but did not come too far until now. Any ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants