-
Notifications
You must be signed in to change notification settings - Fork 394
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
blog: shtab completion #1505
Merged
Merged
blog: shtab completion #1505
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
07858bb
blog: shtab-complete
casperdcl 6b5b810
misc review content updates
casperdcl 433e1a9
deployment requirements
casperdcl 66bd42b
add picture
casperdcl f86125e
minor typo, fix indentation
casperdcl 77de607
gif and example with dvc
casperdcl e578d97
render gif
casperdcl 46a5bfa
add comic xkcd#1205
casperdcl 3caf666
improve gif quality
casperdcl 02b38a5
Fix support for image-less blog posts
rogermparent d282fce
misc review updates
casperdcl d93a9c4
more review comments
casperdcl 7d32fe0
fix GIF
casperdcl 20707ec
minor links
casperdcl 622fd79
add old commit churn link
casperdcl a3b4c76
add key usage image
casperdcl db6d923
attempt image frontmatter & sizing
casperdcl 219f9d3
image sizing and new post image
casperdcl 0771b4d
fix captions
casperdcl 071cde0
annotate key frequency image
casperdcl d16ad48
fix captions
casperdcl 79f33c9
Merge remote-tracking branch 'origin/master' into shtab-complete
casperdcl 531c72d
update dates and lengthen URL
casperdcl d4d3044
comments URL and tags
casperdcl File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
--- | ||
name: Casper da Costa-Luis | ||
avatar: casper_dcl.jpg | ||
links: | ||
- https://github.com/casperdcl | ||
--- | ||
|
||
Computational Physicist; Python Software Foundation (PSF) voting member; GitHub | ||
OS maintainers member. [tqdm](https://github.com/tqdm/tqdm) primary maintainer. | ||
|
||
Expertise in C++/CUDA/Python/Git/Docker. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
--- | ||
title: '(Tab) Complete Any Python Application in 1 Minute or Less' | ||
date: 2020-07-27 | ||
description: | | ||
We've made a painless tab-completion script generator for Python applications! | ||
Find out how to take advantage of it in this blog post. | ||
|
||
descriptionLong: | | ||
We've made a painless tab-completion script generator for Python applications! | ||
It's called `shtab` and it currently works with `argparse`, `docopt`, and | ||
`argopt` to produce `bash` and `zsh` completion scripts. | ||
This tool was originally created to help `dvc`, but we realised it could be made | ||
more generic and valuable to the world's entire ecosystem of Python CLI | ||
applications. Find out how to take advantage of it in this blog post. | ||
picture: 2020-07-27/tab-py.jpg | ||
pictureComment: Zero Effort Tab Completion for Python Applications | ||
author: casper_dcl | ||
commentsUrl: https://discuss.dvc.org/t/tab-complete-any-python-application-in-1-minute-or-less/455 | ||
tags: | ||
- shtab | ||
- Release | ||
- CLI | ||
- Autocomplete | ||
- Tab | ||
- Completion | ||
--- | ||
|
||
Command line tools are powerful. Things like [`make`] have manual pages | ||
spanning, well, | ||
[pages](https://www.gnu.org/software/make/manual/make.html#Options-Summary), | ||
while just the list of [`git`] subcommands is longer than can fit on a standard | ||
`80 x 24` terminal screen. | ||
|
||
```dvc | ||
$ git <TAB> | ||
add filter-branch rebase | ||
am format-patch reflog | ||
annotate fsck relink | ||
... | ||
describe prco unassume | ||
--More-- | ||
``` | ||
|
||
Notice the `--More--` at the bottom? That's the joy of pagination. | ||
|
||
Notice the `<TAB>` at the top? That represents actually pressing the tab key. | ||
Ah, the joy of shell tab completion. | ||
|
||
Tab completion is an indispensable part of writing anything on the command-line. | ||
Personally, I can't imaging trying to `git co` (aliased to `git checkout`) a | ||
branch without `<TAB>` to do the heavy lifting. | ||
[They say](https://en.wikipedia.org/wiki/Letter_frequency) "E" is the most | ||
common vowel, and "T" the most common consonant. My keyboard use probably looks | ||
more like this: | ||
|
||
![](/uploads/images/2020-07-27/key-frequencies.png 'Yes, I use vim =500')_My key | ||
usage_ | ||
|
||
Now there's a tool called `dvc` which is like [Git for data](https://dvc.org). | ||
It can be viewed as a cross-platform combination of [`git`] and [`make`] | ||
designed for handling big data and multiple cloud storage repositories, as well | ||
as tracking machine learning experiments. As you can imagine, supporting that | ||
many buzzwords means it also has a large number of subcommands and options. | ||
|
||
_Every time a new feature is added, maintainers and contributors have to update | ||
tab completion scripts for multiple supported shells. At best, it's a pain, and | ||
at worst, error-prone. If you've worked on maintaining CLI applications, you'll | ||
sympathise._ | ||
|
||
Surely the parser code you've written is informative enough to automate tab | ||
completion? Surely you shouldn't have to maintain and synchronise separate tab | ||
completion scripts? | ||
|
||
Good news: [`shtab`] is a new tool which magically does all of this work. | ||
|
||
Any Python CLI application using [`argparse`], [`docopt`], or [`argopt`] can | ||
have tab completion for free! | ||
|
||
Simply hand your parser object to `shtab` (either via the CLI or the Python | ||
API), and a tab completion script will be generated for your preferred shell. | ||
It's as easy as: | ||
|
||
- CLI: `shtab --shell=bash myprogram.main.parser`, or | ||
- Python API: `import shtab; print(shtab.complete(parser, shell="bash"))`. | ||
|
||
### `argparse` example | ||
|
||
Suppose you have some code in a module `hello.main`: | ||
|
||
```python | ||
import argparse | ||
|
||
def get_main_parser(): | ||
parser = argparse.ArgumentParser(prog="hello") | ||
parser.add_argument( | ||
"who", help="good question", nargs="?", default="world") | ||
parser.add_argument( | ||
"--what", help="a better question", default="hello", | ||
choices=["hello", "goodbye"]) | ||
return parser | ||
|
||
if __name__ == "__main__": | ||
parser = get_main_parser() | ||
args = parser.parse_args() | ||
print("{}, {}!".format(args.what, args.who)) | ||
``` | ||
|
||
To get tab completion for `bash`, simply install [`shtab`] and then run: | ||
|
||
```bash | ||
shtab --shell=bash hello.main.get_main_parser \ | ||
| sudo tee "$BASH_COMPLETION_COMPAT_DIR"/hello >/dev/null | ||
``` | ||
|
||
Zsh user? Not a problem. Simply run: | ||
|
||
```bash | ||
shtab --shell=zsh hello.main.get_main_parser \ | ||
| sudo tee /usr/local/share/zsh/site-functions/_hello >/dev/null | ||
# note the underscore `_` prefix in the filename | ||
``` | ||
|
||
Handily you can install `shtab`'s own completions by following the above | ||
examples replacing `hello` with `shtab`. | ||
|
||
![](/uploads/images/2020-07-27/dvc.gif)_`shtab`-driven `dvc` completion in | ||
`bash` and `zsh`_ | ||
|
||
Using `shtab`, here's what | ||
[`dvc`'s completion](https://dvc.org/doc/install/completion) looks like when | ||
installed: | ||
|
||
```dvc | ||
% dvc <TAB> | ||
Completing dvc commands | ||
add -- Track data files or directories with DVC. | ||
cache -- Manage cache settings. | ||
checkout -- Checkout data files from cache. | ||
commit -- Save changed data to cache and update DVC-files. | ||
completion -- Prints out shell tab completion scripts. | ||
At Top: Hit TAB for more, or the character to insert | ||
``` | ||
|
||
All completion suggestions guaranteed in-sync with the code! The maintainers of | ||
`dvc` were very surprised to find no less than | ||
[84 commits](https://github.com/iterative/dvc/commits/master/scripts/completion) | ||
touching their old completion scripts. Such churn is now a thing of the past! | ||
|
||
You might notice one of the subcommands provided by `dvc` is | ||
[`completion`](https://dvc.org/doc/install/completion). Here's a quick example | ||
of how to provide such convenience for users: | ||
|
||
### Integrating library example | ||
|
||
Feeling minimal? How about adding `import shtab` to your application itself for | ||
a cleaner user interface? And let's use [`argopt`] to convert [`docopt`]'s neat | ||
syntax to `argparse` while we're at it. | ||
|
||
```python | ||
"""Greetings and partings. | ||
|
||
Usage: | ||
greeter [options] [<you>] [<me>] | ||
|
||
Options: | ||
-g, --goodbye : Say "goodbye" (instead of "hello") | ||
-b, --print-bash-completion : Output a bash tab-completion script | ||
-z, --print-zsh-completion : Output a zsh tab-completion script | ||
|
||
Arguments: | ||
<you> : Your name [default: Anon] | ||
<me> : My name [default: Casper] | ||
""" | ||
import sys, argopt, shtab | ||
|
||
parser = argopt.argopt(__doc__) | ||
if __name__ == "__main__": | ||
args = parser.parse_args() | ||
if args.print_bash_completion: | ||
print(shtab.complete(parser, shell="bash")) | ||
sys.exit(0) | ||
if args.print_zsh_completion: | ||
print(shtab.complete(parser, shell="zsh")) | ||
sys.exit(0) | ||
|
||
msg = "k thx bai!" if args.goodbye else "hai!" | ||
print("{} says '{}' to {}".format(args.me, msg, args.you)) | ||
``` | ||
|
||
### Try it out | ||
|
||
There are many more options and features. The [documentation][`shtab`] includes | ||
examples of working with custom file completions and providing a `completion` | ||
subcommand when integrating more tightly with existing applications. | ||
|
||
Try it out with `pip install -U shtab` or `conda install -c conda-forge shtab`! | ||
|
||
Is it worth the time? | ||
|
||
![](https://imgs.xkcd.com/comics/is_it_worth_the_time.png)_It's worth it | ||
[xkcd#1205](https://xkcd.com/1205)_ | ||
|
||
[`shtab`] would be on the second row, far left (maybe even off grid). It's worth | ||
spending days to get right yet only takes seconds to install. | ||
|
||
[`argopt`]: https://pypi.org/project/argopt | ||
[`argparse`]: https://docs.python.org/library/argparse | ||
[`docopt`]: https://pypi.org/project/docopt | ||
[`dvc`]: https://github.com/iterative/dvc | ||
[`git`]: https://git-scm.com | ||
[`make`]: https://en.wikipedia.org/wiki/Make_(software) | ||
[`shtab`]: https://github.com/iterative/shtab |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We forgot to review these. Probably too many @shcheklein @casperdcl ? I'd only keep
Release
and maybeshtab
because no other tag has any posts. Would maybe addCLI
if it's added retroactively to a few others.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to see all current tags?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering the same thing: #1657
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorgeorpinel @casperdcl //cc @elleobrien - tags serve two goals - navigation (and we want to keep them sane for this), and SEO (keywords in meta - I haven't checked this, but I hope it still works or we need to fix this). For SEO we want to include things that people will use to search - "Python CLI autocomplete", etc. Thus we need to have a good balance. No need to optimize tags just for the sake of trying to keep them to the minimum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK in that case all tags here seem relevant, for SEO that is. Though I should say, I think most search engines pretty much ignore suggested meta keywords and extract them from the content instead. But if the meta keywords match the content, then it may be a nice extra.