Skip to content

Commit 3c8880e

Browse files
authored
Merge pull request #459 from python-cmd2/argcomplete_example
Example added demonstrating bash completion bridging argcomplete with AutoCompleter
2 parents 000ae62 + ea65617 commit 3c8880e

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

examples/bash_completion.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python3
2+
# coding=utf-8
3+
# PYTHON_ARGCOMPLETE_OK - This is required at the beginning of the file to enable argcomplete support
4+
"""A simple example demonstrating integration with argcomplete.
5+
6+
This example demonstrates how to achieve automatic auto-completion of argparse arguments for a command-line utility
7+
(CLU) in the Bash shell.
8+
9+
Realistically it will probably only work on Linux and then only in a Bash shell. With some effort you can probably get
10+
it to work on macOS or Windows Subsystem for Linux (WSL); but then again, specifically within a Bash shell. This
11+
automatic Bash completion integration with the argcomplete module is included within cmd2 in order to assist developers
12+
with providing a the best possible out-of-the-box experience with their cmd2 applications, which in many cases will
13+
accept argparse arguments on the command-line when executed. But from an architectural point of view, the
14+
"argcomplete_bridge" functionality within cmd2 doesn't really depend on the rest of cmd2 and could be used in your own
15+
CLU which doesn't use cmd2.
16+
17+
WARNING: For this example to work correctly you need the argcomplete module installed and activated:
18+
pip install argcomplete
19+
activate-global-python-argcomplete
20+
Please see https://github.com/kislyuk/argcomplete for more information on argcomplete.
21+
"""
22+
import argparse
23+
24+
optional_strs = ['Apple', 'Banana', 'Cranberry', 'Durian', 'Elderberry']
25+
26+
bash_parser = argparse.ArgumentParser(prog='base')
27+
28+
bash_parser.add_argument('option', choices=['load', 'export', 'reload'])
29+
30+
bash_parser.add_argument('-u', '--user', help='User name')
31+
bash_parser.add_argument('-p', '--passwd', help='Password')
32+
33+
input_file = bash_parser.add_argument('-f', '--file', type=str, help='Input File')
34+
35+
if __name__ == '__main__':
36+
from cmd2.argcomplete_bridge import bash_complete
37+
# bash_complete flags this argument telling AutoCompleter to yield to bash to perform
38+
# tab completion of a file path
39+
bash_complete(input_file)
40+
41+
flag_opt = bash_parser.add_argument('-o', '--optional', help='Optional flag with choices')
42+
setattr(flag_opt, 'arg_choices', optional_strs)
43+
44+
# Handle bash completion if it's installed
45+
# This early check allows the script to bail out early to provide tab-completion results
46+
# to the argcomplete library. Putting this at the end of the file would cause the full application
47+
# to load fulfill every tab-completion request coming from bash. This can cause a notable delay
48+
# on the bash prompt.
49+
try:
50+
# only move forward if we can import CompletionFinder and AutoCompleter
51+
from cmd2.argcomplete_bridge import CompletionFinder
52+
from cmd2.argparse_completer import AutoCompleter
53+
import sys
54+
if __name__ == '__main__':
55+
completer = CompletionFinder()
56+
57+
# completer will return results to argcomplete and exit the script
58+
completer(bash_parser, AutoCompleter(bash_parser))
59+
except ImportError:
60+
pass
61+
62+
# Intentionally below the bash completion code to reduce tab completion lag
63+
import cmd2
64+
65+
66+
class DummyApp(cmd2.Cmd):
67+
"""
68+
Dummy cmd2 app
69+
"""
70+
71+
def __init__(self):
72+
super().__init__()
73+
74+
75+
if __name__ == '__main__':
76+
args = bash_parser.parse_args()
77+
78+
# demonstrates some handling of the command line parameters
79+
80+
if args.user is None:
81+
user = input('Username: ')
82+
else:
83+
user = args.user
84+
85+
if args.passwd is None:
86+
import getpass
87+
password = getpass.getpass()
88+
else:
89+
password = args.passwd
90+
91+
if args.file is not None:
92+
print('Loading file: {}'.format(args.file))
93+
94+
# Clear the argumentns so cmd2 doesn't try to parse them
95+
sys.argv = sys.argv[:1]
96+
97+
app = DummyApp()
98+
app.cmdloop()

0 commit comments

Comments
 (0)