Skip to content

Commit

Permalink
Fix #608
Browse files Browse the repository at this point in the history
  • Loading branch information
Freed-Wu authored and jaraco committed Dec 18, 2022
1 parent 5a263f3 commit 40af6de
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
29 changes: 29 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,35 @@ package, suitable for invoking from Python like so::
$ python -m keyring get system username
password

If you install keyring by ``pip install 'keyring[completion]'``, you can
generate shell completions by:

keyring --print-completion bash | sudo tee /usr/share/bash-completion/compleitons/keyring
keyring --print-completion zsh | sudo tee /usr/share/zsh/site-functions/_keyring
keyring --print-completion tcsh | sudo tee /etc/profile.d/keyring.csh

**Note**: the path of `/usr/share` is only for GNU/Linux mostly. If you use other OSs,
try:

- macOS, GUN/Linux (Homebrew): /usr/local/share
- Android (Termux): /data/data/com.termux/files/usr/share
- Windows (mingw64 of msys2): /mingw64/share
- ...

If you install keyring by your package manager (apt, pacman, nix, homebrew, etc),
these shell completions should have been packaged and you don't need generate
them by yourself.

After install shell completions, you can enable shell completions by:

- bash: install [bash-completion](https://github.com/scop/bash-completion), and
``. /usr/share/bash-completion/bash_completion`` in your bashrc.
- zsh: ``autoload -Uz compinit && compinit`` in your zshrc, and
``grep -w keyring ~/.zcompdump`` to check if it is installed correctly:

$ grep -w keyring ~/.zcompdump
'keyring' '_keyring'

Configuring
===========

Expand Down
24 changes: 24 additions & 0 deletions keyring/_shtab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from argparse import Action

FILE = None
DIRECTORY = DIR = None


class _PrintCompletionAction(Action):
"""Print completion action."""

def __call__(self, parser, namespace, values, option_string):
print("Please install shtab firstly!")
parser.exit(0)


def add_argument_to(parser, *args, **kwargs):
"""Add completion argument to parser."""
Action.complete = None # type: ignore
parser.add_argument(
"--print-completion",
choices=["bash", "zsh", "tcsh"],
action=_PrintCompletionAction,
help="print shell completion script",
)
return parser
29 changes: 27 additions & 2 deletions keyring/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,49 @@
from . import backend
from . import set_keyring, get_password, set_password, delete_password

try:
import shtab
except ImportError:
from . import _shtab as shtab

# it completes keyring backends for `keyring -b` by the output of `keyring --list-backends`
# % keyring -b <TAB>
# keyring priority
# keyring.backends.chainer.ChainerBackend 10
# keyring.backends.fail.Keyring 0
# ... ...
PREAMBLE = {
"zsh": r"""
keyring_complete() {
local line
while read -r line; do
choices+=(${${line/ \(priority: /\\\\:}/)/})
done <<< "$($words[1] --list-backends)"
_arguments "*:keyring priority:(($choices))"
}
"""
}
KEYRING_COMPLETE = {"zsh": "keyring_complete"}


class CommandLineTool:
def __init__(self):
self.parser = argparse.ArgumentParser()
shtab.add_argument_to(self.parser, preamble=PREAMBLE)
self.parser.add_argument(
"-p",
"--keyring-path",
dest="keyring_path",
default=None,
help="Path to the keyring backend",
)
).complete = shtab.DIR
self.parser.add_argument(
"-b",
"--keyring-backend",
dest="keyring_backend",
default=None,
help="Name of the keyring backend",
)
).complete = KEYRING_COMPLETE
self.parser.add_argument(
"--list-backends",
action="store_true",
Expand Down
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ docs =

# local

completion =
# upstream
shtab

[options.entry_points]
console_scripts =
keyring=keyring.cli:main
Expand Down

0 comments on commit 40af6de

Please sign in to comment.